@hostlink/nuxt-light 1.61.0 → 1.62.1
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.
- package/dist/module.json +1 -1
- package/dist/runtime/components/l-date-picker.d.vue.ts +2 -2
- package/dist/runtime/components/l-date-picker.vue +47 -40
- package/dist/runtime/components/l-date-picker.vue.d.ts +2 -2
- package/dist/runtime/components/l-dialog-upload-files.d.vue.ts +29 -0
- package/dist/runtime/components/l-dialog-upload-files.vue +178 -0
- package/dist/runtime/components/l-dialog-upload-files.vue.d.ts +29 -0
- package/dist/runtime/components/l-file-manager-breadcrumbs.d.vue.ts +10 -0
- package/dist/runtime/components/l-file-manager-breadcrumbs.vue +37 -0
- package/dist/runtime/components/l-file-manager-breadcrumbs.vue.d.ts +10 -0
- package/dist/runtime/components/l-file-manager-move.d.vue.ts +7 -3
- package/dist/runtime/components/l-file-manager-move.vue +68 -29
- package/dist/runtime/components/l-file-manager-move.vue.d.ts +7 -3
- package/dist/runtime/components/l-file-manager-preview.d.vue.ts +3 -13
- package/dist/runtime/components/l-file-manager-preview.vue +33 -23
- package/dist/runtime/components/l-file-manager-preview.vue.d.ts +3 -13
- package/dist/runtime/components/l-file-manager.vue +173 -256
- package/dist/runtime/composables/showUploadFilesDialog.d.ts +1 -0
- package/dist/runtime/composables/showUploadFilesDialog.js +11 -0
- package/dist/runtime/pages/System/fs.vue +26 -51
- package/package.json +2 -2
package/dist/module.json
CHANGED
|
@@ -5,9 +5,9 @@ type __VLS_ModelProps = {
|
|
|
5
5
|
modelValue?: any;
|
|
6
6
|
};
|
|
7
7
|
type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
|
|
8
|
-
declare var
|
|
8
|
+
declare var __VLS_38: string, __VLS_39: any;
|
|
9
9
|
type __VLS_Slots = {} & {
|
|
10
|
-
[K in NonNullable<typeof
|
|
10
|
+
[K in NonNullable<typeof __VLS_38>]?: (props: typeof __VLS_39) => any;
|
|
11
11
|
};
|
|
12
12
|
declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
13
13
|
"update:modelValue": (value: any) => any;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
-
import { ref, computed, watch } from "vue";
|
|
2
|
+
import { ref, computed, watch, nextTick } from "vue";
|
|
3
3
|
import { useLight } from "#imports";
|
|
4
4
|
import { QInput } from "quasar";
|
|
5
5
|
const modelValue = defineModel({ type: null, ...{
|
|
@@ -88,49 +88,29 @@ const props = defineProps({
|
|
|
88
88
|
});
|
|
89
89
|
const light = useLight();
|
|
90
90
|
const popup = ref(null);
|
|
91
|
+
const inputValue = ref("");
|
|
92
|
+
const isInternalUpdate = ref(false);
|
|
93
|
+
function modelToString(val) {
|
|
94
|
+
if (!val) return "";
|
|
95
|
+
if (typeof val === "object" && val.from) {
|
|
96
|
+
return val.from + (val.to ? " to " + val.to : "");
|
|
97
|
+
}
|
|
98
|
+
return val || "";
|
|
99
|
+
}
|
|
91
100
|
watch(modelValue, (newVal) => {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
get: () => {
|
|
96
|
-
if (!modelValue.value) {
|
|
97
|
-
return modelValue.value;
|
|
98
|
-
}
|
|
99
|
-
if (typeof modelValue.value === "object") {
|
|
100
|
-
let s = modelValue.value.from;
|
|
101
|
-
if (modelValue.value.to) {
|
|
102
|
-
s += " to " + modelValue.value.to;
|
|
103
|
-
}
|
|
104
|
-
return s;
|
|
105
|
-
}
|
|
106
|
-
return modelValue.value;
|
|
107
|
-
},
|
|
108
|
-
set: (val) => {
|
|
109
|
-
if (props.range) {
|
|
110
|
-
if (val == null || val == "") {
|
|
111
|
-
modelValue.value = null;
|
|
112
|
-
return;
|
|
113
|
-
}
|
|
114
|
-
const parts = val.split(" to ");
|
|
115
|
-
if (parts.length == 2) {
|
|
116
|
-
const from = parts[0];
|
|
117
|
-
const to = parts[1];
|
|
118
|
-
if (from.match(/^\d{4}-\d{2}-\d{2}$/) && to.match(/^\d{4}-\d{2}-\d{2}$/)) {
|
|
119
|
-
modelValue.value = { from, to };
|
|
120
|
-
return;
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
modelValue.value = null;
|
|
124
|
-
return;
|
|
125
|
-
}
|
|
126
|
-
modelValue.value = val;
|
|
101
|
+
if (isInternalUpdate.value) {
|
|
102
|
+
isInternalUpdate.value = false;
|
|
103
|
+
return;
|
|
127
104
|
}
|
|
128
|
-
|
|
105
|
+
inputValue.value = modelToString(newVal);
|
|
106
|
+
popup.value?.hide();
|
|
107
|
+
}, { deep: true, immediate: true });
|
|
129
108
|
const inputMask = computed(() => {
|
|
130
109
|
if (!props.range) {
|
|
131
110
|
return "####-##-##";
|
|
111
|
+
} else {
|
|
112
|
+
return "####-##-## to ####-##-##";
|
|
132
113
|
}
|
|
133
|
-
return "";
|
|
134
114
|
});
|
|
135
115
|
const inputRules = computed(() => {
|
|
136
116
|
const rules = [];
|
|
@@ -147,7 +127,8 @@ const inputRules = computed(() => {
|
|
|
147
127
|
return null;
|
|
148
128
|
});
|
|
149
129
|
const inputProps = computed(() => {
|
|
150
|
-
const { mask, locale, calendar, modelValue: modelValue2, defautYearMonth, defaultView, events, ...rest } = light.getInputProps(props);
|
|
130
|
+
const { mask, locale, calendar, modelValue: modelValue2, defautYearMonth, defaultView, events, emitImmediately, ...rest } = light.getInputProps(props);
|
|
131
|
+
delete rest["onUpdate:modelValue"];
|
|
151
132
|
return rest;
|
|
152
133
|
});
|
|
153
134
|
const dateProps = computed(() => {
|
|
@@ -183,10 +164,36 @@ const dateProps = computed(() => {
|
|
|
183
164
|
} = props;
|
|
184
165
|
return rest;
|
|
185
166
|
});
|
|
167
|
+
const onUpdateInput = (val) => {
|
|
168
|
+
isInternalUpdate.value = true;
|
|
169
|
+
if (props.range) {
|
|
170
|
+
if (val == null || val === "") {
|
|
171
|
+
modelValue.value = null;
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
const parts = val.split(" to ");
|
|
175
|
+
if (parts.length === 2) {
|
|
176
|
+
const from = parts[0] || "";
|
|
177
|
+
const to = parts[1] || "";
|
|
178
|
+
if (from.match(/^\d{4}-\d{2}-\d{2}$/) && to.match(/^\d{4}-\d{2}-\d{2}$/)) {
|
|
179
|
+
modelValue.value = { from, to };
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
if (from.match(/^\d{4}-\d{2}-\d{2}$/) && to === "") {
|
|
183
|
+
modelValue.value = from;
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
modelValue.value = null;
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
modelValue.value = val;
|
|
191
|
+
};
|
|
186
192
|
</script>
|
|
187
193
|
|
|
188
194
|
<template>
|
|
189
|
-
<q-input
|
|
195
|
+
<q-input :mask="inputMask" :rules="inputRules" v-bind="inputProps" @update:model-value="onUpdateInput"
|
|
196
|
+
v-model="inputValue">
|
|
190
197
|
<template v-slot:prepend>
|
|
191
198
|
<q-icon name="sym_o_event" class="cursor-pointer">
|
|
192
199
|
<q-popup-proxy cover transition-show="scale" transition-hide="scale" ref="popup">
|
|
@@ -5,9 +5,9 @@ type __VLS_ModelProps = {
|
|
|
5
5
|
modelValue?: any;
|
|
6
6
|
};
|
|
7
7
|
type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
|
|
8
|
-
declare var
|
|
8
|
+
declare var __VLS_38: string, __VLS_39: any;
|
|
9
9
|
type __VLS_Slots = {} & {
|
|
10
|
-
[K in NonNullable<typeof
|
|
10
|
+
[K in NonNullable<typeof __VLS_38>]?: (props: typeof __VLS_39) => any;
|
|
11
11
|
};
|
|
12
12
|
declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
13
13
|
"update:modelValue": (value: any) => any;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
declare const _default: typeof __VLS_export;
|
|
2
|
+
export default _default;
|
|
3
|
+
declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
4
|
+
selectedLocation: {
|
|
5
|
+
type: StringConstructor;
|
|
6
|
+
required: true;
|
|
7
|
+
};
|
|
8
|
+
initialFiles: {
|
|
9
|
+
type: ArrayConstructor;
|
|
10
|
+
default: () => never[];
|
|
11
|
+
};
|
|
12
|
+
}>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
13
|
+
hide: (...args: any[]) => void;
|
|
14
|
+
ok: (...args: any[]) => void;
|
|
15
|
+
}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
16
|
+
selectedLocation: {
|
|
17
|
+
type: StringConstructor;
|
|
18
|
+
required: true;
|
|
19
|
+
};
|
|
20
|
+
initialFiles: {
|
|
21
|
+
type: ArrayConstructor;
|
|
22
|
+
default: () => never[];
|
|
23
|
+
};
|
|
24
|
+
}>> & Readonly<{
|
|
25
|
+
onHide?: ((...args: any[]) => any) | undefined;
|
|
26
|
+
onOk?: ((...args: any[]) => any) | undefined;
|
|
27
|
+
}>, {
|
|
28
|
+
initialFiles: unknown[];
|
|
29
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { useDialogPluginComponent } from "quasar";
|
|
3
|
+
import { ref, onMounted } from "vue";
|
|
4
|
+
import { useQuasar } from "quasar";
|
|
5
|
+
import { fs } from "@hostlink/light";
|
|
6
|
+
const props = defineProps({
|
|
7
|
+
selectedLocation: {
|
|
8
|
+
type: String,
|
|
9
|
+
required: true
|
|
10
|
+
},
|
|
11
|
+
initialFiles: {
|
|
12
|
+
type: Array,
|
|
13
|
+
default: () => []
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
defineEmits([
|
|
17
|
+
...useDialogPluginComponent.emits
|
|
18
|
+
]);
|
|
19
|
+
const { dialogRef, onDialogHide, onDialogOK, onDialogCancel } = useDialogPluginComponent();
|
|
20
|
+
const $q = useQuasar();
|
|
21
|
+
const uploadFiles = ref([]);
|
|
22
|
+
const uploadProgress = ref({});
|
|
23
|
+
onMounted(() => {
|
|
24
|
+
if (props.initialFiles && props.initialFiles.length > 0) {
|
|
25
|
+
uploadFiles.value = props.initialFiles;
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
const initializeUploadProgress = () => {
|
|
29
|
+
uploadProgress.value = {};
|
|
30
|
+
uploadFiles.value.forEach((file, index) => {
|
|
31
|
+
uploadProgress.value[index] = {
|
|
32
|
+
name: file.name,
|
|
33
|
+
status: "pending",
|
|
34
|
+
// pending, uploading, completed, failed
|
|
35
|
+
error: null,
|
|
36
|
+
progress: 0
|
|
37
|
+
};
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
const onUploadFiles = async () => {
|
|
41
|
+
initializeUploadProgress();
|
|
42
|
+
try {
|
|
43
|
+
const uploadPromises = uploadFiles.value.map(
|
|
44
|
+
(file, index) => (async () => {
|
|
45
|
+
try {
|
|
46
|
+
uploadProgress.value[index].status = "uploading";
|
|
47
|
+
await fs.uploadFile(props.selectedLocation, file);
|
|
48
|
+
uploadProgress.value[index].status = "completed";
|
|
49
|
+
uploadProgress.value[index].progress = 100;
|
|
50
|
+
} catch (error) {
|
|
51
|
+
uploadProgress.value[index].status = "failed";
|
|
52
|
+
uploadProgress.value[index].error = error?.message || String(error);
|
|
53
|
+
}
|
|
54
|
+
})()
|
|
55
|
+
);
|
|
56
|
+
await Promise.allSettled(uploadPromises);
|
|
57
|
+
const failedUploads = Object.values(uploadProgress.value).filter((p) => p.status === "failed");
|
|
58
|
+
if (failedUploads.length === 0) {
|
|
59
|
+
setTimeout(() => {
|
|
60
|
+
onDialogOK(uploadFiles.value);
|
|
61
|
+
uploadProgress.value = {};
|
|
62
|
+
}, 1e3);
|
|
63
|
+
}
|
|
64
|
+
} catch (e) {
|
|
65
|
+
$q.dialog({
|
|
66
|
+
title: "Error",
|
|
67
|
+
message: e.message
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
const onCancel = () => {
|
|
72
|
+
uploadProgress.value = {};
|
|
73
|
+
uploadFiles.value = [];
|
|
74
|
+
onDialogCancel();
|
|
75
|
+
};
|
|
76
|
+
</script>
|
|
77
|
+
|
|
78
|
+
<template>
|
|
79
|
+
<q-dialog ref="dialogRef" @hide="onDialogHide">
|
|
80
|
+
<q-card style="min-width: 400px;">
|
|
81
|
+
<q-toolbar>
|
|
82
|
+
<q-toolbar-title>{{ $t('Upload Files') }}</q-toolbar-title>
|
|
83
|
+
<q-space></q-space>
|
|
84
|
+
<q-btn
|
|
85
|
+
flat
|
|
86
|
+
round
|
|
87
|
+
dense
|
|
88
|
+
icon="sym_o_close"
|
|
89
|
+
v-close-popup
|
|
90
|
+
:disable="uploadFiles.length > 0 && Object.values(uploadProgress).some(p => p.status === 'uploading')"
|
|
91
|
+
></q-btn>
|
|
92
|
+
</q-toolbar>
|
|
93
|
+
<q-card-section>
|
|
94
|
+
<!-- 顯示上傳進度 -->
|
|
95
|
+
<div v-if="Object.keys(uploadProgress).length > 0" class="q-mb-md">
|
|
96
|
+
<q-list bordered separator>
|
|
97
|
+
<q-item v-for="(progress, index) in uploadProgress" :key="index">
|
|
98
|
+
<q-item-section avatar>
|
|
99
|
+
<q-icon
|
|
100
|
+
v-if="progress.status === 'completed'"
|
|
101
|
+
name="sym_o_check_circle"
|
|
102
|
+
color="positive"
|
|
103
|
+
size="md"
|
|
104
|
+
/>
|
|
105
|
+
<q-icon
|
|
106
|
+
v-else-if="progress.status === 'failed'"
|
|
107
|
+
name="sym_o_error"
|
|
108
|
+
color="negative"
|
|
109
|
+
size="md"
|
|
110
|
+
/>
|
|
111
|
+
<q-icon
|
|
112
|
+
v-else-if="progress.status === 'uploading'"
|
|
113
|
+
name="sym_o_cloud_upload"
|
|
114
|
+
color="primary"
|
|
115
|
+
size="md"
|
|
116
|
+
/>
|
|
117
|
+
<q-icon
|
|
118
|
+
v-else
|
|
119
|
+
name="sym_o_schedule"
|
|
120
|
+
color="grey"
|
|
121
|
+
size="md"
|
|
122
|
+
/>
|
|
123
|
+
</q-item-section>
|
|
124
|
+
|
|
125
|
+
<q-item-section>
|
|
126
|
+
<q-item-label>{{ progress.name }}</q-item-label>
|
|
127
|
+
<q-item-label caption v-if="progress.status === 'uploading'">
|
|
128
|
+
上傳中...
|
|
129
|
+
</q-item-label>
|
|
130
|
+
<q-item-label caption v-else-if="progress.status === 'completed'" class="text-positive">
|
|
131
|
+
上傳完成
|
|
132
|
+
</q-item-label>
|
|
133
|
+
<q-item-label caption v-else-if="progress.status === 'failed'" class="text-negative">
|
|
134
|
+
{{ progress.error }}
|
|
135
|
+
</q-item-label>
|
|
136
|
+
<q-item-label caption v-else>
|
|
137
|
+
等待中...
|
|
138
|
+
</q-item-label>
|
|
139
|
+
|
|
140
|
+
<q-linear-progress
|
|
141
|
+
v-if="progress.status === 'uploading' || progress.status === 'completed'"
|
|
142
|
+
:value="progress.progress / 100"
|
|
143
|
+
:color="progress.status === 'completed' ? 'positive' : 'primary'"
|
|
144
|
+
class="q-mt-xs"
|
|
145
|
+
stripe
|
|
146
|
+
rounded
|
|
147
|
+
/>
|
|
148
|
+
</q-item-section>
|
|
149
|
+
</q-item>
|
|
150
|
+
</q-list>
|
|
151
|
+
</div>
|
|
152
|
+
|
|
153
|
+
<!-- 未上傳時顯示檔案選擇 -->
|
|
154
|
+
<div v-else>
|
|
155
|
+
<q-file v-model="uploadFiles" multiple name="file" :label="$t('Files')" color="primary" outlined />
|
|
156
|
+
</div>
|
|
157
|
+
</q-card-section>
|
|
158
|
+
|
|
159
|
+
<q-card-actions align="right">
|
|
160
|
+
<q-btn
|
|
161
|
+
flat
|
|
162
|
+
:label="$t('Cancel')"
|
|
163
|
+
color="primary"
|
|
164
|
+
v-close-popup
|
|
165
|
+
@click="onCancel"
|
|
166
|
+
:disable="uploadFiles.length > 0 && Object.values(uploadProgress).some(p => p.status === 'uploading')"
|
|
167
|
+
></q-btn>
|
|
168
|
+
<q-btn
|
|
169
|
+
flat
|
|
170
|
+
:label="$t('Upload')"
|
|
171
|
+
color="primary"
|
|
172
|
+
@click="onUploadFiles"
|
|
173
|
+
:disable="uploadFiles.length === 0 || Object.keys(uploadProgress).length > 0"
|
|
174
|
+
></q-btn>
|
|
175
|
+
</q-card-actions>
|
|
176
|
+
</q-card>
|
|
177
|
+
</q-dialog>
|
|
178
|
+
</template>
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
declare const _default: typeof __VLS_export;
|
|
2
|
+
export default _default;
|
|
3
|
+
declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
4
|
+
selectedLocation: {
|
|
5
|
+
type: StringConstructor;
|
|
6
|
+
required: true;
|
|
7
|
+
};
|
|
8
|
+
initialFiles: {
|
|
9
|
+
type: ArrayConstructor;
|
|
10
|
+
default: () => never[];
|
|
11
|
+
};
|
|
12
|
+
}>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
13
|
+
hide: (...args: any[]) => void;
|
|
14
|
+
ok: (...args: any[]) => void;
|
|
15
|
+
}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
16
|
+
selectedLocation: {
|
|
17
|
+
type: StringConstructor;
|
|
18
|
+
required: true;
|
|
19
|
+
};
|
|
20
|
+
initialFiles: {
|
|
21
|
+
type: ArrayConstructor;
|
|
22
|
+
default: () => never[];
|
|
23
|
+
};
|
|
24
|
+
}>> & Readonly<{
|
|
25
|
+
onHide?: ((...args: any[]) => any) | undefined;
|
|
26
|
+
onOk?: ((...args: any[]) => any) | undefined;
|
|
27
|
+
}>, {
|
|
28
|
+
initialFiles: unknown[];
|
|
29
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
declare const _default: typeof __VLS_export;
|
|
2
|
+
export default _default;
|
|
3
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
4
|
+
"update:modelValue": (value: any) => any;
|
|
5
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_ModelProps> & Readonly<{
|
|
6
|
+
"onUpdate:modelValue"?: ((value: any) => any) | undefined;
|
|
7
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
8
|
+
type __VLS_ModelProps = {
|
|
9
|
+
modelValue?: any;
|
|
10
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { computed } from "vue";
|
|
3
|
+
const modelValue = defineModel();
|
|
4
|
+
const breadcrumbs = computed(() => {
|
|
5
|
+
if (!modelValue.value) {
|
|
6
|
+
return [];
|
|
7
|
+
}
|
|
8
|
+
const path = modelValue.value;
|
|
9
|
+
const protocolMatch = path.match(/^([a-zA-Z0-9]+):\/\/(.*)$/);
|
|
10
|
+
if (!protocolMatch) {
|
|
11
|
+
return [];
|
|
12
|
+
}
|
|
13
|
+
const protocol = protocolMatch[1];
|
|
14
|
+
const pathParts = protocolMatch[2].split("/").filter((part) => part.length > 0);
|
|
15
|
+
let breadcrumbs2 = [{
|
|
16
|
+
label: protocol,
|
|
17
|
+
location: `${protocol}://`
|
|
18
|
+
}];
|
|
19
|
+
let currentPath = `${protocol}://`;
|
|
20
|
+
for (let part of pathParts) {
|
|
21
|
+
currentPath += part;
|
|
22
|
+
breadcrumbs2.push({
|
|
23
|
+
label: part,
|
|
24
|
+
location: currentPath
|
|
25
|
+
});
|
|
26
|
+
currentPath += "/";
|
|
27
|
+
}
|
|
28
|
+
return breadcrumbs2;
|
|
29
|
+
});
|
|
30
|
+
</script>
|
|
31
|
+
|
|
32
|
+
<template>
|
|
33
|
+
<q-breadcrumbs>
|
|
34
|
+
<q-breadcrumbs-el v-for="(b, index) in breadcrumbs" :label="b.label" :key="index"
|
|
35
|
+
@click="$emit('update:modelValue', b.location)" href="javascript:void(0)"></q-breadcrumbs-el>
|
|
36
|
+
</q-breadcrumbs>
|
|
37
|
+
</template>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
declare const _default: typeof __VLS_export;
|
|
2
|
+
export default _default;
|
|
3
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
4
|
+
"update:modelValue": (value: any) => any;
|
|
5
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_ModelProps> & Readonly<{
|
|
6
|
+
"onUpdate:modelValue"?: ((value: any) => any) | undefined;
|
|
7
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
8
|
+
type __VLS_ModelProps = {
|
|
9
|
+
modelValue?: any;
|
|
10
|
+
};
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
declare const _default: typeof __VLS_export;
|
|
2
2
|
export default _default;
|
|
3
3
|
declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
4
|
-
|
|
4
|
+
current_location: StringConstructor;
|
|
5
|
+
allow_cross_fs: BooleanConstructor;
|
|
5
6
|
}>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
6
7
|
selected: (...args: any[]) => void;
|
|
7
8
|
}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
8
|
-
|
|
9
|
+
current_location: StringConstructor;
|
|
10
|
+
allow_cross_fs: BooleanConstructor;
|
|
9
11
|
}>> & Readonly<{
|
|
10
12
|
onSelected?: ((...args: any[]) => any) | undefined;
|
|
11
|
-
}>, {
|
|
13
|
+
}>, {
|
|
14
|
+
allow_cross_fs: boolean;
|
|
15
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
@@ -1,35 +1,79 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
-
import { ref,
|
|
2
|
+
import { ref, watch } from "vue";
|
|
3
3
|
import { useQuasar } from "quasar";
|
|
4
|
-
import {
|
|
4
|
+
import { fs, query } from "@hostlink/light";
|
|
5
5
|
const props = defineProps({
|
|
6
|
-
|
|
6
|
+
current_location: String,
|
|
7
|
+
allow_cross_fs: Boolean
|
|
7
8
|
});
|
|
8
|
-
const api = getApiClient();
|
|
9
9
|
const emit = defineEmits(["selected"]);
|
|
10
|
-
const
|
|
10
|
+
const protocolMatch = props.current_location.match(/^([a-zA-Z0-9]+):\/\/(.*)$/);
|
|
11
|
+
const filesystem = ref(protocolMatch ? protocolMatch[1] : "");
|
|
12
|
+
const fss = await query({
|
|
13
|
+
app: {
|
|
14
|
+
fs: {
|
|
15
|
+
list: true
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}).then((res) => res.app.fs.list.map((f) => ({ label: f.name, value: f.name + "://" })));
|
|
19
|
+
const data = await query({
|
|
20
|
+
app: {
|
|
21
|
+
fs: {
|
|
22
|
+
node: {
|
|
23
|
+
__args: {
|
|
24
|
+
location: props.current_location
|
|
25
|
+
},
|
|
26
|
+
__on: {
|
|
27
|
+
__typeName: "Folder",
|
|
28
|
+
children: {
|
|
29
|
+
__typename: true,
|
|
30
|
+
__on: {
|
|
31
|
+
__typeName: "Folder",
|
|
32
|
+
name: true,
|
|
33
|
+
location: true
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}).then((res) => res.app.fs.node.children.filter((n) => n.__typename === "Folder"));
|
|
11
41
|
const folders = ref(data);
|
|
12
42
|
const mode = ref("move");
|
|
13
|
-
const folder = ref(
|
|
14
|
-
const parent = ref("/");
|
|
43
|
+
const folder = ref(props.current_location);
|
|
15
44
|
const qua = useQuasar();
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
45
|
+
watch(filesystem, async () => {
|
|
46
|
+
console.log(filesystem.value);
|
|
47
|
+
folder.value = filesystem.value;
|
|
19
48
|
});
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
49
|
+
watch(folder, async () => {
|
|
50
|
+
folders.value = await query({
|
|
51
|
+
app: {
|
|
52
|
+
fs: {
|
|
53
|
+
node: {
|
|
54
|
+
__args: {
|
|
55
|
+
location: folder.value
|
|
56
|
+
},
|
|
57
|
+
__on: {
|
|
58
|
+
__typeName: "Folder",
|
|
59
|
+
children: {
|
|
60
|
+
__typename: true,
|
|
61
|
+
__on: {
|
|
62
|
+
__typeName: "Folder",
|
|
63
|
+
name: true,
|
|
64
|
+
location: true
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}).then((res) => res.app.fs.node.children.filter((n) => n.__typename === "Folder"));
|
|
28
72
|
});
|
|
29
73
|
const newFolder = ref(null);
|
|
30
74
|
const onClickCreate = async () => {
|
|
31
75
|
let f = folder.value + "/" + newFolder.value;
|
|
32
|
-
|
|
76
|
+
fs.createFolder(f);
|
|
33
77
|
folder.value = f;
|
|
34
78
|
mode.value = "move";
|
|
35
79
|
};
|
|
@@ -43,9 +87,6 @@ const onClickMove = async () => {
|
|
|
43
87
|
}).onOk(async () => {
|
|
44
88
|
menu.value.hide();
|
|
45
89
|
emit("selected", folder.value);
|
|
46
|
-
folder.value = "/";
|
|
47
|
-
parent.value = null;
|
|
48
|
-
folder.value = "/";
|
|
49
90
|
});
|
|
50
91
|
};
|
|
51
92
|
</script>
|
|
@@ -53,6 +94,9 @@ const onClickMove = async () => {
|
|
|
53
94
|
<template>
|
|
54
95
|
<q-menu transition-show="jump-down" transition-hide="jump-up" ref="menu">
|
|
55
96
|
<q-card>
|
|
97
|
+
<q-card-section v-if="allow_cross_fs">
|
|
98
|
+
<q-select label="Filesystem" :options="fss" v-model="filesystem" dense emit-value map-options />
|
|
99
|
+
</q-card-section>
|
|
56
100
|
<q-toolbar>
|
|
57
101
|
<template v-if="mode == 'create'">
|
|
58
102
|
<q-btn flat dense round @click="mode = 'move'" icon="sym_o_arrow_back" class="q-mr-sm">
|
|
@@ -61,12 +105,7 @@ const onClickMove = async () => {
|
|
|
61
105
|
|
|
62
106
|
</template>
|
|
63
107
|
<template v-else>
|
|
64
|
-
<
|
|
65
|
-
<q-tooltip>Back</q-tooltip>
|
|
66
|
-
</q-btn>
|
|
67
|
-
<q-toolbar-title>
|
|
68
|
-
{{ title }}
|
|
69
|
-
</q-toolbar-title>
|
|
108
|
+
<l-file-manager-breadcrumbs v-model="folder" />
|
|
70
109
|
|
|
71
110
|
</template>
|
|
72
111
|
|
|
@@ -91,7 +130,7 @@ const onClickMove = async () => {
|
|
|
91
130
|
|
|
92
131
|
<template v-if="mode == 'move'">
|
|
93
132
|
<q-list>
|
|
94
|
-
<q-item v-for="(b, index) in folders" :key="index" clickable @click="
|
|
133
|
+
<q-item v-for="(b, index) in folders" :key="index" clickable @click="folder = b.location;">
|
|
95
134
|
|
|
96
135
|
<q-item-section avatar>
|
|
97
136
|
<q-icon name="sym_o_folder"></q-icon>
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
declare const _default: typeof __VLS_export;
|
|
2
2
|
export default _default;
|
|
3
3
|
declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
4
|
-
|
|
4
|
+
current_location: StringConstructor;
|
|
5
|
+
allow_cross_fs: BooleanConstructor;
|
|
5
6
|
}>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
6
7
|
selected: (...args: any[]) => void;
|
|
7
8
|
}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
8
|
-
|
|
9
|
+
current_location: StringConstructor;
|
|
10
|
+
allow_cross_fs: BooleanConstructor;
|
|
9
11
|
}>> & Readonly<{
|
|
10
12
|
onSelected?: ((...args: any[]) => any) | undefined;
|
|
11
|
-
}>, {
|
|
13
|
+
}>, {
|
|
14
|
+
allow_cross_fs: boolean;
|
|
15
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
@@ -1,23 +1,13 @@
|
|
|
1
1
|
declare const _default: typeof __VLS_export;
|
|
2
2
|
export default _default;
|
|
3
3
|
declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
4
|
-
|
|
4
|
+
location: {
|
|
5
5
|
type: StringConstructor;
|
|
6
6
|
required: true;
|
|
7
7
|
};
|
|
8
|
-
driveIndex: {
|
|
9
|
-
type: NumberConstructor;
|
|
10
|
-
default: number;
|
|
11
|
-
};
|
|
12
8
|
}>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
13
|
-
|
|
9
|
+
location: {
|
|
14
10
|
type: StringConstructor;
|
|
15
11
|
required: true;
|
|
16
12
|
};
|
|
17
|
-
|
|
18
|
-
type: NumberConstructor;
|
|
19
|
-
default: number;
|
|
20
|
-
};
|
|
21
|
-
}>> & Readonly<{}>, {
|
|
22
|
-
driveIndex: number;
|
|
23
|
-
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
13
|
+
}>> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|