mirror of
https://github.com/colanode/colanode.git
synced 2025-12-16 11:47:47 +01:00
Implement workspace create and sqlite integration
This commit is contained in:
@@ -3,8 +3,10 @@
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Neuron</title>
|
||||
<meta http-equiv="Content-Security-Policy" content="script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:;">
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/renderer.ts"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
240
desktop/package-lock.json
generated
240
desktop/package-lock.json
generated
@@ -18,6 +18,7 @@
|
||||
"@react-oauth/google": "^0.12.1",
|
||||
"@reduxjs/toolkit": "^2.2.7",
|
||||
"axios": "^1.7.2",
|
||||
"better-sqlite3": "^11.1.2",
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"clsx": "^2.1.1",
|
||||
"electron-squirrel-startup": "^1.0.1",
|
||||
@@ -41,6 +42,7 @@
|
||||
"@electron-forge/plugin-fuses": "^7.4.0",
|
||||
"@electron-forge/plugin-vite": "^7.4.0",
|
||||
"@electron/fuses": "^1.8.0",
|
||||
"@types/better-sqlite3": "^7.6.11",
|
||||
"@types/react": "^18.3.3",
|
||||
"@types/react-dom": "^18.3.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.62.0",
|
||||
@@ -2391,6 +2393,16 @@
|
||||
"devOptional": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/better-sqlite3": {
|
||||
"version": "7.6.11",
|
||||
"resolved": "https://registry.npmjs.org/@types/better-sqlite3/-/better-sqlite3-7.6.11.tgz",
|
||||
"integrity": "sha512-i8KcD3PgGtGBLl3+mMYA8PdKkButvPyARxA7IQAd6qeslht13qxb1zzO8dRCtE7U3IoJS782zDBAeoKiM695kg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/cacheable-request": {
|
||||
"version": "6.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz",
|
||||
@@ -3242,7 +3254,6 @@
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
||||
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
@@ -3259,6 +3270,17 @@
|
||||
],
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/better-sqlite3": {
|
||||
"version": "11.1.2",
|
||||
"resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-11.1.2.tgz",
|
||||
"integrity": "sha512-gujtFwavWU4MSPT+h9B+4pkvZdyOUkH54zgLdIrMmmmd4ZqiBIrRNBzNzYVFO417xo882uP5HBu4GjOfaSrIQw==",
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"bindings": "^1.5.0",
|
||||
"prebuild-install": "^7.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/binary-extensions": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
|
||||
@@ -3271,11 +3293,19 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/bindings": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
|
||||
"integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"file-uri-to-path": "1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/bl": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
|
||||
"integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"buffer": "^5.5.0",
|
||||
@@ -3400,7 +3430,6 @@
|
||||
"version": "5.7.1",
|
||||
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
|
||||
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
@@ -4134,7 +4163,6 @@
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
|
||||
"integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"mimic-response": "^3.1.0"
|
||||
@@ -4150,7 +4178,6 @@
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
|
||||
"integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
@@ -4159,6 +4186,15 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/deep-extend": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
|
||||
"integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/deep-is": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
|
||||
@@ -4266,7 +4302,6 @@
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz",
|
||||
"integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
@@ -4993,7 +5028,6 @@
|
||||
"version": "1.4.4",
|
||||
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
|
||||
"integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"once": "^1.4.0"
|
||||
@@ -5674,6 +5708,15 @@
|
||||
"which": "bin/which"
|
||||
}
|
||||
},
|
||||
"node_modules/expand-template": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
|
||||
"integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==",
|
||||
"license": "(MIT OR WTFPL)",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/expand-tilde": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz",
|
||||
@@ -5872,6 +5915,12 @@
|
||||
"node": "^10.12.0 || >=12.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/file-uri-to-path": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
|
||||
"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/filename-reserved-regex": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz",
|
||||
@@ -6107,6 +6156,12 @@
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/fs-constants": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
|
||||
"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/fs-extra": {
|
||||
"version": "10.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
|
||||
@@ -6393,6 +6448,12 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/github-from-package": {
|
||||
"version": "0.0.0",
|
||||
"resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
|
||||
"integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/glob": {
|
||||
"version": "7.2.3",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
|
||||
@@ -6806,7 +6867,6 @@
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
|
||||
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
@@ -6903,14 +6963,12 @@
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/ini": {
|
||||
"version": "1.3.8",
|
||||
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
|
||||
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/internal-slot": {
|
||||
@@ -7869,7 +7927,6 @@
|
||||
"version": "1.2.8",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
|
||||
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
@@ -7985,6 +8042,12 @@
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/mkdirp-classic": {
|
||||
"version": "0.5.3",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
|
||||
"integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
@@ -8021,6 +8084,12 @@
|
||||
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/napi-build-utils": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz",
|
||||
"integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/natural-compare": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
|
||||
@@ -8056,7 +8125,6 @@
|
||||
"version": "3.65.0",
|
||||
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.65.0.tgz",
|
||||
"integrity": "sha512-ThjYBfoDNr08AWx6hGaRbfPwxKV9kVzAzOzlLKbk2CuqXE2xnCh+cbAGnwM3t8Lq4v9rUB7VfondlkBckcJrVA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"semver": "^7.3.5"
|
||||
@@ -8369,7 +8437,6 @@
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"wrappy": "1"
|
||||
@@ -9039,6 +9106,32 @@
|
||||
"node": "^12.20.0 || >=14"
|
||||
}
|
||||
},
|
||||
"node_modules/prebuild-install": {
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.2.tgz",
|
||||
"integrity": "sha512-UnNke3IQb6sgarcZIDU3gbMeTp/9SSU1DAIkil7PrqG1vZlBtY5msYccSKSHDqa3hNg436IXK+SNImReuA1wEQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"detect-libc": "^2.0.0",
|
||||
"expand-template": "^2.0.3",
|
||||
"github-from-package": "0.0.0",
|
||||
"minimist": "^1.2.3",
|
||||
"mkdirp-classic": "^0.5.3",
|
||||
"napi-build-utils": "^1.0.1",
|
||||
"node-abi": "^3.3.0",
|
||||
"pump": "^3.0.0",
|
||||
"rc": "^1.2.7",
|
||||
"simple-get": "^4.0.0",
|
||||
"tar-fs": "^2.0.0",
|
||||
"tunnel-agent": "^0.6.0"
|
||||
},
|
||||
"bin": {
|
||||
"prebuild-install": "bin.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/prelude-ls": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
|
||||
@@ -9104,7 +9197,6 @@
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
|
||||
"integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"end-of-stream": "^1.1.0",
|
||||
@@ -9196,6 +9288,30 @@
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/rc": {
|
||||
"version": "1.2.8",
|
||||
"resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
|
||||
"integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
|
||||
"license": "(BSD-2-Clause OR MIT OR Apache-2.0)",
|
||||
"dependencies": {
|
||||
"deep-extend": "^0.6.0",
|
||||
"ini": "~1.3.0",
|
||||
"minimist": "^1.2.0",
|
||||
"strip-json-comments": "~2.0.1"
|
||||
},
|
||||
"bin": {
|
||||
"rc": "cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/rc/node_modules/strip-json-comments": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
|
||||
"integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react": {
|
||||
"version": "18.3.1",
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
|
||||
@@ -9433,7 +9549,6 @@
|
||||
"version": "3.6.2",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
|
||||
"integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"inherits": "^2.0.3",
|
||||
@@ -9774,7 +9889,6 @@
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
@@ -9829,7 +9943,6 @@
|
||||
"version": "7.6.3",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
|
||||
"integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
@@ -10037,6 +10150,51 @@
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/simple-concat": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
|
||||
"integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/simple-get": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz",
|
||||
"integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"decompress-response": "^6.0.0",
|
||||
"once": "^1.3.1",
|
||||
"simple-concat": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/slash": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
|
||||
@@ -10218,7 +10376,6 @@
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
|
||||
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"safe-buffer": "~5.2.0"
|
||||
@@ -10640,6 +10797,40 @@
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/tar-fs": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz",
|
||||
"integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"chownr": "^1.1.1",
|
||||
"mkdirp-classic": "^0.5.2",
|
||||
"pump": "^3.0.0",
|
||||
"tar-stream": "^2.1.4"
|
||||
}
|
||||
},
|
||||
"node_modules/tar-fs/node_modules/chownr": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
|
||||
"integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/tar-stream": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
|
||||
"integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"bl": "^4.0.3",
|
||||
"end-of-stream": "^1.4.1",
|
||||
"fs-constants": "^1.0.0",
|
||||
"inherits": "^2.0.3",
|
||||
"readable-stream": "^3.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/tar/node_modules/minipass": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz",
|
||||
@@ -10890,6 +11081,18 @@
|
||||
"typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta"
|
||||
}
|
||||
},
|
||||
"node_modules/tunnel-agent": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
|
||||
"integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"safe-buffer": "^5.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/type-check": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
|
||||
@@ -11493,7 +11696,6 @@
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/ws": {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"description": "Neuron Desktop",
|
||||
"main": ".vite/build/main.js",
|
||||
"scripts": {
|
||||
"start": "electron-forge start",
|
||||
"dev": "electron-forge start",
|
||||
"package": "electron-forge package",
|
||||
"make": "electron-forge make",
|
||||
"publish": "electron-forge publish",
|
||||
@@ -21,6 +21,7 @@
|
||||
"@electron-forge/plugin-fuses": "^7.4.0",
|
||||
"@electron-forge/plugin-vite": "^7.4.0",
|
||||
"@electron/fuses": "^1.8.0",
|
||||
"@types/better-sqlite3": "^7.6.11",
|
||||
"@types/react": "^18.3.3",
|
||||
"@types/react-dom": "^18.3.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.62.0",
|
||||
@@ -51,6 +52,7 @@
|
||||
"@react-oauth/google": "^0.12.1",
|
||||
"@reduxjs/toolkit": "^2.2.7",
|
||||
"axios": "^1.7.2",
|
||||
"better-sqlite3": "^11.1.2",
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"clsx": "^2.1.1",
|
||||
"electron-squirrel-startup": "^1.0.1",
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
import React from "react";
|
||||
import {useSelector} from "react-redux";
|
||||
import {RootState} from "@/store";
|
||||
import {Login} from "@/components/accounts/login";
|
||||
|
||||
export function AppLayout() {
|
||||
const account = useSelector((state: RootState) => state.account);
|
||||
|
||||
if (!account) {
|
||||
return <Login />;
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<p>Welcome {account.name}</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
17
desktop/src/components/app-loading.tsx
Normal file
17
desktop/src/components/app-loading.tsx
Normal file
@@ -0,0 +1,17 @@
|
||||
import React from "react";
|
||||
import {Spinner} from "@/components/ui/spinner";
|
||||
|
||||
export function AppLoading() {
|
||||
return (
|
||||
<div className="min-w-screen flex h-full min-h-screen w-full items-center justify-center">
|
||||
<div className="flex flex-col items-center gap-8 text-center">
|
||||
<h2 className="font-neotrax text-shadow-lg text-4xl text-gray-800">
|
||||
loading your workspaces
|
||||
</h2>
|
||||
<div>
|
||||
<Spinner />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,29 +1,38 @@
|
||||
import React from "react";
|
||||
import { createRoot } from 'react-dom/client';
|
||||
import {createBrowserRouter, RouterProvider} from "react-router-dom";
|
||||
import {AppLayout} from "@/components/app-layout";
|
||||
import {TooltipProvider} from "@/components/ui/tooltip";
|
||||
import {Toaster} from "@/components/ui/toaster";
|
||||
import { Provider as ReduxProvider } from "react-redux";
|
||||
import { store } from "@/store";
|
||||
import {useDispatch, useSelector} from "react-redux";
|
||||
import {RootState} from "@/store";
|
||||
import {Login} from "@/components/accounts/login";
|
||||
import {AppLoading} from "@/components/app-loading";
|
||||
import {setWorkspaces} from "@/store/workspaces-slice";
|
||||
import {Outlet} from "react-router-dom";
|
||||
|
||||
const router = createBrowserRouter([
|
||||
{
|
||||
path: '',
|
||||
element: <AppLayout />
|
||||
export function App() {
|
||||
const account = useSelector((state: RootState) => state.account);
|
||||
const workspaces = useSelector((state: RootState) => state.workspaces);
|
||||
const dispatch = useDispatch();
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!account) {
|
||||
return;
|
||||
}
|
||||
])
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<ReduxProvider store={store}>
|
||||
<TooltipProvider>
|
||||
<RouterProvider router={router} />
|
||||
</TooltipProvider>
|
||||
<Toaster />
|
||||
</ReduxProvider>
|
||||
);
|
||||
if (!workspaces.loaded) {
|
||||
// load workspaces async
|
||||
window.globalDb.getWorkspaces().then((workspaces) => {
|
||||
// dispatch action to store workspaces
|
||||
dispatch(setWorkspaces(workspaces));
|
||||
});
|
||||
}
|
||||
|
||||
}, [])
|
||||
|
||||
if (!account) {
|
||||
return <Login />;
|
||||
}
|
||||
|
||||
if (!workspaces.loaded) {
|
||||
return <AppLoading />
|
||||
}
|
||||
|
||||
return <Outlet />
|
||||
}
|
||||
|
||||
const root = createRoot(document.body);
|
||||
root.render(<App />);
|
||||
46
desktop/src/components/root.tsx
Normal file
46
desktop/src/components/root.tsx
Normal file
@@ -0,0 +1,46 @@
|
||||
import React from "react";
|
||||
import { createRoot } from 'react-dom/client';
|
||||
import {createBrowserRouter, RouterProvider} from "react-router-dom";
|
||||
import {App} from "@/components/app";
|
||||
import {TooltipProvider} from "@/components/ui/tooltip";
|
||||
import {Toaster} from "@/components/ui/toaster";
|
||||
import {Provider as ReduxProvider} from "react-redux";
|
||||
import {store} from "@/store";
|
||||
import {WorkspaceRedirect} from "@/components/workspaces/workspace-redirect";
|
||||
import {WorkspaceCreate} from "@/components/workspaces/workspace-create";
|
||||
import {Workspace} from "@/components/workspaces/workspace";
|
||||
|
||||
const router = createBrowserRouter([
|
||||
{
|
||||
path: '',
|
||||
element: <App />,
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
element: <WorkspaceRedirect />
|
||||
},
|
||||
{
|
||||
path: '/create',
|
||||
element: <WorkspaceCreate />
|
||||
},
|
||||
{
|
||||
path: ':workspaceId',
|
||||
element: <Workspace />
|
||||
}
|
||||
]
|
||||
}
|
||||
])
|
||||
|
||||
function Root() {
|
||||
return (
|
||||
<ReduxProvider store={store}>
|
||||
<TooltipProvider>
|
||||
<RouterProvider router={router} />
|
||||
</TooltipProvider>
|
||||
<Toaster />
|
||||
</ReduxProvider>
|
||||
);
|
||||
}
|
||||
|
||||
const root = createRoot(document.getElementById('root') as HTMLElement);
|
||||
root.render(<Root />);
|
||||
24
desktop/src/components/ui/textarea.tsx
Normal file
24
desktop/src/components/ui/textarea.tsx
Normal file
@@ -0,0 +1,24 @@
|
||||
import * as React from "react"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
export interface TextareaProps
|
||||
extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {}
|
||||
|
||||
const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
|
||||
({ className, ...props }, ref) => {
|
||||
return (
|
||||
<textarea
|
||||
className={cn(
|
||||
"flex min-h-[60px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50",
|
||||
className
|
||||
)}
|
||||
ref={ref}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
)
|
||||
Textarea.displayName = "Textarea"
|
||||
|
||||
export { Textarea }
|
||||
130
desktop/src/components/workspaces/workspace-create.tsx
Normal file
130
desktop/src/components/workspaces/workspace-create.tsx
Normal file
@@ -0,0 +1,130 @@
|
||||
import React from 'react';
|
||||
import { z } from 'zod';
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormMessage,
|
||||
FormLabel,
|
||||
} from '@/components/ui/form';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Spinner } from '@/components/ui/spinner';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Textarea } from '@/components/ui/textarea';
|
||||
import { toast } from '@/components/ui/use-toast';
|
||||
import {axios, parseApiError} from "@/lib/axios";
|
||||
import {Workspace} from "@/types/workspaces";
|
||||
import {useDispatch} from "react-redux";
|
||||
import {addWorkspace} from "@/store/workspaces-slice";
|
||||
import {useNavigate} from "react-router-dom";
|
||||
|
||||
const formSchema = z.object({
|
||||
name: z.string().min(3, 'Name must be at least 3 characters long.'),
|
||||
description: z.string(),
|
||||
});
|
||||
|
||||
export function WorkspaceCreate() {
|
||||
const [isPending, setIsPending] = React.useState(false);
|
||||
const form = useForm<z.infer<typeof formSchema>>({
|
||||
resolver: zodResolver(formSchema),
|
||||
defaultValues: {
|
||||
name: '',
|
||||
description: '',
|
||||
},
|
||||
});
|
||||
|
||||
const dispatch = useDispatch();
|
||||
const navigate = useNavigate();
|
||||
|
||||
async function handleSubmit(values: z.infer<typeof formSchema>) {
|
||||
setIsPending(true);
|
||||
try {
|
||||
const { data } = await axios.post<Workspace>('v1/workspaces', values);
|
||||
if (data) {
|
||||
await window.globalDb.addWorkspace({
|
||||
id: data.id,
|
||||
name: data.name,
|
||||
role: 'owner',
|
||||
avatar: null,
|
||||
description: data.description,
|
||||
});
|
||||
dispatch(addWorkspace(data));
|
||||
navigate(`/${data.id}`);
|
||||
} else {
|
||||
toast({
|
||||
title: 'Failed to create workspace',
|
||||
description: 'Invalid response from server',
|
||||
variant: 'destructive',
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
const apiError = parseApiError(error);
|
||||
toast({
|
||||
title: 'Failed to create workspace',
|
||||
description: apiError.message,
|
||||
variant: 'destructive',
|
||||
});
|
||||
} finally {
|
||||
setIsPending(false);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="container flex flex-row justify-center">
|
||||
<div className="w-full max-w-[700px]">
|
||||
<div className="flex flex-row justify-center py-8">
|
||||
<h1 className="text-center text-4xl font-bold leading-tight tracking-tighter lg:leading-[1.1]">
|
||||
Setup your workspace
|
||||
</h1>
|
||||
</div>
|
||||
<Form {...form}>
|
||||
<form
|
||||
className="flex flex-col"
|
||||
onSubmit={form.handleSubmit(handleSubmit)}
|
||||
>
|
||||
<div className="flex-grow space-y-4 py-2 pb-4">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="name"
|
||||
render={({field}) => (
|
||||
<FormItem className="flex-1">
|
||||
<FormLabel>Name *</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder="Name" {...field} />
|
||||
</FormControl>
|
||||
<FormMessage/>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="description"
|
||||
render={({field}) => (
|
||||
<FormItem>
|
||||
<FormLabel>Description</FormLabel>
|
||||
<FormControl>
|
||||
<Textarea
|
||||
placeholder="Write a short description about the workspace"
|
||||
{...field}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage/>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-row justify-end gap-2">
|
||||
<Button type="submit" disabled={isPending}>
|
||||
{isPending && <Spinner className="mr-1"/>}
|
||||
Create
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</Form>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
21
desktop/src/components/workspaces/workspace-redirect.tsx
Normal file
21
desktop/src/components/workspaces/workspace-redirect.tsx
Normal file
@@ -0,0 +1,21 @@
|
||||
import React, {useEffect} from "react";
|
||||
import {useSelector} from "react-redux";
|
||||
import {RootState} from "@/store";
|
||||
import {useNavigate} from "react-router-dom";
|
||||
import {AppLoading} from "@/components/app-loading";
|
||||
|
||||
export function WorkspaceRedirect() {
|
||||
const workspaces = useSelector((state: RootState) => state.workspaces);
|
||||
const navigate = useNavigate();
|
||||
|
||||
useEffect(() => {
|
||||
if (workspaces.workspaces.length == 0) {
|
||||
navigate('/create');
|
||||
return;
|
||||
}
|
||||
|
||||
navigate(`/${workspaces.workspaces[0].id}`);
|
||||
}, [workspaces, navigate])
|
||||
|
||||
return <AppLoading />;
|
||||
}
|
||||
12
desktop/src/components/workspaces/workspace.tsx
Normal file
12
desktop/src/components/workspaces/workspace.tsx
Normal file
@@ -0,0 +1,12 @@
|
||||
import React from "react";
|
||||
import {useParams} from "react-router-dom";
|
||||
|
||||
export function Workspace() {
|
||||
const { workspaceId } = useParams<{ workspaceId: string }>();
|
||||
|
||||
return (
|
||||
<div>
|
||||
<p>Workspace data here {workspaceId}</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
35
desktop/src/data/global-db.ts
Normal file
35
desktop/src/data/global-db.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import {app, ipcMain} from "electron";
|
||||
import database from 'better-sqlite3';
|
||||
import {Workspace} from "@/types/workspaces";
|
||||
|
||||
const path = app.getPath('userData');
|
||||
const globalDb = new database(`${path}/global.db`);
|
||||
|
||||
export function initGlobalDb() {
|
||||
const createWorkspacesTable = `
|
||||
CREATE TABLE IF NOT EXISTS workspaces (
|
||||
id TEXT PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
avatar TEXT,
|
||||
role TEXT NOT NULL,
|
||||
created_at DATE NOT NULL
|
||||
);
|
||||
`;
|
||||
|
||||
globalDb.exec(createWorkspacesTable);
|
||||
}
|
||||
|
||||
export function getWorkspaces(): Workspace[] {
|
||||
const stmt = globalDb.prepare<[], Workspace>('SELECT id, name, avatar, role FROM workspaces');
|
||||
return stmt.all();
|
||||
}
|
||||
|
||||
export function addWorkspace(workspace: Workspace) {
|
||||
const stmt = globalDb.prepare('INSERT INTO workspaces (id, name, avatar, role, created_at) VALUES (?, ?, ?, ?, ?)');
|
||||
stmt.run(workspace.id, workspace.name, workspace.avatar, workspace.role, new Date().toISOString());
|
||||
}
|
||||
|
||||
export function defineGlobalDbHandlers() {
|
||||
ipcMain.handle('get-workspaces', () => getWorkspaces());
|
||||
ipcMain.handle('add-workspace', (event, workspace: Workspace) => addWorkspace(workspace));
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import { app, BrowserWindow } from 'electron';
|
||||
import path from 'path';
|
||||
import {defineGlobalDbHandlers, initGlobalDb} from "@/data/global-db";
|
||||
|
||||
// Handle creating/removing shortcuts on Windows when installing/uninstalling.
|
||||
if (require('electron-squirrel-startup')) {
|
||||
@@ -7,6 +8,8 @@ if (require('electron-squirrel-startup')) {
|
||||
}
|
||||
|
||||
const createWindow = () => {
|
||||
initGlobalDb();
|
||||
|
||||
// Create the browser window.
|
||||
const mainWindow = new BrowserWindow({
|
||||
fullscreen: true,
|
||||
@@ -24,6 +27,8 @@ const createWindow = () => {
|
||||
|
||||
// Open the DevTools.
|
||||
mainWindow.webContents.openDevTools();
|
||||
|
||||
defineGlobalDbHandlers();
|
||||
};
|
||||
|
||||
// This method will be called when Electron has finished
|
||||
|
||||
@@ -1,2 +1,7 @@
|
||||
// See the Electron documentation for details on how to use preload scripts:
|
||||
// https://www.electronjs.org/docs/latest/tutorial/process-model#preload-scripts
|
||||
import { contextBridge, ipcRenderer } from 'electron';
|
||||
import {Workspace} from "@/types/workspaces";
|
||||
|
||||
contextBridge.exposeInMainWorld('globalDb', {
|
||||
getWorkspaces: () => ipcRenderer.invoke('get-workspaces'),
|
||||
addWorkspace: (workspace: Workspace) => ipcRenderer.invoke('add-workspace', workspace),
|
||||
});
|
||||
|
||||
@@ -27,6 +27,4 @@
|
||||
*/
|
||||
|
||||
import './styles/index.css';
|
||||
import './components/app'
|
||||
|
||||
console.log('👋 This message is being logged by "renderer.ts", included via Vite');
|
||||
import './components/root'
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import { configureStore } from '@reduxjs/toolkit'
|
||||
import { accountReducer } from "@/store/account-slice";
|
||||
import { workspacesReducer } from "@/store/workspaces-slice";
|
||||
|
||||
export const store = configureStore({
|
||||
reducer: {
|
||||
account: accountReducer,
|
||||
workspaces: workspacesReducer,
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
31
desktop/src/store/workspaces-slice.ts
Normal file
31
desktop/src/store/workspaces-slice.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import { createSlice } from '@reduxjs/toolkit'
|
||||
import type { PayloadAction } from '@reduxjs/toolkit'
|
||||
import {Workspace} from "@/types/workspaces";
|
||||
|
||||
export interface WorkspacesState {
|
||||
loaded: boolean;
|
||||
workspaces: Workspace[];
|
||||
}
|
||||
|
||||
const initialState: WorkspacesState = {
|
||||
loaded: false,
|
||||
workspaces: [],
|
||||
}
|
||||
|
||||
export const workspacesSlice = createSlice({
|
||||
name: 'account',
|
||||
initialState,
|
||||
reducers: {
|
||||
setWorkspaces: (state, action: PayloadAction<Workspace[]>) => {
|
||||
state.workspaces = action.payload
|
||||
state.loaded = true
|
||||
},
|
||||
addWorkspace: (state, action: PayloadAction<Workspace>) => {
|
||||
state.workspaces.push(action.payload)
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
export const { setWorkspaces, addWorkspace } = workspacesSlice.actions
|
||||
export const workspacesReducer = workspacesSlice.reducer
|
||||
|
||||
12
desktop/src/types/interface.d.ts
vendored
Normal file
12
desktop/src/types/interface.d.ts
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
import {Workspace} from "@/types/workspaces";
|
||||
|
||||
export interface GlobalDbApi {
|
||||
getWorkspaces: () => Promise<Workspace[]>
|
||||
addWorkspace: (workspace: Workspace) => Promise<void>
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
globalDb: GlobalDbApi;
|
||||
}
|
||||
}
|
||||
7
desktop/src/types/workspaces.ts
Normal file
7
desktop/src/types/workspaces.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
export type Workspace = {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
avatar?: string | null;
|
||||
role: string;
|
||||
};
|
||||
Reference in New Issue
Block a user