diff --git a/package-lock.json b/package-lock.json
index 2bafe10..1a7c207 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -16,12 +16,15 @@
"@astrojs/ts-plugin": "^1.1.3",
"@astrojs/vercel": "^5.0.1",
"@astrojs/vue": "^3.0.0",
+ "@nanostores/vue": "^0.10.0",
"@tauri-apps/api": "^1.5.0",
"@vercel/blob": "^0.13.0",
+ "@vueuse/core": "^10.4.1",
"astro": "^3.2.2",
"flowbite": "^1.8.1",
"flowbite-typography": "^1.0.3",
"jose": "^4.15.1",
+ "nanostores": "^0.9.3",
"tailwind-scrollbar": "^3.0.5",
"tailwindcss": "^3.3.3",
"typescript": "^5.2.2",
@@ -1246,6 +1249,28 @@
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
},
+ "node_modules/@nanostores/vue": {
+ "version": "0.10.0",
+ "resolved": "https://registry.npmjs.org/@nanostores/vue/-/vue-0.10.0.tgz",
+ "integrity": "sha512-832RAUbzRfHPs1CdqVEwfvgB2+RD/INji4Zo8bUSEfRO2pQRMMeq479gydnohGpRaa0oNwlfKo7TGFXCghq/1g==",
+ "engines": {
+ "node": "^18.0.0 || >=20.0.0"
+ },
+ "peerDependencies": {
+ "@nanostores/logger": ">=0.2.3",
+ "@vue/devtools-api": ">=6.5.0",
+ "nanostores": ">=0.9.2",
+ "vue": ">=3.3.1"
+ },
+ "peerDependenciesMeta": {
+ "@nanostores/logger": {
+ "optional": true
+ },
+ "@vue/devtools-api": {
+ "optional": true
+ }
+ }
+ },
"node_modules/@nodelib/fs.scandir": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@@ -1693,6 +1718,11 @@
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.0.tgz",
"integrity": "sha512-MFETx3tbTjE7Uk6vvnWINA/1iJ7LuMdO4fcq8UfF0pRbj01aGLduVvQcRyswuACJdpnHgg8E3rQLhaRdNEJS0w=="
},
+ "node_modules/@types/web-bluetooth": {
+ "version": "0.0.17",
+ "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.17.tgz",
+ "integrity": "sha512-4p9vcSmxAayx72yn70joFoL44c9MO/0+iVEBIQXe3v2h2SiAsEIo/G5v6ObFWvNKRFjbrVadNf9LqEEZeQPzdA=="
+ },
"node_modules/@types/yargs": {
"version": "17.0.26",
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.26.tgz",
@@ -1996,6 +2026,89 @@
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.3.4.tgz",
"integrity": "sha512-7OjdcV8vQ74eiz1TZLzZP4JwqM5fA94K6yntPS5Z25r9HDuGNzaGdgvwKYq6S+MxwF0TFRwe50fIR/MYnakdkQ=="
},
+ "node_modules/@vueuse/core": {
+ "version": "10.4.1",
+ "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-10.4.1.tgz",
+ "integrity": "sha512-DkHIfMIoSIBjMgRRvdIvxsyboRZQmImofLyOHADqiVbQVilP8VVHDhBX2ZqoItOgu7dWa8oXiNnScOdPLhdEXg==",
+ "dependencies": {
+ "@types/web-bluetooth": "^0.0.17",
+ "@vueuse/metadata": "10.4.1",
+ "@vueuse/shared": "10.4.1",
+ "vue-demi": ">=0.14.5"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ }
+ },
+ "node_modules/@vueuse/core/node_modules/vue-demi": {
+ "version": "0.14.6",
+ "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.6.tgz",
+ "integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==",
+ "hasInstallScript": true,
+ "bin": {
+ "vue-demi-fix": "bin/vue-demi-fix.js",
+ "vue-demi-switch": "bin/vue-demi-switch.js"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ },
+ "peerDependencies": {
+ "@vue/composition-api": "^1.0.0-rc.1",
+ "vue": "^3.0.0-0 || ^2.6.0"
+ },
+ "peerDependenciesMeta": {
+ "@vue/composition-api": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@vueuse/metadata": {
+ "version": "10.4.1",
+ "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-10.4.1.tgz",
+ "integrity": "sha512-2Sc8X+iVzeuMGHr6O2j4gv/zxvQGGOYETYXEc41h0iZXIRnRbJZGmY/QP8dvzqUelf8vg0p/yEA5VpCEu+WpZg==",
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ }
+ },
+ "node_modules/@vueuse/shared": {
+ "version": "10.4.1",
+ "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-10.4.1.tgz",
+ "integrity": "sha512-vz5hbAM4qA0lDKmcr2y3pPdU+2EVw/yzfRsBdu+6+USGa4PxqSQRYIUC9/NcT06y+ZgaTsyURw2I9qOFaaXHAg==",
+ "dependencies": {
+ "vue-demi": ">=0.14.5"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ }
+ },
+ "node_modules/@vueuse/shared/node_modules/vue-demi": {
+ "version": "0.14.6",
+ "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.6.tgz",
+ "integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==",
+ "hasInstallScript": true,
+ "bin": {
+ "vue-demi-fix": "bin/vue-demi-fix.js",
+ "vue-demi-switch": "bin/vue-demi-switch.js"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ },
+ "peerDependencies": {
+ "@vue/composition-api": "^1.0.0-rc.1",
+ "vue": "^3.0.0-0 || ^2.6.0"
+ },
+ "peerDependenciesMeta": {
+ "@vue/composition-api": {
+ "optional": true
+ }
+ }
+ },
"node_modules/abab": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz",
@@ -5876,6 +5989,20 @@
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
+ "node_modules/nanostores": {
+ "version": "0.9.3",
+ "resolved": "https://registry.npmjs.org/nanostores/-/nanostores-0.9.3.tgz",
+ "integrity": "sha512-KobZjcVyNndNrb5DAjfs0WG0lRcZu5Q1BOrfTOxokFLi25zFrWPjg+joXC6kuDqNfSt9fQwppyjUBkRPtsL+8w==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "engines": {
+ "node": "^16.0.0 || ^18.0.0 || >=20.0.0"
+ }
+ },
"node_modules/napi-build-utils": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz",
diff --git a/package.json b/package.json
index 8db8f9e..8e23002 100644
--- a/package.json
+++ b/package.json
@@ -35,12 +35,15 @@
"@astrojs/ts-plugin": "^1.1.3",
"@astrojs/vercel": "^5.0.1",
"@astrojs/vue": "^3.0.0",
+ "@nanostores/vue": "^0.10.0",
"@tauri-apps/api": "^1.5.0",
"@vercel/blob": "^0.13.0",
+ "@vueuse/core": "^10.4.1",
"astro": "^3.2.2",
"flowbite": "^1.8.1",
"flowbite-typography": "^1.0.3",
"jose": "^4.15.1",
+ "nanostores": "^0.9.3",
"tailwind-scrollbar": "^3.0.5",
"tailwindcss": "^3.3.3",
"typescript": "^5.2.2",
diff --git a/src/components/base/confirmModal.vue b/src/components/base/confirmModal.vue
new file mode 100644
index 0000000..048bc9b
--- /dev/null
+++ b/src/components/base/confirmModal.vue
@@ -0,0 +1,86 @@
+
+
+
+
+
+
+
+
+
+
+ {{ t('confirmModal.yesImSure') }}
+
+
+ {{ t('confirmModal.noCancel') }}
+
+
+
+
+
+
+
+
diff --git a/src/components/base/contextMenu.vue b/src/components/base/contextMenu.vue
new file mode 100644
index 0000000..58cf86b
--- /dev/null
+++ b/src/components/base/contextMenu.vue
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
diff --git a/src/components/base/modal.vue b/src/components/base/modal.vue
new file mode 100644
index 0000000..fdeef2d
--- /dev/null
+++ b/src/components/base/modal.vue
@@ -0,0 +1,76 @@
+
+
+
+
+
+
+
+
+ Close modal
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/base/select.vue b/src/components/base/select.vue
new file mode 100644
index 0000000..f38147a
--- /dev/null
+++ b/src/components/base/select.vue
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+ {{ error }}
+
+
+
+
+
diff --git a/src/components/base/toast.vue b/src/components/base/toast.vue
new file mode 100644
index 0000000..f14b56a
--- /dev/null
+++ b/src/components/base/toast.vue
@@ -0,0 +1,122 @@
+
+
+
+
+
+
+
+
+ Close
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/files/ContextMenu.vue b/src/components/files/ContextMenu.vue
deleted file mode 100644
index 1fb9656..0000000
--- a/src/components/files/ContextMenu.vue
+++ /dev/null
@@ -1,47 +0,0 @@
-
-
-
-
-
diff --git a/src/components/files/File.vue b/src/components/files/File.vue
deleted file mode 100644
index f7a1399..0000000
--- a/src/components/files/File.vue
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-
- {{ modelValue.name }}
-
-
-
-
-
diff --git a/src/components/files/FileBrowser.vue b/src/components/files/FileBrowser.vue
deleted file mode 100644
index 4ebccea..0000000
--- a/src/components/files/FileBrowser.vue
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/components/files/Folder.vue b/src/components/files/Folder.vue
deleted file mode 100644
index 43912fc..0000000
--- a/src/components/files/Folder.vue
+++ /dev/null
@@ -1,60 +0,0 @@
-
-
-
-
-
- {{ modelValue.name }}
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/components/item/Browser.vue b/src/components/item/Browser.vue
new file mode 100644
index 0000000..4935a90
--- /dev/null
+++ b/src/components/item/Browser.vue
@@ -0,0 +1,189 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ toast.message }}
+
+
+
+
diff --git a/src/components/item/file/EditModal.vue b/src/components/item/file/EditModal.vue
new file mode 100644
index 0000000..dac4d4a
--- /dev/null
+++ b/src/components/item/file/EditModal.vue
@@ -0,0 +1,82 @@
+
+
+ {{ t('fileBrowser.file.renameFile') }}
+
+
+
+
+
diff --git a/src/components/item/file/File.vue b/src/components/item/file/File.vue
new file mode 100644
index 0000000..be9808b
--- /dev/null
+++ b/src/components/item/file/File.vue
@@ -0,0 +1,88 @@
+
+
+
+
+
+ {{ t('fileBrowser.file.areYouSureYouWantToDeleteThisFile') }}
+
+
+
+
diff --git a/src/components/files/NoFiles.vue b/src/components/item/file/NoFiles.vue
similarity index 57%
rename from src/components/files/NoFiles.vue
rename to src/components/item/file/NoFiles.vue
index 73c2215..06177c1 100644
--- a/src/components/files/NoFiles.vue
+++ b/src/components/item/file/NoFiles.vue
@@ -27,9 +27,44 @@
SVG, PNG, JPG or GIF (MAX. 800x400px)
-
+
-
+
diff --git a/src/components/item/folder/CreateModal.vue b/src/components/item/folder/CreateModal.vue
new file mode 100644
index 0000000..eee6849
--- /dev/null
+++ b/src/components/item/folder/CreateModal.vue
@@ -0,0 +1,116 @@
+
+
+ {{ t('fileBrowser.folder.createFolder') }}
+
+
+
+
+
diff --git a/src/components/item/folder/EditModal.vue b/src/components/item/folder/EditModal.vue
new file mode 100644
index 0000000..f19495a
--- /dev/null
+++ b/src/components/item/folder/EditModal.vue
@@ -0,0 +1,121 @@
+
+
+ {{ t('fileBrowser.folder.editFolder') }}
+
+
+
+
+
diff --git a/src/components/item/folder/Folder.vue b/src/components/item/folder/Folder.vue
new file mode 100644
index 0000000..085b663
--- /dev/null
+++ b/src/components/item/folder/Folder.vue
@@ -0,0 +1,104 @@
+
+
+
+
+
+ {{ t('fileBrowser.folder.areYouSureYouWantToDeleteThisFolder') }}
+
+
+
+
diff --git a/src/lang/da.ts b/src/lang/da.ts
index db707ce..7f62c62 100644
--- a/src/lang/da.ts
+++ b/src/lang/da.ts
@@ -43,6 +43,48 @@ export default {
submit: 'Nulstil adgangskode',
},
},
+ fileBrowser: {
+ file: {
+ uploadFile: 'Upload fil',
+ renameFile: 'Omdøb fil',
+ name: 'Navn',
+ delete: 'Slet',
+ rename: 'Omdøb',
+ areYouSureYouWantToDeleteThisFile: 'Er du sikker på, at du vil slette denne fil?',
+ },
+ folder: {
+ name: 'Navn',
+ createFolder: 'Opret mappe',
+ editFolder: 'Rediger mappe',
+ create: 'Opret',
+ edit: 'Rediger',
+ share: 'Del',
+ delete: 'Slet',
+ openInNewTab: 'Åben i ny fane',
+ areYouSureYouWantToDeleteThisFolder: 'Er du sikker på, at du vil slette denne mappe?',
+ color: {
+ name: 'Farve',
+ required: 'Farve er påkrævet',
+ red: 'Rød',
+ orange: 'Orange',
+ amber: 'Rav',
+ yellow: 'Gul',
+ lime: 'Lime',
+ green: 'Grøn',
+ emerald: 'Smaragd',
+ teal: 'Blågrøn',
+ cyan: 'Cyan',
+ sky: 'Himmelblå',
+ blue: 'Blå',
+ indigo: 'Indigo',
+ violet: 'Violet',
+ purple: 'Lilla',
+ fuchsia: 'Fuchsia',
+ pink: 'Pink',
+ rose: 'Rose',
+ },
+ },
+ },
layout: {
sr: {
signOut: 'Log ud',
@@ -57,4 +99,8 @@ export default {
toggleThemeMode: 'Lys / mørk tilstand',
},
},
+ confirmModal: {
+ yesImSure: 'Ja, jeg er sikker',
+ noCancel: 'Nej, annuller',
+ },
};
diff --git a/src/lang/en.ts b/src/lang/en.ts
index 332ade0..413b0dd 100644
--- a/src/lang/en.ts
+++ b/src/lang/en.ts
@@ -43,6 +43,48 @@ export default {
submit: 'Reset password',
},
},
+ fileBrowser: {
+ file: {
+ uploadFile: 'Upload file',
+ renameFile: 'Rename file',
+ name: 'Name',
+ delete: 'Delete',
+ rename: 'Rename',
+ areYouSureYouWantToDeleteThisFile: 'Are you sure you want to delete this file?',
+ },
+ folder: {
+ name: 'Name',
+ createFolder: 'Create folder',
+ editFolder: 'Edit folder',
+ create: 'Create',
+ edit: 'Edit',
+ share: 'Share',
+ delete: 'Delete',
+ openInNewTab: 'Open in new tab',
+ areYouSureYouWantToDeleteThisFolder: 'Are you sure you want to delete this folder?',
+ color: {
+ name: 'Color',
+ required: 'Color is required',
+ red: 'Red',
+ orange: 'Orange',
+ amber: 'Amber',
+ yellow: 'Yellow',
+ lime: 'Lime',
+ green: 'Green',
+ emerald: 'Emerald',
+ teal: 'Teal',
+ cyan: 'Cyan',
+ sky: 'Sky',
+ blue: 'Blue',
+ indigo: 'Indigo',
+ violet: 'Violet',
+ purple: 'Purple',
+ fuchsia: 'Fuchsia',
+ pink: 'Pink',
+ rose: 'Rose',
+ },
+ },
+ },
layout: {
sr: {
signOut: 'Sign out',
@@ -57,4 +99,8 @@ export default {
toggleThemeMode: 'Light / dark mode',
},
},
+ confirmModal: {
+ yesImSure: 'Yes, I am sure',
+ noCancel: 'No, cancel',
+ },
};
diff --git a/src/layouts/FooterSidebar.astro b/src/layouts/FooterSidebar.astro
index f2b8d3c..3828ee1 100644
--- a/src/layouts/FooterSidebar.astro
+++ b/src/layouts/FooterSidebar.astro
@@ -2,85 +2,4 @@
import CopyrightNotice from '@components/CopyrightNotice.astro';
---
-
-
diff --git a/src/layouts/LayoutSidebar.astro b/src/layouts/LayoutSidebar.astro
index 3d44a07..cee6d39 100644
--- a/src/layouts/LayoutSidebar.astro
+++ b/src/layouts/LayoutSidebar.astro
@@ -13,7 +13,7 @@ import SideBar from './SideBar.astro';
diff --git a/src/lib/contextMenu.ts b/src/lib/contextMenu.ts
new file mode 100644
index 0000000..56f65cf
--- /dev/null
+++ b/src/lib/contextMenu.ts
@@ -0,0 +1,14 @@
+import { useEventBus, type EventBusKey } from '@vueuse/core';
+import { isModalOpen } from '@stores/modal';
+
+const contextMenuOpenEvent: EventBusKey<{ name: 'contextMenuOpen' }> = Symbol('contextMenuOpen');
+
+const bus = useEventBus(contextMenuOpenEvent);
+
+isModalOpen.listen((isOpen) => {
+ if (isOpen) {
+ bus.emit();
+ }
+});
+
+export default bus;
diff --git a/src/lib/items/files.ts b/src/lib/items/files.ts
index 021f950..339f766 100644
--- a/src/lib/items/files.ts
+++ b/src/lib/items/files.ts
@@ -1,5 +1,7 @@
import { ItemClass, type ItemType } from './items';
-import { FolderClass } from './folders';
+import { type FolderType } from './folders';
+import { upload } from '@vercel/blob/client';
+import { api } from '@lib/helpers';
export class FileClass extends ItemClass {
private _blobUrl: string;
@@ -10,23 +12,60 @@ export class FileClass extends ItemClass {
this._blobUrl = fileObject.blobUrl;
}
- static create(name: string, parent: FolderClass | null) {
- // TODO: Send request to create folder
-
- // Placeholder for now
- const returnedFile = {
- id: 1,
- name: name,
- mimeType: 'application/vnd.cloudstore.folder',
- ownerId: 43535,
- parentId: parent?.id || null,
- deletedAt: null,
- createdAt: new Date(),
- updatedAt: new Date(),
- blobUrl: 'https://www.google.com',
- };
-
- return new FileClass(returnedFile);
+ static async create(file: File, parent: FolderType | null) {
+ await upload(file.name, file, {
+ access: 'public',
+ handleUploadUrl: api('blob'),
+ clientPayload: JSON.stringify({
+ parentId: parent?.id ?? null,
+ }),
+ });
+ }
+
+ async update(input: { name: string }) {
+ const response = await fetch(api('blob'), {
+ method: 'PUT',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ credentials: 'include',
+ body: JSON.stringify({
+ id: this.id,
+ name: input.name,
+ }),
+ });
+
+ if (!response.ok) {
+ if (response.status >= 400 && response.status < 500) {
+ const json = await response.json();
+
+ throw new Error(json.error);
+ }
+
+ throw new Error(await response.text());
+ }
+
+ return new FileClass(await response.json());
+ }
+
+ async delete() {
+ const response = await fetch(api('blob/' + this.id), {
+ method: 'DELETE',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ credentials: 'include',
+ });
+
+ if (!response.ok) {
+ if (response.status >= 400 && response.status < 500) {
+ const json = await response.json();
+
+ throw new Error(json.error);
+ }
+
+ throw new Error(await response.text());
+ }
}
get blobUrl() {
diff --git a/src/lib/items/folders.ts b/src/lib/items/folders.ts
index 951629b..ac06f04 100644
--- a/src/lib/items/folders.ts
+++ b/src/lib/items/folders.ts
@@ -1,3 +1,4 @@
+import { api } from '@lib/helpers';
import { ItemClass, type ItemType } from './items';
export class FolderClass extends ItemClass {
@@ -9,23 +10,78 @@ export class FolderClass extends ItemClass {
this._color = folderObject.color;
}
- static create(name: string, parent: FolderClass | null) {
- // TODO: Send request to create folder
-
- // Placeholder for now
- const returnedFolder = {
- id: 1,
- name: name,
- mimeType: 'application/vnd.cloudstore.folder',
- ownerId: 43535,
- parentId: parent?.id || null,
- deletedAt: null,
- createdAt: new Date(),
- updatedAt: new Date(),
- color: FolderClass.randomColor(),
- };
-
- return new FolderClass(returnedFolder);
+ static async create(input: { name: string; parent: FolderType | null; color: FolderColor }) {
+ const response = await fetch(api('folder'), {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ credentials: 'include',
+ body: JSON.stringify({
+ name: input.name,
+ parentId: input.parent?.id ?? null,
+ color: input.color,
+ }),
+ });
+
+ if (!response.ok) {
+ if (response.status >= 400 && response.status < 500) {
+ const json = await response.json();
+
+ throw new Error(json.error);
+ }
+
+ throw new Error(await response.text());
+ }
+
+ return new FolderClass(await response.json());
+ }
+
+ async update(input: { name: string; color: FolderColor }) {
+ const response = await fetch(api('folder'), {
+ method: 'PUT',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ credentials: 'include',
+ body: JSON.stringify({
+ id: this.id,
+ name: input.name,
+ color: input.color,
+ }),
+ });
+
+ if (!response.ok) {
+ if (response.status >= 400 && response.status < 500) {
+ const json = await response.json();
+
+ throw new Error(json.error);
+ }
+
+ throw new Error(await response.text());
+ }
+
+ return new FolderClass(await response.json());
+ }
+
+ async delete() {
+ const response = await fetch(api('folder/' + this.id), {
+ method: 'DELETE',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ credentials: 'include',
+ });
+
+ if (!response.ok) {
+ if (response.status >= 400 && response.status < 500) {
+ const json = await response.json();
+
+ throw new Error(json.error);
+ }
+
+ throw new Error(await response.text());
+ }
}
get color() {
@@ -36,12 +92,6 @@ export class FolderClass extends ItemClass {
return FolderColors[this._color];
}
- private static randomColor() {
- return Object.keys(FolderColors)[
- Math.floor(Math.random() * Object.keys(FolderColors).length)
- ] as FolderColor;
- }
-
static isFolder(object: any): object is FolderType {
if (!ItemClass.isItem(object)) return false;
@@ -59,7 +109,7 @@ export type FolderType = {
color: FolderColor;
} & ItemType;
-const FolderColors =
{
+export const FolderColors = {
red: 'from-red-500 to-orange-500',
orange: 'from-orange-500 to-amber-500',
amber: 'from-amber-500 to-yellow-500',
@@ -78,5 +128,5 @@ const FolderColors = {
pink: 'from-pink-500 to-rose-500',
rose: 'from-rose-500 to-red-500',
};
-type FolderColor = keyof typeof FolderColors;
+export type FolderColor = keyof typeof FolderColors;
type FolderColorValue = (typeof FolderColors)[FolderColor];
diff --git a/src/lib/items/items.ts b/src/lib/items/items.ts
index 29d1b7d..b371378 100644
--- a/src/lib/items/items.ts
+++ b/src/lib/items/items.ts
@@ -35,6 +35,10 @@ export abstract class ItemClass {
return this._name;
}
+ protected set name(value: string) {
+ this._name = value;
+ }
+
get mimeType() {
return this._mimeType;
}
diff --git a/src/pages/u/folder/[id].astro b/src/pages/u/folder/[id].astro
index c1c1c64..e9b19c8 100644
--- a/src/pages/u/folder/[id].astro
+++ b/src/pages/u/folder/[id].astro
@@ -1,6 +1,7 @@
---
import LayoutSidebar from '@layouts/LayoutSidebar.astro';
-import FileBrowser from '@components/files/FileBrowser.vue';
+// @ts-ignore
+import Browser from '@components/item/Browser.vue';
// @ts-ignore https://github.com/withastro/language-tools/issues/476
import { api, url } from '@lib/helpers';
import { FolderClass } from '@lib/items/folders';
@@ -36,7 +37,7 @@ const user = Astro.locals.user as User;
---
-
-
+
+
diff --git a/src/pages/u/index.astro b/src/pages/u/index.astro
index 891cda0..e3fa003 100644
--- a/src/pages/u/index.astro
+++ b/src/pages/u/index.astro
@@ -1,13 +1,14 @@
---
import LayoutSidebar from '@layouts/LayoutSidebar.astro';
-import FileBrowser from '@components/files/FileBrowser.vue';
+// @ts-ignore
+import Browser from '@components/item/Browser.vue';
// We can safely cast this as we know that middleware would have already checked for a valid user
const user = Astro.locals.user as User;
---
-
-
+
+
diff --git a/src/stores/items.ts b/src/stores/items.ts
new file mode 100644
index 0000000..f43a2ae
--- /dev/null
+++ b/src/stores/items.ts
@@ -0,0 +1,16 @@
+import { map } from 'nanostores';
+import type { ItemClass } from '@lib/items/items';
+
+export const itemsStore = map
>({});
+
+export function addItem(item: ItemClass) {
+ itemsStore.setKey(item.id, item);
+}
+
+export function updateItem(item: ItemClass) {
+ itemsStore.setKey(item.id, item);
+}
+
+export function removeItem(item: ItemClass) {
+ itemsStore.setKey(item.id, undefined);
+}
diff --git a/src/stores/modal.ts b/src/stores/modal.ts
new file mode 100644
index 0000000..7312a06
--- /dev/null
+++ b/src/stores/modal.ts
@@ -0,0 +1,3 @@
+import { atom } from 'nanostores';
+
+export const isModalOpen = atom(false);
diff --git a/tsconfig.json b/tsconfig.json
index a2b7fc2..e8aedb7 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -10,7 +10,8 @@
"paths": {
"@components/*": ["src/components/*"],
"@layouts/*": ["src/layouts/*"],
- "@lib/*": ["src/lib/*"]
+ "@lib/*": ["src/lib/*"],
+ "@stores/*": ["src/stores/*"]
},
"strictNullChecks": true,
"verbatimModuleSyntax": true,