quasar-ui-danx 0.4.79 → 0.4.81
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/danx.es.js +3985 -3940
- package/dist/danx.es.js.map +1 -1
- package/dist/danx.umd.js +81 -81
- package/dist/danx.umd.js.map +1 -1
- package/dist/style.css +1 -1
- package/package.json +1 -1
- package/src/components/ActionTable/Form/Fields/MultiFileField.vue +3 -1
- package/src/components/Utility/Buttons/ActionButton.vue +64 -56
- package/src/components/Utility/Files/FilePreview.vue +16 -11
- package/src/helpers/FileUpload.ts +0 -16
package/package.json
CHANGED
@@ -27,7 +27,8 @@
|
|
27
27
|
:class="filePreviewClass"
|
28
28
|
:style="styleSize"
|
29
29
|
:file="file"
|
30
|
-
:
|
30
|
+
:show-transcodes="showTranscodes"
|
31
|
+
:related-files="uploadedFiles"
|
31
32
|
downloadable
|
32
33
|
:removable="!readonly && !disabled"
|
33
34
|
@remove="onRemove(file)"
|
@@ -92,6 +93,7 @@ const props = withDefaults(defineProps<{
|
|
92
93
|
addIconClass?: string;
|
93
94
|
filePreviewClass?: string;
|
94
95
|
filePreviewBtnSize?: string;
|
96
|
+
showTranscodes?: boolean;
|
95
97
|
}>(), {
|
96
98
|
modelValue: null,
|
97
99
|
field: null,
|
@@ -1,64 +1,66 @@
|
|
1
1
|
<template>
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
2
|
+
<QBtn
|
3
|
+
:loading="isSaving"
|
4
|
+
class="shadow-none py-0"
|
5
|
+
:class="buttonClass"
|
6
|
+
:disable="disabled"
|
7
|
+
@click="()=> onAction()"
|
8
|
+
>
|
9
|
+
<div class="flex items-center flex-nowrap">
|
10
|
+
<component
|
11
|
+
:is="icon || typeOptions.icon"
|
12
|
+
class="transition-all"
|
13
|
+
:class="resolvedIconClass"
|
14
|
+
/>
|
15
|
+
<div
|
16
|
+
v-if="label || label === 0"
|
17
|
+
class="ml-2"
|
18
|
+
:class="labelClass"
|
19
|
+
>
|
20
|
+
{{ label }}
|
21
|
+
</div>
|
22
|
+
<slot />
|
23
|
+
</div>
|
24
|
+
<QTooltip
|
25
|
+
v-if="tooltip"
|
26
|
+
class="whitespace-nowrap"
|
27
|
+
:class="tooltipClass"
|
28
|
+
>
|
29
|
+
<slot name="tooltip">
|
30
|
+
{{ tooltip }}
|
31
|
+
</slot>
|
32
|
+
</QTooltip>
|
33
|
+
<QMenu
|
34
|
+
v-if="isConfirming"
|
35
|
+
:model-value="true"
|
36
|
+
>
|
37
|
+
<div class="p-4 bg-slate-600">
|
38
|
+
<div>{{ confirmText }}</div>
|
39
|
+
<div class="flex items-center flex-nowrap mt-2">
|
40
|
+
<div class="flex-grow">
|
41
|
+
<ActionButton
|
42
|
+
type="cancel"
|
43
|
+
color="gray"
|
44
|
+
@click="isConfirming = false"
|
45
|
+
/>
|
46
|
+
</div>
|
47
|
+
<ActionButton
|
48
|
+
type="confirm"
|
49
|
+
color="green"
|
50
|
+
@click="()=> onAction(true)"
|
51
|
+
/>
|
52
|
+
</div>
|
53
|
+
</div>
|
54
|
+
</QMenu>
|
55
|
+
</QBtn>
|
56
56
|
</template>
|
57
57
|
<script setup lang="ts">
|
58
58
|
import {
|
59
|
+
FaSolidArrowRotateRight as RestartIcon,
|
59
60
|
FaSolidArrowsRotate as RefreshIcon,
|
60
61
|
FaSolidCircleCheck as ConfirmIcon,
|
61
62
|
FaSolidCircleXmark as CancelIcon,
|
63
|
+
FaSolidCodeMerge as MergeIcon,
|
62
64
|
FaSolidCopy as CopyIcon,
|
63
65
|
FaSolidFileExport as ExportIcon,
|
64
66
|
FaSolidFileImport as ImportIcon,
|
@@ -75,8 +77,8 @@ import { computed, ref } from "vue";
|
|
75
77
|
import { ActionTarget, ResourceAction } from "../../../types";
|
76
78
|
|
77
79
|
export interface ActionButtonProps {
|
78
|
-
type?: "trash" | "create" | "edit" | "copy" | "folder" | "play" | "stop" | "pause" | "refresh" | "confirm" | "cancel" | "export" | "import" | "minus";
|
79
|
-
color?: "red" | "blue" | "sky" | "sky-invert" | "green" | "green-invert" | "lime" | "white" | "gray" | "yellow" | "orange";
|
80
|
+
type?: "trash" | "create" | "edit" | "copy" | "folder" | "play" | "stop" | "pause" | "refresh" | "restart" | "confirm" | "cancel" | "export" | "import" | "minus" | "merge";
|
81
|
+
color?: "red" | "blue" | "blue-invert" | "sky" | "sky-invert" | "green" | "green-invert" | "lime" | "white" | "gray" | "yellow" | "orange";
|
80
82
|
size?: "xxs" | "xs" | "sm" | "md" | "lg";
|
81
83
|
icon?: object | string;
|
82
84
|
iconClass?: string;
|
@@ -154,6 +156,8 @@ const colorClass = computed(() => {
|
|
154
156
|
return "text-green-300 bg-green-900 hover:bg-green-800";
|
155
157
|
case "blue":
|
156
158
|
return "text-blue-900 bg-blue-300 hover:bg-blue-400";
|
159
|
+
case "blue-invert":
|
160
|
+
return "text-blue-300 bg-blue-900 hover:bg-blue-800";
|
157
161
|
case "sky":
|
158
162
|
return "text-sky-900 bg-sky-300 hover:bg-sky-400";
|
159
163
|
case "sky-invert":
|
@@ -199,10 +203,14 @@ const typeOptions = computed(() => {
|
|
199
203
|
return { icon: StopIcon };
|
200
204
|
case "pause":
|
201
205
|
return { icon: PauseIcon };
|
206
|
+
case "restart":
|
207
|
+
return { icon: RestartIcon };
|
202
208
|
case "refresh":
|
203
209
|
return { icon: RefreshIcon };
|
204
210
|
case "minus":
|
205
211
|
return { icon: MinusIcon };
|
212
|
+
case "merge":
|
213
|
+
return { icon: MergeIcon };
|
206
214
|
default:
|
207
215
|
return { icon: EditIcon };
|
208
216
|
}
|
@@ -6,7 +6,7 @@
|
|
6
6
|
<template v-if="computedImage">
|
7
7
|
<div
|
8
8
|
class="grow h-full"
|
9
|
-
@click="
|
9
|
+
@click="onShowPreview"
|
10
10
|
>
|
11
11
|
<div
|
12
12
|
v-if="isVideo"
|
@@ -143,8 +143,9 @@
|
|
143
143
|
|
144
144
|
<script setup lang="ts">
|
145
145
|
import { DocumentTextIcon as TextFileIcon, DownloadIcon, PlayIcon } from "@heroicons/vue/outline";
|
146
|
-
import { computed, ComputedRef,
|
147
|
-
import {
|
146
|
+
import { computed, ComputedRef, ref, shallowRef } from "vue";
|
147
|
+
import { danxOptions } from "../../../config";
|
148
|
+
import { download, uniqueBy } from "../../../helpers";
|
148
149
|
import { ImageIcon, PdfIcon, TrashIcon as RemoveIcon } from "../../../svg";
|
149
150
|
import { UploadedFile } from "../../../types";
|
150
151
|
import { FullScreenCarouselDialog } from "../Dialogs";
|
@@ -171,6 +172,7 @@ export interface FilePreviewProps {
|
|
171
172
|
disabled?: boolean;
|
172
173
|
square?: boolean;
|
173
174
|
btnSize?: "xs" | "sm" | "md" | "lg";
|
175
|
+
showTranscodes?: boolean;
|
174
176
|
}
|
175
177
|
|
176
178
|
const emit = defineEmits(["remove"]);
|
@@ -207,10 +209,11 @@ const computedImage: ComputedRef<UploadedFile | null> = computed(() => {
|
|
207
209
|
return null;
|
208
210
|
});
|
209
211
|
|
212
|
+
const transcodes = shallowRef(props.file?.transcodes || null);
|
210
213
|
const isUploading = computed(() => !props.file || props.file?.progress !== undefined);
|
211
214
|
const statusMessage = computed(() => isUploading.value ? "Uploading..." : transcodingStatus.value?.message);
|
212
215
|
const previewableFiles: ComputedRef<(UploadedFile | null)[] | null> = computed(() => {
|
213
|
-
return props.relatedFiles?.length > 0 ? uniqueBy([computedImage.value, ...props.relatedFiles], filesHaveSameUrl) : [computedImage.value];
|
216
|
+
return props.relatedFiles?.length > 0 ? uniqueBy([computedImage.value, ...(props.showTranscodes ? (transcodes.value || []) : props.relatedFiles)], filesHaveSameUrl) : [computedImage.value];
|
214
217
|
});
|
215
218
|
|
216
219
|
function filesHaveSameUrl(a: UploadedFile, b: UploadedFile) {
|
@@ -253,13 +256,6 @@ const transcodingStatus = computed(() => {
|
|
253
256
|
return status;
|
254
257
|
});
|
255
258
|
|
256
|
-
// Check for an active transcode and make sure the file is being polled for updates
|
257
|
-
onMounted(() => {
|
258
|
-
if (transcodingStatus.value) {
|
259
|
-
(new FileUpload([])).waitForTranscode(props.file);
|
260
|
-
}
|
261
|
-
});
|
262
|
-
|
263
259
|
const isConfirmingRemove = ref(false);
|
264
260
|
function onRemove() {
|
265
261
|
if (!isConfirmingRemove.value) {
|
@@ -271,6 +267,15 @@ function onRemove() {
|
|
271
267
|
emit("remove");
|
272
268
|
}
|
273
269
|
}
|
270
|
+
|
271
|
+
async function onShowPreview() {
|
272
|
+
showPreview.value = true;
|
273
|
+
|
274
|
+
if (props.showTranscodes && props.file && !transcodes.value) {
|
275
|
+
const file = await danxOptions.value.fileUpload.refreshFile(props.file.id) as UploadedFile;
|
276
|
+
transcodes.value = file.transcodes || [];
|
277
|
+
}
|
278
|
+
}
|
274
279
|
</script>
|
275
280
|
|
276
281
|
<style module="cls" lang="scss">
|
@@ -13,7 +13,6 @@ import {
|
|
13
13
|
import { resolveFileLocation } from "./files";
|
14
14
|
import { FlashMessages } from "./FlashMessages";
|
15
15
|
import { storeObject } from "./objectStore";
|
16
|
-
import { sleep } from "./utils";
|
17
16
|
|
18
17
|
|
19
18
|
export class FileUpload {
|
@@ -231,7 +230,6 @@ export class FileUpload {
|
|
231
230
|
// Fire the file complete callbacks
|
232
231
|
this.fireCompleteCallback(fileUpload, storedFile);
|
233
232
|
this.checkAllComplete();
|
234
|
-
await this.waitForTranscode(storedFile);
|
235
233
|
} catch (error: any) {
|
236
234
|
this.errorHandler(e, fileUpload.file, error);
|
237
235
|
}
|
@@ -293,20 +291,6 @@ export class FileUpload {
|
|
293
291
|
return false;
|
294
292
|
}
|
295
293
|
|
296
|
-
/**
|
297
|
-
* Keeps refreshing the file while there is transcoding in progress
|
298
|
-
*/
|
299
|
-
async waitForTranscode(file: UploadedFile) {
|
300
|
-
// Only allow waiting for transcode 1 time per file
|
301
|
-
if (!file.meta || file.meta.is_waiting_transcode) return;
|
302
|
-
file.meta.is_waiting_transcode = true;
|
303
|
-
let currentFile: UploadedFile | null = file;
|
304
|
-
while (currentFile && this.isTranscoding(currentFile)) {
|
305
|
-
await sleep(1000);
|
306
|
-
currentFile = await this.refreshFile(currentFile);
|
307
|
-
}
|
308
|
-
}
|
309
|
-
|
310
294
|
/**
|
311
295
|
* Start uploading all files
|
312
296
|
*/
|