@hostlink/nuxt-light 1.60.6 → 1.62.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (176) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/runtime/components/L/CustomField/Add.d.vue.ts +17 -9
  3. package/dist/runtime/components/L/CustomField/Add.vue.d.ts +17 -9
  4. package/dist/runtime/components/L/CustomField/List.d.vue.ts +5 -1
  5. package/dist/runtime/components/L/CustomField/List.vue.d.ts +5 -1
  6. package/dist/runtime/components/L/Database/create-table-dialog.d.vue.ts +7 -6
  7. package/dist/runtime/components/L/Database/create-table-dialog.vue.d.ts +7 -6
  8. package/dist/runtime/components/L/Fieldset.d.vue.ts +20 -7
  9. package/dist/runtime/components/L/Fieldset.vue.d.ts +20 -7
  10. package/dist/runtime/components/L/Revision.d.vue.ts +19 -9
  11. package/dist/runtime/components/L/Revision.vue.d.ts +19 -9
  12. package/dist/runtime/components/L/Storage.d.vue.ts +11 -7
  13. package/dist/runtime/components/L/Storage.vue.d.ts +11 -7
  14. package/dist/runtime/components/L/System/Setting/authentication.d.vue.ts +11 -1
  15. package/dist/runtime/components/L/System/Setting/authentication.vue.d.ts +11 -1
  16. package/dist/runtime/components/L/System/Setting/developer.d.vue.ts +4 -1
  17. package/dist/runtime/components/L/System/Setting/developer.vue.d.ts +4 -1
  18. package/dist/runtime/components/L/System/Setting/forget-password.d.vue.ts +5 -1
  19. package/dist/runtime/components/L/System/Setting/forget-password.vue.d.ts +5 -1
  20. package/dist/runtime/components/L/System/Setting/general.d.vue.ts +6 -1
  21. package/dist/runtime/components/L/System/Setting/general.vue.d.ts +6 -1
  22. package/dist/runtime/components/L/System/Setting/mail.d.vue.ts +7 -1
  23. package/dist/runtime/components/L/System/Setting/mail.vue.d.ts +7 -1
  24. package/dist/runtime/components/L/System/Setting/modules.d.vue.ts +5 -1
  25. package/dist/runtime/components/L/System/Setting/modules.vue.d.ts +5 -1
  26. package/dist/runtime/components/L/System/Setting/security.d.vue.ts +20 -1
  27. package/dist/runtime/components/L/System/Setting/security.vue +5 -2
  28. package/dist/runtime/components/L/System/Setting/security.vue.d.ts +20 -1
  29. package/dist/runtime/components/L/ValidationInput.d.vue.ts +22 -6
  30. package/dist/runtime/components/L/ValidationInput.vue.d.ts +22 -6
  31. package/dist/runtime/components/MyTest.d.vue.ts +5 -7
  32. package/dist/runtime/components/MyTest.vue.d.ts +5 -7
  33. package/dist/runtime/components/l-add-btn.d.vue.ts +16 -10
  34. package/dist/runtime/components/l-add-btn.vue.d.ts +16 -10
  35. package/dist/runtime/components/l-alert.d.vue.ts +12 -6
  36. package/dist/runtime/components/l-alert.vue.d.ts +12 -6
  37. package/dist/runtime/components/l-app-main.d.vue.ts +10 -6
  38. package/dist/runtime/components/l-app-main.vue.d.ts +10 -6
  39. package/dist/runtime/components/l-banner.d.vue.ts +6 -3
  40. package/dist/runtime/components/l-banner.vue.d.ts +6 -3
  41. package/dist/runtime/components/l-bar.d.vue.ts +4 -1
  42. package/dist/runtime/components/l-bar.vue.d.ts +4 -1
  43. package/dist/runtime/components/l-btn.d.vue.ts +6 -1
  44. package/dist/runtime/components/l-btn.vue.d.ts +6 -1
  45. package/dist/runtime/components/l-card.d.vue.ts +16 -4
  46. package/dist/runtime/components/l-card.vue.d.ts +16 -4
  47. package/dist/runtime/components/l-checkbox.d.vue.ts +3 -1
  48. package/dist/runtime/components/l-checkbox.vue.d.ts +3 -1
  49. package/dist/runtime/components/l-col.d.vue.ts +6 -1
  50. package/dist/runtime/components/l-col.vue.d.ts +6 -1
  51. package/dist/runtime/components/l-customizer.d.vue.ts +68 -16
  52. package/dist/runtime/components/l-customizer.vue.d.ts +68 -16
  53. package/dist/runtime/components/l-date-picker.d.vue.ts +16 -3
  54. package/dist/runtime/components/l-date-picker.vue.d.ts +16 -3
  55. package/dist/runtime/components/l-delete-btn.d.vue.ts +8 -8
  56. package/dist/runtime/components/l-delete-btn.vue.d.ts +8 -8
  57. package/dist/runtime/components/l-dialog-database-field-add.d.vue.ts +7 -6
  58. package/dist/runtime/components/l-dialog-database-field-add.vue.d.ts +7 -6
  59. package/dist/runtime/components/l-dialog-upload-files.d.vue.ts +29 -0
  60. package/dist/runtime/components/l-dialog-upload-files.vue +178 -0
  61. package/dist/runtime/components/l-dialog-upload-files.vue.d.ts +29 -0
  62. package/dist/runtime/components/l-drag-drop-container.d.vue.ts +15 -7
  63. package/dist/runtime/components/l-drag-drop-container.vue.d.ts +15 -7
  64. package/dist/runtime/components/l-drag-drop-group.d.vue.ts +9 -2
  65. package/dist/runtime/components/l-drag-drop-group.vue.d.ts +9 -2
  66. package/dist/runtime/components/l-editor.d.vue.ts +11 -1
  67. package/dist/runtime/components/l-editor.vue.d.ts +11 -1
  68. package/dist/runtime/components/l-facebook-button.d.vue.ts +5 -4
  69. package/dist/runtime/components/l-facebook-button.vue.d.ts +5 -4
  70. package/dist/runtime/components/l-fav-menu.d.vue.ts +5 -7
  71. package/dist/runtime/components/l-fav-menu.vue.d.ts +5 -7
  72. package/dist/runtime/components/l-field.d.vue.ts +11 -1
  73. package/dist/runtime/components/l-field.vue.d.ts +11 -1
  74. package/dist/runtime/components/l-file-manager-breadcrumbs.d.vue.ts +10 -0
  75. package/dist/runtime/components/l-file-manager-breadcrumbs.vue +37 -0
  76. package/dist/runtime/components/l-file-manager-breadcrumbs.vue.d.ts +10 -0
  77. package/dist/runtime/components/l-file-manager-labels.d.vue.ts +4 -4
  78. package/dist/runtime/components/l-file-manager-labels.vue.d.ts +4 -4
  79. package/dist/runtime/components/l-file-manager-move.d.vue.ts +13 -9
  80. package/dist/runtime/components/l-file-manager-move.vue +68 -29
  81. package/dist/runtime/components/l-file-manager-move.vue.d.ts +13 -9
  82. package/dist/runtime/components/l-file-manager-preview.d.vue.ts +11 -9
  83. package/dist/runtime/components/l-file-manager-preview.vue +33 -23
  84. package/dist/runtime/components/l-file-manager-preview.vue.d.ts +11 -9
  85. package/dist/runtime/components/l-file-manager.d.vue.ts +45 -13
  86. package/dist/runtime/components/l-file-manager.vue +173 -256
  87. package/dist/runtime/components/l-file-manager.vue.d.ts +45 -13
  88. package/dist/runtime/components/l-file-upload.d.vue.ts +14 -3
  89. package/dist/runtime/components/l-file-upload.vue.d.ts +14 -3
  90. package/dist/runtime/components/l-file.d.vue.ts +13 -1
  91. package/dist/runtime/components/l-file.vue.d.ts +13 -1
  92. package/dist/runtime/components/l-form-dialog.d.vue.ts +57 -14
  93. package/dist/runtime/components/l-form-dialog.vue.d.ts +57 -14
  94. package/dist/runtime/components/l-form.d.vue.ts +33 -1
  95. package/dist/runtime/components/l-form.vue.d.ts +33 -1
  96. package/dist/runtime/components/l-group-select.d.vue.ts +38 -9
  97. package/dist/runtime/components/l-group-select.vue.d.ts +38 -9
  98. package/dist/runtime/components/l-icon-picker.d.vue.ts +6 -0
  99. package/dist/runtime/components/l-icon-picker.vue.d.ts +6 -0
  100. package/dist/runtime/components/l-input-select.d.vue.ts +13 -1
  101. package/dist/runtime/components/l-input-select.vue.d.ts +13 -1
  102. package/dist/runtime/components/l-input.d.vue.ts +12 -2
  103. package/dist/runtime/components/l-input.vue.d.ts +12 -2
  104. package/dist/runtime/components/l-item.d.vue.ts +5 -1
  105. package/dist/runtime/components/l-item.vue.d.ts +5 -1
  106. package/dist/runtime/components/l-link.d.vue.ts +19 -9
  107. package/dist/runtime/components/l-link.vue.d.ts +19 -9
  108. package/dist/runtime/components/l-list.d.vue.ts +5 -1
  109. package/dist/runtime/components/l-list.vue.d.ts +5 -1
  110. package/dist/runtime/components/l-login.d.vue.ts +5 -1
  111. package/dist/runtime/components/l-login.vue.d.ts +5 -1
  112. package/dist/runtime/components/l-menu.d.vue.ts +5 -7
  113. package/dist/runtime/components/l-menu.vue.d.ts +5 -7
  114. package/dist/runtime/components/l-microsoft-button.d.vue.ts +11 -1
  115. package/dist/runtime/components/l-microsoft-button.vue.d.ts +11 -1
  116. package/dist/runtime/components/l-page.d.vue.ts +9 -4
  117. package/dist/runtime/components/l-page.vue.d.ts +9 -4
  118. package/dist/runtime/components/l-repeater.d.vue.ts +75 -18
  119. package/dist/runtime/components/l-repeater.vue.d.ts +75 -18
  120. package/dist/runtime/components/l-row.d.vue.ts +3 -1
  121. package/dist/runtime/components/l-row.vue.d.ts +3 -1
  122. package/dist/runtime/components/l-select.d.vue.ts +17 -1
  123. package/dist/runtime/components/l-select.vue.d.ts +17 -1
  124. package/dist/runtime/components/l-setup-2fa-dialog.d.vue.ts +25 -11
  125. package/dist/runtime/components/l-setup-2fa-dialog.vue.d.ts +25 -11
  126. package/dist/runtime/components/l-small-box.d.vue.ts +6 -1
  127. package/dist/runtime/components/l-small-box.vue.d.ts +6 -1
  128. package/dist/runtime/components/l-statistic.d.vue.ts +14 -8
  129. package/dist/runtime/components/l-statistic.vue.d.ts +14 -8
  130. package/dist/runtime/components/l-table.d.vue.ts +29 -7
  131. package/dist/runtime/components/l-table.vue.d.ts +29 -7
  132. package/dist/runtime/components/l-tabs.d.vue.ts +4 -1
  133. package/dist/runtime/components/l-tabs.vue.d.ts +4 -1
  134. package/dist/runtime/components/l-time-picker.d.vue.ts +8 -3
  135. package/dist/runtime/components/l-time-picker.vue.d.ts +8 -3
  136. package/dist/runtime/components/user-list.d.vue.ts +5 -7
  137. package/dist/runtime/components/user-list.vue.d.ts +5 -7
  138. package/dist/runtime/composables/showUploadFilesDialog.d.ts +1 -0
  139. package/dist/runtime/composables/showUploadFilesDialog.js +11 -0
  140. package/dist/runtime/composables/useLight.d.ts +22 -22
  141. package/dist/runtime/formkit/Checkbox.d.vue.ts +5 -7
  142. package/dist/runtime/formkit/Checkbox.vue.d.ts +5 -7
  143. package/dist/runtime/formkit/DatePicker.d.vue.ts +5 -7
  144. package/dist/runtime/formkit/DatePicker.vue.d.ts +5 -7
  145. package/dist/runtime/formkit/Editor.d.vue.ts +5 -7
  146. package/dist/runtime/formkit/Editor.vue.d.ts +5 -7
  147. package/dist/runtime/formkit/File.d.vue.ts +5 -7
  148. package/dist/runtime/formkit/File.vue.d.ts +5 -7
  149. package/dist/runtime/formkit/FilePicker.d.vue.ts +5 -7
  150. package/dist/runtime/formkit/FilePicker.vue.d.ts +5 -7
  151. package/dist/runtime/formkit/FileUpload.d.vue.ts +5 -7
  152. package/dist/runtime/formkit/FileUpload.vue.d.ts +5 -7
  153. package/dist/runtime/formkit/Form.d.vue.ts +3 -1
  154. package/dist/runtime/formkit/Form.vue.d.ts +3 -1
  155. package/dist/runtime/formkit/GroupSelect.d.vue.ts +5 -7
  156. package/dist/runtime/formkit/GroupSelect.vue.d.ts +5 -7
  157. package/dist/runtime/formkit/Input.d.vue.ts +1 -1
  158. package/dist/runtime/formkit/Input.vue.d.ts +1 -1
  159. package/dist/runtime/formkit/InputSelect.d.vue.ts +1 -1
  160. package/dist/runtime/formkit/InputSelect.vue.d.ts +1 -1
  161. package/dist/runtime/formkit/InputXlsx.d.vue.ts +5 -7
  162. package/dist/runtime/formkit/InputXlsx.vue.d.ts +5 -7
  163. package/dist/runtime/formkit/OptionGroup.d.vue.ts +5 -7
  164. package/dist/runtime/formkit/OptionGroup.vue.d.ts +5 -7
  165. package/dist/runtime/formkit/Radio.d.vue.ts +5 -7
  166. package/dist/runtime/formkit/Radio.vue.d.ts +5 -7
  167. package/dist/runtime/formkit/Repeater.d.vue.ts +5 -7
  168. package/dist/runtime/formkit/Repeater.vue.d.ts +5 -7
  169. package/dist/runtime/formkit/Select.d.vue.ts +5 -7
  170. package/dist/runtime/formkit/Select.vue.d.ts +5 -7
  171. package/dist/runtime/formkit/Textarea.d.vue.ts +1 -1
  172. package/dist/runtime/formkit/Textarea.vue.d.ts +1 -1
  173. package/dist/runtime/formkit/TimePicker.d.vue.ts +5 -7
  174. package/dist/runtime/formkit/TimePicker.vue.d.ts +5 -7
  175. package/dist/runtime/pages/System/fs.vue +26 -51
  176. package/package.json +3 -3
@@ -1,43 +1,42 @@
1
1
  <script setup>
2
2
  import { useI18n } from "vue-i18n";
3
3
  import { ref, watch, computed } from "vue";
4
- import { useQuasar, format } from "quasar";
5
- import { q, m, useLight } from "#imports";
6
- import { getApiClient, getGrantedRights } from "@hostlink/light";
7
- const api = getApiClient();
8
- import { getDrive, listDrives } from "@hostlink/light";
4
+ import { useQuasar, format, date } from "quasar";
5
+ import { q, m, useLight, showUploadFilesDialog } from "#imports";
6
+ import { getGrantedRights } from "@hostlink/light";
7
+ import { fs } from "@hostlink/light";
9
8
  const { humanStorageSize } = format;
10
9
  const light = useLight();
11
10
  const i18n = useI18n();
12
11
  const $q = useQuasar();
13
12
  const emit = defineEmits(["input", "close"]);
14
- const drives = await listDrives();
13
+ const fss = await q({
14
+ app: {
15
+ fs: {
16
+ list: true
17
+ }
18
+ }
19
+ }).then((res) => res.app.fs.list);
15
20
  const folders = ref([]);
16
21
  const files = ref([]);
17
- const nodes = drives.map((drive2) => {
22
+ const nodes = fss.map((drive) => {
18
23
  return {
19
24
  icon: "sym_o_storage",
20
- name: drive2.name,
21
- id: drive2.index.toString(),
25
+ name: drive.name,
26
+ location: drive.name + "://",
22
27
  path: "/",
23
28
  lazy: true,
24
- driveIndex: drive2.index,
29
+ driveIndex: drive.index,
25
30
  type: "drive"
26
31
  };
27
32
  });
28
33
  const onLazyLoad = async ({ node, key, done, fail }) => {
29
- const folders2 = await api.drive(node.driveIndex).folders.list(node.path, {
30
- name: true,
31
- path: true
32
- });
33
- const data = folders2.map((item) => {
34
- item.driveIndex = node.driveIndex;
35
- item.id = node.driveIndex + "/" + item.path;
34
+ const folder = await fs.list(node.location);
35
+ const folders2 = folder.children.filter((item) => item.__typename === "Folder").map((item) => {
36
36
  item.lazy = true;
37
- item.type = "folder";
38
37
  return item;
39
38
  });
40
- done(data);
39
+ done(folders2);
41
40
  };
42
41
  const props = defineProps({
43
42
  closeable: Boolean,
@@ -80,7 +79,14 @@ const columns = ref([
80
79
  {
81
80
  name: "last_modified",
82
81
  label: i18n.t("Last Modified"),
83
- field: "lastModifiedHuman",
82
+ field: "lastModified",
83
+ sortable: true,
84
+ format: (value) => {
85
+ if (value) {
86
+ return date.formatDate(value * 1e3, "YYYY-MM-DD HH:mm:ss");
87
+ }
88
+ return "";
89
+ },
84
90
  align: "left"
85
91
  },
86
92
  {
@@ -88,6 +94,7 @@ const columns = ref([
88
94
  label: i18n.t("Size"),
89
95
  field: "size",
90
96
  align: "right",
97
+ sortable: true,
91
98
  format: (val) => {
92
99
  if (val == null) {
93
100
  return "";
@@ -100,104 +107,43 @@ const columns = ref([
100
107
  const localSearch = ref(null);
101
108
  const rightDrawerOpen = ref(false);
102
109
  const leftDrawerOpen = ref(false);
103
- const showDateOptions = ref(false);
104
- const exactPhrase = ref("");
105
- const hasWords = ref("");
106
- const excludeWords = ref("");
107
- const byWebsite = ref("");
108
- const byDate = ref("Any time");
109
- function onClear() {
110
- exactPhrase.value = "";
111
- hasWords.value = "";
112
- excludeWords.value = "";
113
- byWebsite.value = "";
114
- byDate.value = "Any time";
115
- }
116
- function changeDate(option) {
117
- byDate.value = option;
118
- showDateOptions.value = false;
119
- }
120
110
  function toggleLeftDrawer() {
121
111
  leftDrawerOpen.value = !leftDrawerOpen.value;
122
112
  }
123
113
  const loadItems = async () => {
124
- let path2 = selectedPath.value;
114
+ let path = selectedLocation.value;
125
115
  files.value = [];
126
116
  folders.value = [];
127
- loading.value = true;
128
- let filesParams = { path: path2 };
129
- if (label.value) {
130
- filesParams.type = label.value;
117
+ if (!path) {
118
+ return;
131
119
  }
132
- if (localSearch.value) {
133
- filesParams.search = localSearch.value;
120
+ if (label.value || localSearch.value) {
121
+ loading.value = true;
122
+ const items2 = await fs.find(localSearch.value, label.value);
123
+ loading.value = false;
124
+ files.value = items2.filter((item) => item.__typename === "File");
125
+ folders.value = items2.filter((item) => item.__typename === "Folder");
126
+ return;
134
127
  }
135
- const resp = await q({
136
- app: {
137
- drive: {
138
- __args: {
139
- index: selectedDrive.value
140
- },
141
- files: {
142
- __args: filesParams,
143
- name: true,
144
- path: true,
145
- size: true,
146
- mime: true,
147
- url: true,
148
- lastModified: true,
149
- lastModifiedHuman: true
150
- }
151
- }
152
- }
153
- });
154
- files.value = resp.app.drive.files.map((item) => {
155
- item.driveIndex = selectedDrive.value;
156
- item.type = "file";
157
- return item;
158
- });
128
+ loading.value = true;
129
+ const folder = await fs.list(path);
130
+ loading.value = false;
131
+ files.value = folder.children.filter((item) => item.__typename === "File");
159
132
  if (!label.value && !localSearch.value) {
160
- folders.value = (await drive.value.folders.list(path2)).map((item) => {
161
- item.driveIndex = selectedDrive.value;
162
- item.type = "folder";
133
+ folders.value = folder.children.filter((item) => item.__typename === "Folder").map((item) => {
163
134
  item.lazy = true;
164
- item.id = selectedDrive.value + "/" + item.path;
165
135
  return item;
166
136
  });
167
- reloadTreeFolder(selectedNodePath.value, folders.value);
137
+ reloadTreeFolder(selectedLocation.value, folders.value);
168
138
  }
169
- loading.value = false;
170
139
  };
171
140
  const label = ref(null);
172
141
  watch(label, () => {
173
142
  loadItems();
174
143
  });
175
144
  const selected = ref([]);
176
- const breadcrumbs = computed(() => {
177
- if (selectedPath.value.toString() == "") {
178
- return [];
179
- }
180
- let paths = selectedNodePath.value.split("/");
181
- let driveIndex = paths.shift();
182
- let driveName = drives.find((d) => d.index == driveIndex).name;
183
- let breadcrumbs2 = [{
184
- label: driveName,
185
- path: driveIndex
186
- }];
187
- let ps = [];
188
- for (let p of paths) {
189
- if (p) {
190
- ps.push(p);
191
- breadcrumbs2.push({
192
- label: p,
193
- path: driveIndex + "/" + ps.join("/")
194
- });
195
- }
196
- }
197
- return breadcrumbs2;
198
- });
199
145
  const onClickRow = (evt, row, index) => {
200
- if (row.type == "folder") {
146
+ if (row.__typename == "Folder") {
201
147
  preview.value = null;
202
148
  return;
203
149
  }
@@ -205,31 +151,31 @@ const onClickRow = (evt, row, index) => {
205
151
  };
206
152
  const grid = ref(false);
207
153
  const onDblclickRow = (evt, row, index) => {
208
- if (row.type == "folder") {
209
- selectedNodePath.value = row.driveIndex + "/" + row.path;
154
+ if (row.__typename == "Folder") {
155
+ selectedLocation.value = row.location;
210
156
  return;
211
157
  }
212
- if (row.type == "file") {
158
+ if (row.__typename == "File") {
213
159
  emit("input", row.path);
214
160
  }
215
161
  };
216
- const findFolder = (path2, folders2) => {
162
+ const findFolder = (path, folders2) => {
217
163
  folders2.value.forEach((item) => {
218
- if (item.path == path2) {
164
+ if (item.path == path) {
219
165
  return item;
220
166
  }
221
- let found = findFolder(path2, item.children);
167
+ let found = findFolder(path, item.children);
222
168
  if (found) {
223
169
  return found;
224
170
  }
225
171
  });
226
172
  };
227
- const reloadTreeFolder = (path2, newFolders) => {
228
- let node = folderTree.value.getNodeByKey(path2);
173
+ const reloadTreeFolder = (path, newFolders) => {
174
+ let node = folderTree.value.getNodeByKey(path);
229
175
  if (node) {
230
176
  node.lazy = false;
231
177
  node.children = newFolders;
232
- folderTree.value.setExpanded(path2, true);
178
+ folderTree.value.setExpanded(path, true);
233
179
  }
234
180
  };
235
181
  const onDeleteSelected = () => {
@@ -238,14 +184,17 @@ const onDeleteSelected = () => {
238
184
  message: "Are you sure you want to delete this files or folders?",
239
185
  cancel: true
240
186
  }).onOk(async () => {
187
+ loading.value = true;
241
188
  for (let row of selected.value) {
242
- if (row.type == "folder") {
243
- await drive.value.folders.delete(row.path);
189
+ if (row.__typename == "Folder") {
190
+ await fs.deleteFolder(row.location);
244
191
  } else {
245
- await drive.value.files.delete(row.path);
192
+ await fs.deleteFile(row.location);
246
193
  }
247
194
  }
195
+ loading.value = false;
248
196
  selected.value = [];
197
+ preview.value = null;
249
198
  await loadItems();
250
199
  });
251
200
  };
@@ -257,98 +206,83 @@ const onNewFolder = () => {
257
206
  label: "Name",
258
207
  isValid: (val) => {
259
208
  return val.length > 0;
260
- }
209
+ },
210
+ hint: "Create a new folder in " + selectedLocation.value
261
211
  },
262
212
  cancel: true
263
213
  }).onOk(async (name) => {
264
- await drive.value.folders.create(selectedPath.value + "/" + name);
214
+ loading.value = true;
215
+ await fs.createFolder(selectedLocation.value + "/" + name);
265
216
  await loadItems();
217
+ loading.value = false;
266
218
  });
267
219
  };
268
- const onDeleteRow = (row) => {
269
- if (row.type == "file") {
220
+ const onDeleteRow = (node) => {
221
+ if (node.__typename == "File") {
270
222
  $q.dialog({
271
223
  title: "Delete",
272
224
  message: "Are you sure you want to delete this file?",
273
225
  cancel: true
274
226
  }).onOk(async () => {
275
- await drive.value.files.delete(row.path);
227
+ loading.value = true;
228
+ await fs.deleteFile(node.location);
276
229
  await loadItems();
230
+ loading.value = false;
277
231
  });
278
- } else if (row.type == "folder") {
232
+ } else if (node.__typename == "Folder") {
279
233
  $q.dialog({
280
234
  title: "Delete",
281
235
  message: "Are you sure you want to delete this folder?",
282
236
  cancel: true
283
237
  }).onOk(async () => {
284
- await drive.value.folders.delete(row.path);
238
+ loading.value = true;
239
+ await fs.deleteFolder(node.location);
285
240
  await loadItems();
241
+ loading.value = false;
286
242
  });
287
243
  }
288
244
  };
289
- const onRenameRow = (row) => {
245
+ const onRenameNode = (node) => {
290
246
  $q.dialog({
291
- title: "Rename " + row.type,
247
+ title: "Rename " + node.__typename,
292
248
  prompt: {
293
249
  label: "Name",
294
- model: row.name
250
+ model: node.name
295
251
  },
296
252
  cancel: true
297
253
  }).onOk(async (name) => {
298
254
  try {
299
- if (row.type == "file") {
300
- await drive.value.files.rename(row.path, name);
255
+ if (node.__typename == "File") {
256
+ await fs.renameFile(node.location, name);
301
257
  } else {
302
- await drive.value.folders.rename(row.path, name);
258
+ await fs.renameFolder(node.location, name);
303
259
  }
260
+ await loadItems();
304
261
  } catch (e) {
305
- $q.dialog({
262
+ $q.notify({
306
263
  title: "Error",
307
- message: e.message
264
+ message: e.message,
265
+ type: "negative"
308
266
  });
309
- return;
310
267
  }
311
- await loadItems();
312
268
  });
313
269
  };
314
- const uploadFiles = ref([]);
315
- const showUploadFiles = ref(false);
316
- const onUploadFiles = async () => {
317
- $q.loading.show({
318
- message: "Uploading files..."
270
+ const openUploadDialog = () => {
271
+ showUploadFilesDialog(selectedLocation.value).onOk((files2) => {
272
+ loadItems();
319
273
  });
274
+ };
275
+ const preview = ref(null);
276
+ const moveToFolder = async (folder) => {
320
277
  try {
321
- for (let file of uploadFiles.value) {
322
- await m("lightDriveUploadFile", {
323
- index: selectedDrive.value,
324
- path: selectedPath.value,
325
- file
326
- });
278
+ for (let node of selected.value) {
279
+ await fs.move(node.location, folder);
327
280
  }
328
281
  } catch (e) {
329
282
  $q.dialog({
330
283
  title: "Error",
331
284
  message: e.message
332
285
  });
333
- $q.loading.hide();
334
- return;
335
- }
336
- uploadFiles.value = [];
337
- $q.loading.hide();
338
- showUploadFiles.value = false;
339
- await loadItems();
340
- };
341
- const preview = ref(null);
342
- const drive = computed(() => {
343
- return api.drive(selectedDrive.value);
344
- });
345
- const moveToFolder = async (folder) => {
346
- for (let row of selected.value) {
347
- if (row.type == "folder") {
348
- await drive.value.folders.move(row.path, folder);
349
- } else {
350
- await drive.value.files.move(row.path, folder);
351
- }
352
286
  }
353
287
  await loadItems();
354
288
  };
@@ -356,21 +290,14 @@ const submitSearch = (e) => {
356
290
  localSearch.value = search.value;
357
291
  loadItems();
358
292
  };
359
- const onDownloadRow = async (row) => {
360
- const base64Content = await getDrive(row.driveIndex).files.readFileAsBase64(row.path);
293
+ const onDownloadNode = async (node) => {
294
+ const base64Content = await fs.readFile(node.location, "base64");
361
295
  const downloadLink = document.createElement("a");
362
- downloadLink.href = `data:application/octet-stream;base64,${base64Content}`;
363
- downloadLink.download = row.name;
296
+ downloadLink.href = `data:${node.mimeType};base64,${base64Content}`;
297
+ downloadLink.download = node.name;
364
298
  downloadLink.click();
365
299
  };
366
300
  const search = ref(null);
367
- const reloadStorage = async () => {
368
- path.value = props.base;
369
- search.value = "";
370
- localSearch.value = "";
371
- label.value = null;
372
- await loadItems();
373
- };
374
301
  const permission = await getGrantedRights([
375
302
  "fs.folder.create",
376
303
  "fs.folder.delete",
@@ -380,19 +307,19 @@ const permission = await getGrantedRights([
380
307
  "fs.file.upload"
381
308
  ]);
382
309
  const canDeleteRow = (row) => {
383
- if (row.type == "folder" && permission.includes("fs.folder.delete")) {
310
+ if (row.__typename == "Folder" && permission.includes("fs.folder.delete")) {
384
311
  return true;
385
312
  }
386
- if (row.type == "file" && permission.includes("fs.file.delete")) {
313
+ if (row.__typename == "File" && permission.includes("fs.file.delete")) {
387
314
  return true;
388
315
  }
389
316
  return false;
390
317
  };
391
318
  const canRenameRow = (row) => {
392
- if (row.type == "folder" && permission.includes("fs.folder.rename")) {
319
+ if (row.__typename == "Folder" && permission.includes("fs.folder.rename")) {
393
320
  return true;
394
321
  }
395
- if (row.type == "file" && permission.includes("fs.file.rename")) {
322
+ if (row.__typename == "File" && permission.includes("fs.file.rename")) {
396
323
  return true;
397
324
  }
398
325
  return false;
@@ -400,18 +327,37 @@ const canRenameRow = (row) => {
400
327
  const showPreviewImgDialog = ref(false);
401
328
  const previewImg = ref(null);
402
329
  const isDark = computed(() => light.isDarkMode());
403
- const onPreview = (row) => {
330
+ const getFilePublicUrl = async (location) => {
331
+ const file = await q({
332
+ app: {
333
+ fs: {
334
+ node: {
335
+ __args: {
336
+ location
337
+ },
338
+ __typename: true,
339
+ __on: {
340
+ __typeName: "File",
341
+ publicUrl: true
342
+ }
343
+ }
344
+ }
345
+ }
346
+ }).then((res) => res.app.fs.node);
347
+ return file.publicUrl;
348
+ };
349
+ const onPreview = async (node) => {
404
350
  showPreviewImgDialog.value = true;
405
- previewImg.value = row.url;
351
+ previewImg.value = await getFilePublicUrl(node.location);
406
352
  };
407
- const onPreviewPDF = async (row) => {
353
+ const onPreviewPDF = async (node) => {
408
354
  const height = window.innerHeight - 200;
409
355
  $q.dialog({
410
356
  autoClose: true,
411
357
  fullWidth: true,
412
358
  fullHeight: true,
413
359
  title: "Preview PDF",
414
- message: "<iframe src='" + row.url + "' width='100%' height='" + height + "px'></iframe>",
360
+ message: "<iframe src='" + await getFilePublicUrl(node.location) + "' width='100%' height='" + height + "px'></iframe>",
415
361
  html: true
416
362
  });
417
363
  };
@@ -421,54 +367,41 @@ const onClickInfo = async (row) => {
421
367
  const items = computed(() => {
422
368
  return [...folders.value, ...files.value];
423
369
  });
424
- const selectedNodePath = ref(null);
425
- const selectedDrive = computed(() => {
426
- if (selectedNodePath.value) {
427
- const [driveIndex, ...path2] = selectedNodePath.value.split("/");
428
- return parseInt(driveIndex);
429
- }
430
- return null;
431
- });
432
- const selectedPath = computed(() => {
433
- if (selectedNodePath.value) {
434
- const [driveIndex, ...path2] = selectedNodePath.value.split("/");
435
- return "/" + path2.join("/");
436
- }
437
- return "";
438
- });
439
- watch(selectedNodePath, async () => {
370
+ const selectedLocation = ref(null);
371
+ watch(selectedLocation, async () => {
440
372
  selected.value = [];
441
373
  await loadItems();
442
374
  });
443
375
  const canPreview = (file) => {
444
- if (!file.mime) {
376
+ if (!file.mimeType) {
445
377
  return false;
446
378
  }
447
- return file.mime.startsWith("image/");
379
+ return file.mimeType.startsWith("image/");
448
380
  };
449
381
  const onCheckTotalSize = async (folder) => {
450
382
  const d = $q.dialog({
451
383
  title: "Total Size",
452
384
  progress: true
453
385
  });
454
- const resp = await q({
386
+ const node = await q({
455
387
  app: {
456
- drive: {
457
- __args: {
458
- index: folder.driveIndex
459
- },
460
- folder: {
388
+ fs: {
389
+ node: {
461
390
  __args: {
462
- path: folder.path
391
+ location: folder.location
463
392
  },
464
- totalSize: true
393
+ __typename: true,
394
+ name: true,
395
+ __on: {
396
+ __typeName: "Folder",
397
+ totalSize: true
398
+ }
465
399
  }
466
400
  }
467
401
  }
468
- });
469
- const size = humanStorageSize(resp.app.drive.folder.totalSize);
402
+ }).then((res) => res.app.fs.node);
470
403
  d.update({
471
- message: "Total size of folder '" + folder.name + "' is " + size,
404
+ message: "Total size of folder '" + node.name + "' is " + humanStorageSize(node.totalSize),
472
405
  progress: false
473
406
  });
474
407
  };
@@ -494,7 +427,7 @@ const onDuplicateFile = async (file) => {
494
427
  const onDrop = (event) => {
495
428
  event.preventDefault();
496
429
  event.stopPropagation();
497
- if (selectedNodePath.value == null) {
430
+ if (selectedLocation.value == null) {
498
431
  $q.notify({
499
432
  type: "warning",
500
433
  message: "Please select a folder to upload files."
@@ -503,18 +436,19 @@ const onDrop = (event) => {
503
436
  }
504
437
  const files2 = event.dataTransfer.files;
505
438
  console.log("Dropped files:", files2);
506
- uploadFiles.value = [];
507
- for (let i = 0; i < files2.length; i++) {
508
- uploadFiles.value.push(files2[i]);
439
+ if (files2.length > 0) {
440
+ const fileList = Array.from(files2);
441
+ showUploadFilesDialog(selectedLocation.value, fileList).onOk((uploadedFiles) => {
442
+ loadItems();
443
+ });
509
444
  }
510
- showUploadFiles.value = true;
511
445
  dragzone.value.style.border = "none";
512
446
  };
513
447
  const dragzone = ref(null);
514
448
  const onDragover = (event) => {
515
449
  event.preventDefault();
516
450
  event.stopPropagation();
517
- if (selectedNodePath.value == null) {
451
+ if (selectedLocation.value == null) {
518
452
  return;
519
453
  }
520
454
  dragzone.value.style.border = "2px dashed #1976d2";
@@ -522,21 +456,24 @@ const onDragover = (event) => {
522
456
  const onDragLeave = (event) => {
523
457
  event.preventDefault();
524
458
  event.stopPropagation();
525
- if (selectedNodePath.value == null) {
459
+ if (selectedLocation.value == null) {
526
460
  return;
527
461
  }
528
462
  dragzone.value.style.border = "none";
529
463
  };
530
464
  const getFileIcon = (file) => {
531
- if (file.mime.startsWith("image/")) {
465
+ if (!file.mimeType) {
466
+ return "sym_o_description";
467
+ }
468
+ if (file.mimeType.startsWith("image/")) {
532
469
  return "sym_o_image";
533
- } else if (file.mime === "application/pdf") {
470
+ } else if (file.mimeType === "application/pdf") {
534
471
  return "sym_o_picture_as_pdf";
535
- } else if (file.mime.startsWith("video/")) {
472
+ } else if (file.mimeType.startsWith("video/")) {
536
473
  return "sym_o_videocam";
537
- } else if (file.mime.startsWith("audio/")) {
474
+ } else if (file.mimeType.startsWith("audio/")) {
538
475
  return "sym_o_audiotrack";
539
- } else if (file.mime === "application/zip" || file.mime === "application/x-rar-compressed") {
476
+ } else if (file.mimeType === "application/zip" || file.mimeType === "application/x-rar-compressed") {
540
477
  return "sym_o_archive";
541
478
  } else {
542
479
  return "sym_o_description";
@@ -573,7 +510,7 @@ const getFileIcon = (file) => {
573
510
  <q-list padding class="text-grey-8">
574
511
  <q-item>
575
512
  <q-item-section>
576
- <l-btn icon="add" label="New" :disable="!selectedNodePath">
513
+ <l-btn icon="add" label="New" :disable="!selectedLocation">
577
514
  <q-menu>
578
515
  <q-list>
579
516
  <q-item clickable v-close-popup @click="onNewFolder" v-if="permission.includes('fs.folder.create')">
@@ -583,7 +520,7 @@ const getFileIcon = (file) => {
583
520
  <q-item-section>{{ $t('Folder') }}</q-item-section>
584
521
  </q-item>
585
522
  <q-separator />
586
- <q-item clickable v-close-popup @click="showUploadFiles = true"
523
+ <q-item clickable v-close-popup @click="openUploadDialog"
587
524
  v-if="permission.includes('fs.file.upload')">
588
525
  <q-item-section avatar>
589
526
  <q-icon name="sym_o_upload_file"></q-icon>
@@ -596,8 +533,8 @@ const getFileIcon = (file) => {
596
533
  </q-item-section>
597
534
  </q-item>
598
535
 
599
- <q-tree ref="folderTree" :nodes="nodes" node-key="id" label-key="name" @lazy-load="onLazyLoad"
600
- v-model:selected="selectedNodePath" no-selection-unset>
536
+ <q-tree ref="folderTree" :nodes="nodes" node-key="location" label-key="name" @lazy-load="onLazyLoad"
537
+ v-model:selected="selectedLocation" no-selection-unset>
601
538
  </q-tree>
602
539
 
603
540
  <q-separator inset class="q-my-sm" />
@@ -608,7 +545,7 @@ const getFileIcon = (file) => {
608
545
  </q-drawer>
609
546
 
610
547
  <q-drawer v-model="rightDrawerOpen" side="right" show-if-above bordered>
611
- <l-file-manager-preview :path="preview.path" v-if="preview" :key="preview.path" :drive-index="selectedDrive" />
548
+ <l-file-manager-preview :location="preview.location" v-if="preview" :key="preview.location" />
612
549
  </q-drawer>
613
550
 
614
551
  <q-page-container :style="{ height }">
@@ -622,33 +559,12 @@ const getFileIcon = (file) => {
622
559
  </q-card>
623
560
  </q-dialog>
624
561
 
625
- <q-dialog v-model="showUploadFiles" persistent transition-show="scale" transition-hide="scale">
626
- <q-card style="min-width: 400px;">
627
- <q-toolbar>
628
- <q-toolbar-title>{{ $t('Upload Files') }}</q-toolbar-title>
629
- <q-space></q-space>
630
- <q-btn flat round dense icon="sym_o_close" v-close-popup></q-btn>
631
- </q-toolbar>
632
- <q-card-section>
633
- <q-file ref="file" v-model="uploadFiles" multiple name="file" label="Files" color="primary"></q-file>
634
- </q-card-section>
635
-
636
- <q-card-actions align="right">
637
- <q-btn flat :label="$t('Cancel')" color="primary" v-close-popup></q-btn>
638
- <q-btn flat :label="$t('Upload')" color="primary" @click="onUploadFiles"></q-btn>
639
- </q-card-actions>
640
- </q-card>
641
- </q-dialog>
642
-
643
562
  <q-toolbar>
644
- <q-breadcrumbs>
645
- <q-breadcrumbs-el v-for="(b, index) in breadcrumbs" :label="b.label" :key="index"
646
- @click="selectedNodePath = b.path" href="javascript:void(0)"></q-breadcrumbs-el>
647
- </q-breadcrumbs>
563
+ <l-file-manager-breadcrumbs v-model="selectedLocation" />
648
564
  <q-space></q-space>
649
-
650
565
  <q-btn flat round icon="sym_o_drive_file_move" v-if="selected.length > 0">
651
- <l-file-manager-move @selected="moveToFolder($event)" :drive-index="selectedDrive" />
566
+ <l-file-manager-move @selected="moveToFolder($event)" :current_location="selectedLocation"
567
+ :allow_cross_fs="selected.every(item => item.__typename == 'File')" />
652
568
  <q-tooltip>
653
569
  {{ $t('Move to') }}
654
570
  </q-tooltip>
@@ -668,7 +584,7 @@ const getFileIcon = (file) => {
668
584
 
669
585
  <template v-if="grid">
670
586
  <q-table :title="$t('Folders')" flat grid :columns="columns" :rows="folders" hide-pagination
671
- :pagination="{ rowsPerPage: 0 }">
587
+ :pagination="{ rowsPerPage: 0 }" row-key="location">
672
588
  <template v-slot:item="props">
673
589
  <div class="q-pa-xs col-xs-12 col-sm-6 col-md-4" @click="onDblclickRow(null, props.row, null)">
674
590
  <q-card flat bordered>
@@ -689,14 +605,14 @@ const getFileIcon = (file) => {
689
605
  </q-table>
690
606
 
691
607
  <q-table :title="$t('Files')" flat grid :columns="columns" :rows="files" hide-pagination
692
- :pagination="{ rowsPerPage: 0 }">
608
+ :pagination="{ rowsPerPage: 0 }" row-key="location">
693
609
 
694
610
  <template v-slot:item="props">
695
611
  <div class="q-pa-xs col-xs-12 col-sm-6 col-md-4" @click="onClickRow(null, props.row, null)">
696
612
  <q-card flat bordered>
697
613
  <q-item>
698
614
  <q-item-section avatar>
699
- <q-icon :name="getFileIcon(props.row)" size="sm"></q-icon>
615
+ <q-icon :name="getFileIcon(props.row)" size="sm"></q-icon>
700
616
  </q-item-section>
701
617
  <q-item-section>
702
618
  <q-item-label lines="1">
@@ -718,12 +634,12 @@ const getFileIcon = (file) => {
718
634
  <template v-else>
719
635
 
720
636
  <q-table flat :columns="columns" :rows="items" @row-dblclick="onDblclickRow" @row-click="onClickRow"
721
- :pagination="pagination" row-key="path" selection="multiple" v-model:selected="selected" dense
637
+ :pagination="pagination" row-key="location" selection="multiple" v-model:selected="selected" dense
722
638
  :loading="loading" :loading-label="$t('Loading...')" :no-data-label="$t('No data available')"
723
639
  separator="horizontal" :rows-per-page-options="[0]" color="primary">
724
640
  <template #body-cell-icon="props">
725
641
  <q-td auto-width>
726
- <q-icon name="sym_o_folder" v-if="props.value == 'folder'" size="sm" />
642
+ <q-icon name="sym_o_folder" v-if="props.row.__typename == 'Folder'" size="sm" />
727
643
  <q-icon :name="getFileIcon(props.row)" v-else size="sm" />
728
644
  </q-td>
729
645
  </template>
@@ -735,7 +651,7 @@ const getFileIcon = (file) => {
735
651
  <q-list>
736
652
 
737
653
  <q-item clickable v-close-popup="true" @click="onCheckTotalSize(props.row)"
738
- v-if="props.row.type == 'folder'">
654
+ v-if="props.row.__typename == 'Folder'">
739
655
  <q-item-section avatar>
740
656
  <q-icon name="sym_o_info"></q-icon>
741
657
  </q-item-section>
@@ -749,14 +665,15 @@ const getFileIcon = (file) => {
749
665
  <q-item-section>{{ $t('Delete') }}</q-item-section>
750
666
  </q-item>
751
667
 
752
- <q-item v-if="props.row.type == 'file'" clickable v-close-popup @click="onDownloadRow(props.row)">
668
+ <q-item v-if="props.row.__typename == 'File'" clickable v-close-popup
669
+ @click="onDownloadNode(props.row)">
753
670
  <q-item-section avatar>
754
671
  <q-icon name="sym_o_download"></q-icon>
755
672
  </q-item-section>
756
673
  <q-item-section>{{ $t('Download') }}</q-item-section>
757
674
  </q-item>
758
675
 
759
- <q-item clickable v-close-popup @click="onRenameRow(props.row)" v-if="canRenameRow(props.row)">
676
+ <q-item clickable v-close-popup @click="onRenameNode(props.row)" v-if="canRenameRow(props.row)">
760
677
  <q-item-section avatar>
761
678
  <q-icon name="sym_o_edit"></q-icon>
762
679
  </q-item-section>
@@ -764,7 +681,7 @@ const getFileIcon = (file) => {
764
681
  </q-item>
765
682
 
766
683
  <q-item clickable v-close-popup @click="onDuplicateFile(props.row)"
767
- v-if="props.row.type == 'file'">
684
+ v-if="props.row.__typename == 'File'">
768
685
  <q-item-section avatar>
769
686
  <q-icon name="sym_o_content_copy"></q-icon>
770
687
  </q-item-section>
@@ -778,7 +695,7 @@ const getFileIcon = (file) => {
778
695
  <q-item-section>{{ $t('Preview') }}</q-item-section>
779
696
  </q-item>
780
697
 
781
- <q-item clickable v-close-popup v-if="props.row.mime == 'application/pdf'"
698
+ <q-item clickable v-close-popup v-if="props.row.mimeType == 'application/pdf'"
782
699
  @click="onPreviewPDF(props.row)">
783
700
  <q-item-section avatar>
784
701
  <q-icon name="sym_o_preview"></q-icon>