demo dashboard using new system, including optional accounts
|
|
@ -15,6 +15,6 @@ jobs:
|
|||
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa
|
||||
ssh-keyscan -H ${{ secrets.SSH_HOST }} > ~/.ssh/known_hosts
|
||||
- name: connect and pull
|
||||
run: ssh ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} "cd ${{ secrets.SSH_WORK_DIR }} && git pull && docker compose up -d --build && exit"
|
||||
run: ssh ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} "cd /home/ubuntu/VEL-Connect-PB/velconnect && git pull && docker compose up -d --build --remove-orphans && exit"
|
||||
- name: cleanup
|
||||
run: rm -rf ~/.ssh
|
||||
|
|
|
|||
|
|
@ -1,21 +0,0 @@
|
|||
# build output
|
||||
dist/
|
||||
# generated types
|
||||
.astro/
|
||||
|
||||
# dependencies
|
||||
node_modules/
|
||||
|
||||
# logs
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
|
||||
|
||||
# environment variables
|
||||
.env
|
||||
.env.production
|
||||
|
||||
# macOS-specific files
|
||||
.DS_Store
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
"recommendations": ["astro-build.astro-vscode"],
|
||||
"unwantedRecommendations": []
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"command": "./node_modules/.bin/astro dev",
|
||||
"name": "Development server",
|
||||
"request": "launch",
|
||||
"type": "node-terminal"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
# Astro Starter Kit: Minimal
|
||||
|
||||
```
|
||||
npm create astro@latest -- --template minimal
|
||||
```
|
||||
|
||||
[](https://stackblitz.com/github/withastro/astro/tree/latest/examples/minimal)
|
||||
[](https://codesandbox.io/p/sandbox/github/withastro/astro/tree/latest/examples/minimal)
|
||||
[](https://codespaces.new/withastro/astro?devcontainer_path=.devcontainer/minimal/devcontainer.json)
|
||||
|
||||
> 🧑🚀 **Seasoned astronaut?** Delete this file. Have fun!
|
||||
|
||||
## 🚀 Project Structure
|
||||
|
||||
Inside of your Astro project, you'll see the following folders and files:
|
||||
|
||||
```
|
||||
/
|
||||
├── public/
|
||||
├── src/
|
||||
│ └── pages/
|
||||
│ └── index.astro
|
||||
└── package.json
|
||||
```
|
||||
|
||||
Astro looks for `.astro` or `.md` files in the `src/pages/` directory. Each page is exposed as a route based on its file name.
|
||||
|
||||
There's nothing special about `src/components/`, but that's where we like to put any Astro/React/Vue/Svelte/Preact components.
|
||||
|
||||
Any static assets, like images, can be placed in the `public/` directory.
|
||||
|
||||
## 🧞 Commands
|
||||
|
||||
All commands are run from the root of the project, from a terminal:
|
||||
|
||||
| Command | Action |
|
||||
| :------------------------ | :----------------------------------------------- |
|
||||
| `npm install` | Installs dependencies |
|
||||
| `npm run dev` | Starts local dev server at `localhost:3000` |
|
||||
| `npm run build` | Build your production site to `./dist/` |
|
||||
| `npm run preview` | Preview your build locally, before deploying |
|
||||
| `npm run astro ...` | Run CLI commands like `astro add`, `astro check` |
|
||||
| `npm run astro -- --help` | Get help using the Astro CLI |
|
||||
|
||||
## 👀 Want to learn more?
|
||||
|
||||
Feel free to check [our documentation](https://docs.astro.build) or jump into our [Discord server](https://astro.build/chat).
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
import { defineConfig } from 'astro/config';
|
||||
|
||||
// https://astro.build/config
|
||||
export default defineConfig({});
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
{
|
||||
"name": "",
|
||||
"type": "module",
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"dev": "astro dev",
|
||||
"start": "astro dev",
|
||||
"build": "astro build",
|
||||
"preview": "astro preview",
|
||||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"astro": "^2.8.0"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 128 128">
|
||||
<path d="M50.4 78.5a75.1 75.1 0 0 0-28.5 6.9l24.2-65.7c.7-2 1.9-3.2 3.4-3.2h29c1.5 0 2.7 1.2 3.4 3.2l24.2 65.7s-11.6-7-28.5-7L67 45.5c-.4-1.7-1.6-2.8-2.9-2.8-1.3 0-2.5 1.1-2.9 2.7L50.4 78.5Zm-1.1 28.2Zm-4.2-20.2c-2 6.6-.6 15.8 4.2 20.2a17.5 17.5 0 0 1 .2-.7 5.5 5.5 0 0 1 5.7-4.5c2.8.1 4.3 1.5 4.7 4.7.2 1.1.2 2.3.2 3.5v.4c0 2.7.7 5.2 2.2 7.4a13 13 0 0 0 5.7 4.9v-.3l-.2-.3c-1.8-5.6-.5-9.5 4.4-12.8l1.5-1a73 73 0 0 0 3.2-2.2 16 16 0 0 0 6.8-11.4c.3-2 .1-4-.6-6l-.8.6-1.6 1a37 37 0 0 1-22.4 2.7c-5-.7-9.7-2-13.2-6.2Z" />
|
||||
<style>
|
||||
path { fill: #000; }
|
||||
@media (prefers-color-scheme: dark) {
|
||||
path { fill: #FFF; }
|
||||
}
|
||||
</style>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 749 B |
|
|
@ -1 +0,0 @@
|
|||
/// <reference types="astro/client" />
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
---
|
||||
---
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<meta name="generator" content={Astro.generator} />
|
||||
<title>Astro</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Astro</h1>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
{
|
||||
"extends": "astro/tsconfigs/strict"
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
.DS_Store
|
||||
node_modules
|
||||
/build
|
||||
/.svelte-kit
|
||||
/package
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
|
||||
# Ignore files for PNPM, NPM and YARN
|
||||
pnpm-lock.yaml
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
module.exports = {
|
||||
root: true,
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'plugin:svelte/recommended',
|
||||
'prettier'
|
||||
],
|
||||
parser: '@typescript-eslint/parser',
|
||||
plugins: ['@typescript-eslint'],
|
||||
parserOptions: {
|
||||
sourceType: 'module',
|
||||
ecmaVersion: 2020,
|
||||
extraFileExtensions: ['.svelte']
|
||||
},
|
||||
env: {
|
||||
browser: true,
|
||||
es2017: true,
|
||||
node: true
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: ['*.svelte'],
|
||||
parser: 'svelte-eslint-parser',
|
||||
parserOptions: {
|
||||
parser: '@typescript-eslint/parser'
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
.DS_Store
|
||||
node_modules
|
||||
/build
|
||||
/.svelte-kit
|
||||
/package
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
vite.config.js.timestamp-*
|
||||
vite.config.ts.timestamp-*
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
engine-strict=true
|
||||
resolution-mode=highest
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
.DS_Store
|
||||
node_modules
|
||||
/build
|
||||
/.svelte-kit
|
||||
/package
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
|
||||
# Ignore files for PNPM, NPM and YARN
|
||||
pnpm-lock.yaml
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"useTabs": true,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "none",
|
||||
"printWidth": 100,
|
||||
"plugins": ["prettier-plugin-svelte"],
|
||||
"pluginSearchDirs": ["."],
|
||||
"overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }]
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"configurations": [
|
||||
{
|
||||
"command": "npm run dev",
|
||||
"name": "Run npm start",
|
||||
"request": "launch",
|
||||
"type": "node-terminal"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
{
|
||||
"name": "example-dashboard",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vite dev",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview",
|
||||
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
||||
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
||||
"lint": "prettier --plugin-search-dir . --check . && eslint .",
|
||||
"format": "prettier --plugin-search-dir . --write ."
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sveltejs/adapter-auto": "^2.0.0",
|
||||
"@sveltejs/kit": "^1.20.4",
|
||||
"@typescript-eslint/eslint-plugin": "^5.45.0",
|
||||
"@typescript-eslint/parser": "^5.45.0",
|
||||
"eslint": "^8.28.0",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-plugin-svelte": "^2.30.0",
|
||||
"prettier": "^2.8.0",
|
||||
"prettier-plugin-svelte": "^2.10.1",
|
||||
"svelte": "^4.0.0",
|
||||
"svelte-check": "^3.4.3",
|
||||
"svelte-preprocess": "^5.0.4",
|
||||
"tslib": "^2.4.1",
|
||||
"typescript": "^5.0.0",
|
||||
"vite": "^4.3.6",
|
||||
"sass": "^1.63.6"
|
||||
},
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"pocketbase": "^0.15.2"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
// See https://kit.svelte.dev/docs/types#app
|
||||
// for information about these interfaces
|
||||
declare global {
|
||||
namespace App {
|
||||
// interface Error {}
|
||||
// interface Locals {}
|
||||
// interface PageData {}
|
||||
// interface Platform {}
|
||||
}
|
||||
}
|
||||
|
||||
export {};
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
%sveltekit.head%
|
||||
</head>
|
||||
<body data-sveltekit-preload-data="hover">
|
||||
<div style="display: contents">%sveltekit.body%</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
/* Write your global styles here, in SCSS syntax. Variables and mixins from the src/variables.scss file are available here without importing */
|
||||
$color-blossom: #bc1f2d;
|
||||
$color-fade: #be434d;
|
||||
|
||||
$color-bg: #1a1a1a;
|
||||
$color-bg-alt: #333;
|
||||
|
||||
/* $color-text: #dedce5; */
|
||||
$color-text: #c9c9c9;
|
||||
$font-size-base: 2rem;
|
||||
|
||||
$font-family-base: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial,
|
||||
'Noto Sans', sans-serif;
|
||||
$font-family-heading: $font-family-base;
|
||||
|
||||
@import 'lib/css/main';
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
<script lang="ts">
|
||||
import { currentUser, pb } from '../velconnect';
|
||||
|
||||
let email: string;
|
||||
let password: string;
|
||||
|
||||
async function login() {
|
||||
const user = await pb.collection('Users').authWithPassword(email, password);
|
||||
console.log(user);
|
||||
}
|
||||
|
||||
async function signUp() {
|
||||
try {
|
||||
const data = {
|
||||
email,
|
||||
password,
|
||||
passwordConfirm: password
|
||||
};
|
||||
const createdUser = await pb.collection('Users').create(data);
|
||||
await login();
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
|
||||
function signOut() {
|
||||
pb.authStore.clear();
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if $currentUser}
|
||||
<p>
|
||||
Signed in as {$currentUser.email}
|
||||
<button on:click={signOut}>Sign Out</button>
|
||||
</p>
|
||||
{:else}
|
||||
<form on:submit|preventDefault>
|
||||
<input placeholder="Email" type="text" bind:value={email} />
|
||||
|
||||
<input placeholder="Password" type="password" bind:value={password} />
|
||||
<button on:click={signUp}>Sign Up</button>
|
||||
<button on:click={login}>Login</button>
|
||||
</form>
|
||||
{/if}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
<script lang="ts">
|
||||
import { currentDevice, currentUser, pb, type Device, pairedDevices } from '../velconnect';
|
||||
|
||||
let pairingCode: string;
|
||||
let errorMessage: string | null;
|
||||
|
||||
async function pair() {
|
||||
// find the device by pairing code
|
||||
try {
|
||||
let device = (await pb
|
||||
.collection('Device')
|
||||
.getFirstListItem(`pairing_code="${pairingCode}"`)) as Device;
|
||||
|
||||
// add it to the local data
|
||||
currentDevice.set(device.id);
|
||||
pairedDevices.set([...$pairedDevices, device.id]);
|
||||
|
||||
// add it to my account if logged in
|
||||
if ($currentUser) {
|
||||
$currentUser.devices.push(device.id);
|
||||
await pb.collection('Users').update($currentUser.id, $currentUser);
|
||||
}
|
||||
errorMessage = null;
|
||||
} catch (e) {
|
||||
if (e == "ClientResponseError 404: The requested resource wasn't found.") {
|
||||
errorMessage = 'Device not found with this pairing code.';
|
||||
}
|
||||
console.error('Not found: ' + e);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<input bind:value={pairingCode} placeholder="Paring Code" />
|
||||
<button on:click={pair}>Pair</button>
|
||||
{#if errorMessage}
|
||||
<p>{errorMessage}</p>
|
||||
{/if}
|
||||
|
|
@ -0,0 +1,257 @@
|
|||
/* Sakura.css v1.4.1
|
||||
* ================
|
||||
* Minimal css theme.
|
||||
* Project: https://github.com/oxalorg/sakura/
|
||||
*/
|
||||
|
||||
/* Body */
|
||||
|
||||
html {
|
||||
font-size: 62.5%; // So that root size becomes 10px
|
||||
font-family: $font-family-base;
|
||||
}
|
||||
|
||||
body {
|
||||
// $font-size-base must be a rem value
|
||||
font-size: $font-size-base;
|
||||
line-height: 1.618;
|
||||
max-width: 38em;
|
||||
margin: auto;
|
||||
color: $color-text;
|
||||
background-color: $color-bg;
|
||||
padding: 13px;
|
||||
}
|
||||
|
||||
@media (max-width: 684px) {
|
||||
body {
|
||||
font-size: $font-size-base * 0.85;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 382px) {
|
||||
body {
|
||||
font-size: $font-size-base * 0.75;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin word-wrap() {
|
||||
overflow-wrap: break-word;
|
||||
word-wrap: break-word;
|
||||
-ms-word-break: break-all;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
line-height: 1.1;
|
||||
font-family: $font-family-heading;
|
||||
font-weight: 700;
|
||||
margin-top: 3rem;
|
||||
margin-bottom: 1.5rem;
|
||||
@include word-wrap;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2.35em;
|
||||
}
|
||||
h2 {
|
||||
font-size: 2em;
|
||||
}
|
||||
h3 {
|
||||
font-size: 1.75em;
|
||||
}
|
||||
h4 {
|
||||
font-size: 1.5em;
|
||||
}
|
||||
h5 {
|
||||
font-size: 1.25em;
|
||||
}
|
||||
h6 {
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 0px;
|
||||
margin-bottom: 2.5rem;
|
||||
}
|
||||
|
||||
small,
|
||||
sub,
|
||||
sup {
|
||||
font-size: 75%;
|
||||
}
|
||||
|
||||
hr {
|
||||
border-color: $color-blossom;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: $color-blossom;
|
||||
|
||||
&:visited {
|
||||
color: darken($color-blossom, 10%);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: $color-fade;
|
||||
border-bottom: 2px solid $color-text;
|
||||
}
|
||||
}
|
||||
|
||||
ul {
|
||||
padding-left: 1.4em;
|
||||
margin-top: 0px;
|
||||
margin-bottom: 2.5rem;
|
||||
}
|
||||
|
||||
li {
|
||||
margin-bottom: 0.4em;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin-left: 0px;
|
||||
margin-right: 0px;
|
||||
padding-left: 1em;
|
||||
padding-top: 0.8em;
|
||||
padding-bottom: 0.8em;
|
||||
padding-right: 0.8em;
|
||||
border-left: 5px solid $color-blossom;
|
||||
margin-bottom: 2.5rem;
|
||||
background-color: $color-bg-alt;
|
||||
}
|
||||
|
||||
blockquote p {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
img,
|
||||
video {
|
||||
height: auto;
|
||||
max-width: 100%;
|
||||
margin-top: 0px;
|
||||
margin-bottom: 2.5rem;
|
||||
}
|
||||
|
||||
/* Pre and Code */
|
||||
|
||||
pre {
|
||||
background-color: $color-bg-alt;
|
||||
display: block;
|
||||
padding: 1em;
|
||||
overflow-x: auto;
|
||||
margin-top: 0px;
|
||||
margin-bottom: 2.5rem;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
code,
|
||||
kbd,
|
||||
samp {
|
||||
font-size: 0.9em;
|
||||
padding: 0 0.5em;
|
||||
background-color: $color-bg-alt;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
pre > code {
|
||||
padding: 0;
|
||||
background-color: transparent;
|
||||
white-space: pre;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
/* Tables */
|
||||
|
||||
table {
|
||||
text-align: justify;
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
td,
|
||||
th {
|
||||
padding: 0.5em;
|
||||
border-bottom: 1px solid $color-bg-alt;
|
||||
}
|
||||
|
||||
/* Buttons, forms and input */
|
||||
|
||||
input,
|
||||
textarea {
|
||||
border: 1px solid $color-text;
|
||||
|
||||
&:focus {
|
||||
border: 1px solid $color-blossom;
|
||||
}
|
||||
}
|
||||
|
||||
textarea {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.button,
|
||||
button,
|
||||
input[type='submit'],
|
||||
input[type='reset'],
|
||||
input[type='button'] {
|
||||
display: inline-block;
|
||||
padding: 5px 10px;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
white-space: nowrap;
|
||||
|
||||
background-color: $color-blossom;
|
||||
color: $color-bg;
|
||||
border-radius: 1px;
|
||||
border: 1px solid $color-blossom;
|
||||
cursor: pointer;
|
||||
box-sizing: border-box;
|
||||
|
||||
&[disabled] {
|
||||
cursor: default;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
&:focus:enabled,
|
||||
&:hover:enabled {
|
||||
background-color: $color-fade;
|
||||
border-color: $color-fade;
|
||||
color: $color-bg;
|
||||
outline: 0;
|
||||
}
|
||||
}
|
||||
|
||||
textarea,
|
||||
select,
|
||||
input {
|
||||
color: $color-text;
|
||||
padding: 6px 10px; /* The 6px vertically centers text on FF, ignored by Webkit */
|
||||
margin-bottom: 10px;
|
||||
background-color: $color-bg-alt;
|
||||
border: 1px solid $color-bg-alt;
|
||||
border-radius: 4px;
|
||||
box-shadow: none;
|
||||
box-sizing: border-box;
|
||||
|
||||
&:focus {
|
||||
border: 1px solid $color-blossom;
|
||||
outline: 0;
|
||||
}
|
||||
}
|
||||
|
||||
input[type='checkbox']:focus {
|
||||
outline: 1px dotted $color-blossom;
|
||||
}
|
||||
|
||||
label,
|
||||
legend,
|
||||
fieldset {
|
||||
display: block;
|
||||
margin-bottom: 0.5rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
import PocketBase from 'pocketbase';
|
||||
import { writable } from 'svelte/store';
|
||||
import { type Record } from 'pocketbase';
|
||||
|
||||
export const pb = new PocketBase('http://127.0.0.1:8090');
|
||||
|
||||
export const currentUser = writable(pb.authStore.model);
|
||||
|
||||
pb.authStore.onChange((auth) => {
|
||||
console.log('authStore changed', auth);
|
||||
currentUser.set(pb.authStore.model);
|
||||
});
|
||||
|
||||
let pairedDevicesInit: string[] = [];
|
||||
export const pairedDevices = writable(pairedDevicesInit);
|
||||
export const currentDevice = writable('');
|
||||
|
||||
interface HasData extends Record {
|
||||
data: { [key: string]: string };
|
||||
}
|
||||
export interface Device extends Record {
|
||||
current_room: string;
|
||||
current_app: string;
|
||||
data: { [key: string]: string };
|
||||
}
|
||||
export interface RoomData extends HasData {}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
<script>
|
||||
import '../app.scss';
|
||||
</script>
|
||||
|
||||
<slot />
|
||||
|
|
@ -0,0 +1,235 @@
|
|||
<script lang="ts">
|
||||
import { onDestroy, onMount } from 'svelte';
|
||||
import {
|
||||
currentDevice,
|
||||
type Device,
|
||||
pairedDevices,
|
||||
pb,
|
||||
type RoomData,
|
||||
currentUser
|
||||
} from '../lib/velconnect';
|
||||
import Login from '$lib/components/Login.svelte';
|
||||
import Pair from '$lib/components/Pair.svelte';
|
||||
|
||||
if ($currentDevice == '' && $pairedDevices.length > 0) {
|
||||
currentDevice.set($pairedDevices[0]);
|
||||
}
|
||||
|
||||
let unsubscribeDeviceData: () => void;
|
||||
let unsubscribeCurrentDevice: () => void;
|
||||
|
||||
let deviceData: Device | null;
|
||||
let roomData: RoomData | null;
|
||||
|
||||
let sending = false;
|
||||
|
||||
$: deviceData,
|
||||
() => {
|
||||
console.log('Device data changed');
|
||||
};
|
||||
|
||||
onMount(async () => {
|
||||
if ($currentDevice != '') {
|
||||
deviceData = await pb.collection('Device').getOne($currentDevice);
|
||||
}
|
||||
|
||||
unsubscribeCurrentDevice = currentDevice.subscribe(async (val) => {
|
||||
console.log('current device changed');
|
||||
unsubscribeDeviceData?.();
|
||||
if (val != '') {
|
||||
deviceData = await pb.collection('Device').getOne($currentDevice);
|
||||
unsubscribeDeviceData = await pb.collection('Device').subscribe(val, (data) => {
|
||||
deviceData = data.record as Device;
|
||||
});
|
||||
} else {
|
||||
deviceData = null;
|
||||
roomData = null;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
onDestroy(() => {
|
||||
unsubscribeCurrentDevice?.();
|
||||
unsubscribeDeviceData?.();
|
||||
});
|
||||
|
||||
let abortController = new AbortController();
|
||||
function delayedSend() {
|
||||
console.log('fn: delayedSend()');
|
||||
|
||||
// abort the previous send
|
||||
abortController.abort();
|
||||
const newAbortController = new AbortController();
|
||||
abortController = newAbortController;
|
||||
setTimeout(() => {
|
||||
if (!newAbortController.signal.aborted) {
|
||||
send();
|
||||
} else {
|
||||
console.log('aborted');
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
function send() {
|
||||
console.log('sending...');
|
||||
sending = true;
|
||||
let promises = [];
|
||||
if (deviceData) {
|
||||
promises.push(pb.collection('Device').update(deviceData.id, deviceData));
|
||||
}
|
||||
if (roomData) {
|
||||
promises.push(pb.collection('DataBlock').update(roomData.id, roomData));
|
||||
}
|
||||
Promise.all(promises).then(() => {
|
||||
sending = false;
|
||||
});
|
||||
}
|
||||
|
||||
function removeDevice(d: string) {
|
||||
pairedDevices.set($pairedDevices.filter((i) => i != d));
|
||||
|
||||
if ($currentDevice == d) {
|
||||
console.log('Removed current device');
|
||||
|
||||
// if there are still devices left
|
||||
if ($pairedDevices.length > 0) {
|
||||
currentDevice.set($pairedDevices[0]);
|
||||
} else {
|
||||
currentDevice.set('');
|
||||
}
|
||||
}
|
||||
|
||||
if ($currentUser) {
|
||||
$currentUser.devices.filter((i: string) => i != d);
|
||||
pb.collection('Users').update($currentUser.id, $currentUser);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<h1>VEL-Connect</h1>
|
||||
<img src="/img/velconnect_logo_1.png" alt="logo" width="70px" height="28px" />
|
||||
<p>
|
||||
This is a demo dashboard. Visit the <a href="https://github.com/velaboratory/VEL-Connect"
|
||||
>GitHub repo</a
|
||||
> to copy it and make your own.
|
||||
</p>
|
||||
|
||||
<Login />
|
||||
<Pair />
|
||||
|
||||
<div>
|
||||
<h3>Devices:</h3>
|
||||
{#each $pairedDevices as d}
|
||||
<div>
|
||||
<button
|
||||
on:click={() => {
|
||||
currentDevice.set(d);
|
||||
}}>{d}</button
|
||||
>
|
||||
<button
|
||||
on:click={() => {
|
||||
removeDevice(d);
|
||||
}}>x</button
|
||||
>
|
||||
</div>
|
||||
{/each}
|
||||
{#if $pairedDevices.length == 0}
|
||||
<p>No devices paired. Enter a pairing code above.</p>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
{#if sending}
|
||||
<div>
|
||||
<progress />
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if deviceData != null && deviceData.data != null}
|
||||
<div>
|
||||
<h3>Device Info</h3>
|
||||
|
||||
<device-field>
|
||||
<h6>Device ID:</h6>
|
||||
<code>{deviceData.id}</code>
|
||||
</device-field>
|
||||
<device-field>
|
||||
<h6>Pairing Code:</h6>
|
||||
<code>{deviceData.pairing_code}</code>
|
||||
</device-field>
|
||||
<device-field>
|
||||
<h6>First Seen</h6>
|
||||
<p>{deviceData.created}</p>
|
||||
</device-field>
|
||||
<device-field>
|
||||
<h6>Last Seen</h6>
|
||||
<p>{deviceData.updated}</p>
|
||||
</device-field>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3>Settings</h3>
|
||||
|
||||
<label>
|
||||
User Name
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Enter username..."
|
||||
bind:value={deviceData.friendly_name}
|
||||
on:input={delayedSend}
|
||||
/>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
Avatar URL
|
||||
<a href="https://demo.readyplayer.me" target="blank">
|
||||
Create New Avatar
|
||||
<svg style="width:1em;height:1em;margin-bottom:-.15em;" viewBox="0 0 24 24">
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M14,3V5H17.59L7.76,14.83L9.17,16.24L19,6.41V10H21V3M19,19H5V5H12V3H5C3.89,3 3,3.9 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V12H19V19Z"
|
||||
/>
|
||||
</svg>
|
||||
</a>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="https://----.glb"
|
||||
bind:value={deviceData.data.avatar_url}
|
||||
on:input={delayedSend}
|
||||
/>
|
||||
</label>
|
||||
|
||||
<device-field>
|
||||
<h6>Current Room</h6>
|
||||
<a href="/join/{deviceData.current_app}/room_name" target="blank">
|
||||
Shareable Link
|
||||
<svg style="width:1em;height:1em;margin-bottom:-.15em;" viewBox="0 0 24 24">
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M14,3V5H17.59L7.76,14.83L9.17,16.24L19,6.41V10H21V3M19,19H5V5H12V3H5C3.89,3 3,3.9 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V12H19V19Z"
|
||||
/>
|
||||
</svg>
|
||||
</a>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="room_1"
|
||||
bind:value={deviceData.current_room}
|
||||
on:input={delayedSend}
|
||||
/>
|
||||
</device-field>
|
||||
</div>
|
||||
|
||||
<h6>Raw JSON:</h6>
|
||||
<pre><code>{JSON.stringify(deviceData, null, 2)}</code></pre>
|
||||
{/if}
|
||||
|
||||
<style lang="scss">
|
||||
device-field {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0em;
|
||||
width: fit-content;
|
||||
p {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1 @@
|
|||
/* Variables and mixins declared here will be available in all other SCSS files */
|
||||
|
|
@ -0,0 +1,223 @@
|
|||
/* Sakura.css v1.4.1
|
||||
* ================
|
||||
* Minimal css theme.
|
||||
* Project: https://github.com/oxalorg/sakura/
|
||||
*/
|
||||
/* Body */
|
||||
html {
|
||||
font-size: 62.5%;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif;
|
||||
}
|
||||
|
||||
body {
|
||||
font-size: 1.8rem;
|
||||
line-height: 1.618;
|
||||
max-width: 38em;
|
||||
margin: auto;
|
||||
color: #4a4a4a;
|
||||
background-color: #f9f9f9;
|
||||
padding: 13px;
|
||||
}
|
||||
|
||||
@media (max-width: 684px) {
|
||||
body {
|
||||
font-size: 1.53rem;
|
||||
}
|
||||
}
|
||||
@media (max-width: 382px) {
|
||||
body {
|
||||
font-size: 1.35rem;
|
||||
}
|
||||
}
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
line-height: 1.1;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif;
|
||||
font-weight: 700;
|
||||
margin-top: 3rem;
|
||||
margin-bottom: 1.5rem;
|
||||
overflow-wrap: break-word;
|
||||
word-wrap: break-word;
|
||||
-ms-word-break: break-all;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2.35em;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 2em;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.75em;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: 1.25em;
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 0px;
|
||||
margin-bottom: 2.5rem;
|
||||
}
|
||||
|
||||
small, sub, sup {
|
||||
font-size: 75%;
|
||||
}
|
||||
|
||||
hr {
|
||||
border-color: #1d7484;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: #1d7484;
|
||||
}
|
||||
a:visited {
|
||||
color: #144f5a;
|
||||
}
|
||||
a:hover {
|
||||
color: #982c61;
|
||||
border-bottom: 2px solid #4a4a4a;
|
||||
}
|
||||
|
||||
ul {
|
||||
padding-left: 1.4em;
|
||||
margin-top: 0px;
|
||||
margin-bottom: 2.5rem;
|
||||
}
|
||||
|
||||
li {
|
||||
margin-bottom: 0.4em;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin-left: 0px;
|
||||
margin-right: 0px;
|
||||
padding-left: 1em;
|
||||
padding-top: 0.8em;
|
||||
padding-bottom: 0.8em;
|
||||
padding-right: 0.8em;
|
||||
border-left: 5px solid #1d7484;
|
||||
margin-bottom: 2.5rem;
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
|
||||
blockquote p {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
img, video {
|
||||
height: auto;
|
||||
max-width: 100%;
|
||||
margin-top: 0px;
|
||||
margin-bottom: 2.5rem;
|
||||
}
|
||||
|
||||
/* Pre and Code */
|
||||
pre {
|
||||
background-color: #f1f1f1;
|
||||
display: block;
|
||||
padding: 1em;
|
||||
overflow-x: auto;
|
||||
margin-top: 0px;
|
||||
margin-bottom: 2.5rem;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
code, kbd, samp {
|
||||
font-size: 0.9em;
|
||||
padding: 0 0.5em;
|
||||
background-color: #f1f1f1;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
pre > code {
|
||||
padding: 0;
|
||||
background-color: transparent;
|
||||
white-space: pre;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
/* Tables */
|
||||
table {
|
||||
text-align: justify;
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
td, th {
|
||||
padding: 0.5em;
|
||||
border-bottom: 1px solid #f1f1f1;
|
||||
}
|
||||
|
||||
/* Buttons, forms and input */
|
||||
input, textarea {
|
||||
border: 1px solid #4a4a4a;
|
||||
}
|
||||
input:focus, textarea:focus {
|
||||
border: 1px solid #1d7484;
|
||||
}
|
||||
|
||||
textarea {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.button, button, input[type=submit], input[type=reset], input[type=button] {
|
||||
display: inline-block;
|
||||
padding: 5px 10px;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
white-space: nowrap;
|
||||
background-color: #1d7484;
|
||||
color: #f9f9f9;
|
||||
border-radius: 1px;
|
||||
border: 1px solid #1d7484;
|
||||
cursor: pointer;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.button[disabled], button[disabled], input[type=submit][disabled], input[type=reset][disabled], input[type=button][disabled] {
|
||||
cursor: default;
|
||||
opacity: 0.5;
|
||||
}
|
||||
.button:focus:enabled, .button:hover:enabled, button:focus:enabled, button:hover:enabled, input[type=submit]:focus:enabled, input[type=submit]:hover:enabled, input[type=reset]:focus:enabled, input[type=reset]:hover:enabled, input[type=button]:focus:enabled, input[type=button]:hover:enabled {
|
||||
background-color: #982c61;
|
||||
border-color: #982c61;
|
||||
color: #f9f9f9;
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
textarea, select, input {
|
||||
color: #4a4a4a;
|
||||
padding: 6px 10px; /* The 6px vertically centers text on FF, ignored by Webkit */
|
||||
margin-bottom: 10px;
|
||||
background-color: #f1f1f1;
|
||||
border: 1px solid #f1f1f1;
|
||||
border-radius: 4px;
|
||||
box-shadow: none;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
textarea:focus, select:focus, input:focus {
|
||||
border: 1px solid #1d7484;
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
input[type=checkbox]:focus {
|
||||
outline: 1px dotted #1d7484;
|
||||
}
|
||||
|
||||
label, legend, fieldset {
|
||||
display: block;
|
||||
margin-bottom: 0.5rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 5.9 KiB |
|
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 6.4 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 815 B After Width: | Height: | Size: 815 B |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 977 B After Width: | Height: | Size: 977 B |
|
Before Width: | Height: | Size: 131 KiB After Width: | Height: | Size: 131 KiB |
|
Before Width: | Height: | Size: 224 KiB After Width: | Height: | Size: 224 KiB |
|
Before Width: | Height: | Size: 437 KiB After Width: | Height: | Size: 437 KiB |
|
Before Width: | Height: | Size: 437 KiB After Width: | Height: | Size: 437 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 6.9 KiB After Width: | Height: | Size: 6.9 KiB |
|
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 8.5 KiB |
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 7.1 KiB |
|
|
@ -0,0 +1,18 @@
|
|||
import { vitePreprocess } from '@sveltejs/kit/vite';
|
||||
import adapter from '@sveltejs/adapter-auto';
|
||||
|
||||
/** @type {import('@sveltejs/kit').Config} */
|
||||
const config = {
|
||||
// Consult https://kit.svelte.dev/docs/integrations#preprocessors
|
||||
// for more information about preprocessors
|
||||
preprocess: [vitePreprocess({})],
|
||||
|
||||
kit: {
|
||||
// adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list.
|
||||
// If your environment is not supported or you settled on a specific environment, switch out the adapter.
|
||||
// See https://kit.svelte.dev/docs/adapters for more information about adapters.
|
||||
adapter: adapter()
|
||||
}
|
||||
};
|
||||
|
||||
export default config;
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"extends": "./.svelte-kit/tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"checkJs": true,
|
||||
"esModuleInterop": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"resolveJsonModule": true,
|
||||
"skipLibCheck": true,
|
||||
"sourceMap": true,
|
||||
"strict": true
|
||||
}
|
||||
// Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias
|
||||
//
|
||||
// If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
|
||||
// from the referenced tsconfig.json - TypeScript does not merge them in
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
import { sveltekit } from '@sveltejs/kit/vite';
|
||||
import { defineConfig } from 'vite';
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [sveltekit()],
|
||||
|
||||
css: {
|
||||
preprocessorOptions: {
|
||||
scss: {
|
||||
additionalData: '@use "src/variables.scss" as *;'
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -68,6 +68,11 @@ func main() {
|
|||
}
|
||||
}
|
||||
|
||||
// double-check that data is not null
|
||||
if (record.Get("data") == nil) || (record.Get("data") == "") {
|
||||
record.Set("data", "{}")
|
||||
}
|
||||
|
||||
// apply to the db
|
||||
if err := dao.SaveRecord(record); err != nil {
|
||||
return err
|
||||
|
|
@ -134,6 +139,11 @@ func main() {
|
|||
}
|
||||
}
|
||||
|
||||
// double-check that data is not null
|
||||
if (record.Get("data") == nil) || (record.Get("data") == "") {
|
||||
record.Set("data", "{}")
|
||||
}
|
||||
|
||||
// apply to the db
|
||||
if err := dao.SaveRecord(record); err != nil {
|
||||
return err
|
||||
|
|
|
|||
|
|
@ -0,0 +1,54 @@
|
|||
package migrations
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/pocketbase/dbx"
|
||||
"github.com/pocketbase/pocketbase/daos"
|
||||
m "github.com/pocketbase/pocketbase/migrations"
|
||||
"github.com/pocketbase/pocketbase/models/schema"
|
||||
)
|
||||
|
||||
func init() {
|
||||
m.Register(func(db dbx.Builder) error {
|
||||
dao := daos.New(db);
|
||||
|
||||
collection, err := dao.FindCollectionByNameOrId("fupstz47c55s69f")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// add
|
||||
new_current_room_data := &schema.SchemaField{}
|
||||
json.Unmarshal([]byte(`{
|
||||
"system": false,
|
||||
"id": "g5wezfiu",
|
||||
"name": "current_room_data",
|
||||
"type": "relation",
|
||||
"required": false,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"collectionId": "3qwwkz4wb0lyi78",
|
||||
"cascadeDelete": false,
|
||||
"minSelect": null,
|
||||
"maxSelect": 1,
|
||||
"displayFields": []
|
||||
}
|
||||
}`), new_current_room_data)
|
||||
collection.Schema.AddField(new_current_room_data)
|
||||
|
||||
return dao.SaveCollection(collection)
|
||||
}, func(db dbx.Builder) error {
|
||||
dao := daos.New(db);
|
||||
|
||||
collection, err := dao.FindCollectionByNameOrId("fupstz47c55s69f")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// remove
|
||||
collection.Schema.RemoveField("g5wezfiu")
|
||||
|
||||
return dao.SaveCollection(collection)
|
||||
})
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
package migrations
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/pocketbase/dbx"
|
||||
"github.com/pocketbase/pocketbase/daos"
|
||||
m "github.com/pocketbase/pocketbase/migrations"
|
||||
"github.com/pocketbase/pocketbase/models/schema"
|
||||
)
|
||||
|
||||
func init() {
|
||||
m.Register(func(db dbx.Builder) error {
|
||||
dao := daos.New(db);
|
||||
|
||||
collection, err := dao.FindCollectionByNameOrId("fupstz47c55s69f")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// remove
|
||||
collection.Schema.RemoveField("g5wezfiu")
|
||||
|
||||
return dao.SaveCollection(collection)
|
||||
}, func(db dbx.Builder) error {
|
||||
dao := daos.New(db);
|
||||
|
||||
collection, err := dao.FindCollectionByNameOrId("fupstz47c55s69f")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// add
|
||||
del_current_room_data := &schema.SchemaField{}
|
||||
json.Unmarshal([]byte(`{
|
||||
"system": false,
|
||||
"id": "g5wezfiu",
|
||||
"name": "current_room_data",
|
||||
"type": "relation",
|
||||
"required": false,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"collectionId": "3qwwkz4wb0lyi78",
|
||||
"cascadeDelete": false,
|
||||
"minSelect": null,
|
||||
"maxSelect": 1,
|
||||
"displayFields": []
|
||||
}
|
||||
}`), del_current_room_data)
|
||||
collection.Schema.AddField(del_current_room_data)
|
||||
|
||||
return dao.SaveCollection(collection)
|
||||
})
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
package migrations
|
||||
|
||||
import (
|
||||
"github.com/pocketbase/dbx"
|
||||
"github.com/pocketbase/pocketbase/daos"
|
||||
m "github.com/pocketbase/pocketbase/migrations"
|
||||
)
|
||||
|
||||
func init() {
|
||||
m.Register(func(db dbx.Builder) error {
|
||||
dao := daos.New(db);
|
||||
|
||||
collection, err := dao.FindCollectionByNameOrId("_pb_users_auth_")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
collection.Name = "Users"
|
||||
|
||||
return dao.SaveCollection(collection)
|
||||
}, func(db dbx.Builder) error {
|
||||
dao := daos.New(db);
|
||||
|
||||
collection, err := dao.FindCollectionByNameOrId("_pb_users_auth_")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
collection.Name = "users"
|
||||
|
||||
return dao.SaveCollection(collection)
|
||||
})
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
package migrations
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/pocketbase/dbx"
|
||||
"github.com/pocketbase/pocketbase/daos"
|
||||
m "github.com/pocketbase/pocketbase/migrations"
|
||||
"github.com/pocketbase/pocketbase/models/schema"
|
||||
)
|
||||
|
||||
func init() {
|
||||
m.Register(func(db dbx.Builder) error {
|
||||
dao := daos.New(db);
|
||||
|
||||
collection, err := dao.FindCollectionByNameOrId("_pb_users_auth_")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// add
|
||||
new_devices := &schema.SchemaField{}
|
||||
json.Unmarshal([]byte(`{
|
||||
"system": false,
|
||||
"id": "1hwaooub",
|
||||
"name": "devices",
|
||||
"type": "relation",
|
||||
"required": false,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"collectionId": "fupstz47c55s69f",
|
||||
"cascadeDelete": false,
|
||||
"minSelect": null,
|
||||
"maxSelect": null,
|
||||
"displayFields": []
|
||||
}
|
||||
}`), new_devices)
|
||||
collection.Schema.AddField(new_devices)
|
||||
|
||||
return dao.SaveCollection(collection)
|
||||
}, func(db dbx.Builder) error {
|
||||
dao := daos.New(db);
|
||||
|
||||
collection, err := dao.FindCollectionByNameOrId("_pb_users_auth_")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// remove
|
||||
collection.Schema.RemoveField("1hwaooub")
|
||||
|
||||
return dao.SaveCollection(collection)
|
||||
})
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
package migrations
|
||||
|
||||
import (
|
||||
"github.com/pocketbase/dbx"
|
||||
"github.com/pocketbase/pocketbase/daos"
|
||||
m "github.com/pocketbase/pocketbase/migrations"
|
||||
"github.com/pocketbase/pocketbase/tools/types"
|
||||
)
|
||||
|
||||
func init() {
|
||||
m.Register(func(db dbx.Builder) error {
|
||||
dao := daos.New(db);
|
||||
|
||||
collection, err := dao.FindCollectionByNameOrId("fupstz47c55s69f")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
collection.ListRule = types.Pointer("")
|
||||
|
||||
return dao.SaveCollection(collection)
|
||||
}, func(db dbx.Builder) error {
|
||||
dao := daos.New(db);
|
||||
|
||||
collection, err := dao.FindCollectionByNameOrId("fupstz47c55s69f")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
collection.ListRule = nil
|
||||
|
||||
return dao.SaveCollection(collection)
|
||||
})
|
||||
}
|
||||