@nextcloud/vue 9.11.0 → 9.13.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.
- package/CHANGELOG.md +36 -0
- package/dist/assets/NcAppContent.css +20 -20
- package/dist/assets/NcAppNavigation.css +13 -13
- package/dist/assets/NcAppNavigationItem.css +45 -49
- package/dist/assets/NcAppNavigationList.css +2 -26
- package/dist/assets/NcAppNavigationNewItem.css +0 -4
- package/dist/assets/NcAppNavigationSettings.css +6 -6
- package/dist/assets/NcAppSettingsDialog.css +3 -3
- package/dist/assets/NcAppSettingsShortcutsSection.css +1 -1
- package/dist/assets/NcAppSidebar.css +28 -28
- package/dist/assets/NcAssistantButton.css +9 -9
- package/dist/assets/NcAssistantContent.css +3 -3
- package/dist/assets/NcAssistantIcon.css +4 -4
- package/dist/assets/NcAvatar.css +26 -26
- package/dist/assets/NcBlurHash.css +2 -2
- package/dist/assets/NcDateTimePicker.css +234 -234
- package/dist/assets/NcDialog.css +16 -16
- package/dist/assets/NcFilePicker.css +1 -1
- package/dist/assets/NcFormBox.css +11 -11
- package/dist/assets/NcFormBoxButton.css +2 -2
- package/dist/assets/NcFormBoxItem.css +15 -15
- package/dist/assets/NcFormBoxSwitch.css +2 -2
- package/dist/assets/NcFormGroup.css +7 -7
- package/dist/assets/NcHotkey.css +8 -8
- package/dist/assets/NcHotkeyList.css +2 -2
- package/dist/assets/NcIconToggleSwitch.css +4 -4
- package/dist/assets/NcKbd.css +3 -3
- package/dist/assets/NcModal.css +69 -63
- package/dist/assets/NcPopover.css +16 -16
- package/dist/assets/NcProfileHoverCard.css +82 -59
- package/dist/assets/NcRadioGroup.css +2 -2
- package/dist/assets/NcRadioGroupButton.css +14 -14
- package/dist/assets/NcRichContenteditable.css +17 -17
- package/dist/assets/NcRichText.css +2 -2
- package/dist/assets/NcUploadPicker.css +41 -0
- package/dist/assets/autolink.css +3 -3
- package/dist/chunks/NcActionInput.mjs +2 -2
- package/dist/chunks/NcActions.mjs +2 -2
- package/dist/chunks/NcAppContent.mjs +171 -298
- package/dist/chunks/NcAppContent.mjs.map +1 -1
- package/dist/chunks/NcAppContentList.vue_vue_type_script_setup_true_lang.mjs +21 -0
- package/dist/chunks/NcAppContentList.vue_vue_type_script_setup_true_lang.mjs.map +1 -0
- package/dist/chunks/NcAppNavigation.mjs +9 -6
- package/dist/chunks/NcAppNavigation.mjs.map +1 -1
- package/dist/chunks/NcAppNavigationItem.mjs +6 -29
- package/dist/chunks/NcAppNavigationItem.mjs.map +1 -1
- package/dist/chunks/NcAppNavigationList.mjs +8 -138
- package/dist/chunks/NcAppNavigationList.mjs.map +1 -1
- package/dist/chunks/NcAppNavigationNewItem.mjs +1 -1
- package/dist/chunks/NcAppNavigationNewItem.mjs.map +1 -1
- package/dist/chunks/NcAppNavigationSearch.mjs +2 -2
- package/dist/chunks/NcAppNavigationSettings.mjs +8 -8
- package/dist/chunks/NcAppSettingsDialog.mjs +5 -5
- package/dist/chunks/NcAppSettingsShortcutsSection.mjs +3 -3
- package/dist/chunks/NcAppSidebar.mjs +15 -15
- package/dist/chunks/NcAppSidebar.mjs.map +1 -1
- package/dist/chunks/NcAssistantButton.mjs +7 -7
- package/dist/chunks/NcAssistantContent.mjs +3 -3
- package/dist/chunks/NcAssistantIcon.mjs +4 -4
- package/dist/chunks/NcAvatar.mjs +30 -10
- package/dist/chunks/NcAvatar.mjs.map +1 -1
- package/dist/chunks/NcBlurHash.mjs +2 -2
- package/dist/chunks/NcCheckboxRadioSwitch.mjs +1 -1
- package/dist/chunks/NcCollectionList.mjs +3 -3
- package/dist/chunks/NcColorPicker.mjs +2 -2
- package/dist/chunks/NcContent.mjs +2 -2
- package/dist/chunks/NcDashboardWidget.mjs +4 -4
- package/dist/chunks/NcDashboardWidget.mjs.map +1 -1
- package/dist/chunks/NcDateTimePicker.mjs +7 -4
- package/dist/chunks/NcDateTimePicker.mjs.map +1 -1
- package/dist/chunks/NcDateTimePickerNative.mjs +2 -2
- package/dist/chunks/NcDialog.mjs +1 -1
- package/dist/chunks/NcDialog.mjs.map +1 -1
- package/dist/chunks/NcDialogButton.vue_vue_type_script_setup_true_lang.mjs +2 -2
- package/dist/chunks/NcEmojiPicker.mjs +2 -2
- package/dist/chunks/NcFilePicker.mjs +6 -5
- package/dist/chunks/NcFilePicker.mjs.map +1 -1
- package/dist/chunks/NcFormBox.mjs +5 -5
- package/dist/chunks/NcFormBoxButton.mjs +2 -2
- package/dist/chunks/NcFormBoxItem.mjs +8 -8
- package/dist/chunks/NcFormBoxSwitch.mjs +2 -2
- package/dist/chunks/NcFormGroup.mjs +7 -7
- package/dist/chunks/NcHotkey.mjs +4 -4
- package/dist/chunks/NcHotkeyList.mjs +4 -4
- package/dist/chunks/NcIconToggleSwitch.mjs +2 -2
- package/dist/chunks/NcKbd.mjs +4 -4
- package/dist/chunks/NcMentionBubble.vue_vue_type_style_index_0_scoped_3c4a673d_lang.mjs +7 -7
- package/dist/chunks/NcMentionBubble.vue_vue_type_style_index_0_scoped_3c4a673d_lang.mjs.map +1 -1
- package/dist/chunks/NcModal.mjs +18 -11
- package/dist/chunks/NcModal.mjs.map +1 -1
- package/dist/chunks/NcPasswordField.mjs +2 -2
- package/dist/chunks/NcPopover.mjs +2 -2
- package/dist/chunks/NcProfileHoverCard.mjs +205 -157
- package/dist/chunks/NcProfileHoverCard.mjs.map +1 -1
- package/dist/chunks/NcRadioGroup.mjs +2 -2
- package/dist/chunks/NcRadioGroupButton.mjs +6 -6
- package/dist/chunks/NcReferenceWidget.mjs +2 -2
- package/dist/chunks/NcRelatedResourcesPanel.mjs +4 -4
- package/dist/chunks/NcRichContenteditable.mjs +12 -12
- package/dist/chunks/NcRichText.mjs +3 -3
- package/dist/chunks/NcRichText.mjs.map +1 -1
- package/dist/chunks/NcSettingsSection.mjs +2 -2
- package/dist/chunks/NcSettingsSelectGroup.mjs +2 -2
- package/dist/chunks/NcTextField.vue_vue_type_script_setup_true_lang.mjs +2 -2
- package/dist/chunks/NcTimezonePicker.vue_vue_type_script_setup_true_lang.mjs +2 -2
- package/dist/chunks/NcUploadPicker.mjs +269 -0
- package/dist/chunks/NcUploadPicker.mjs.map +1 -0
- package/dist/chunks/NcUserStatusIcon.mjs +2 -2
- package/dist/chunks/_l10n.mjs +91 -89
- package/dist/chunks/_l10n.mjs.map +1 -1
- package/dist/chunks/autolink.mjs +3 -3
- package/dist/chunks/colors.mjs +2 -2
- package/dist/chunks/mdi.mjs +7 -5
- package/dist/chunks/mdi.mjs.map +1 -1
- package/dist/chunks/referencePickerModal.mjs +5 -5
- package/dist/components/NcActionInput/NcActionInput.vue.d.ts +3 -3
- package/dist/components/NcAppContent/NcAppContent.vue.d.ts +77 -149
- package/dist/components/NcAppContent/index.d.ts +5 -0
- package/dist/components/NcAppContentList/NcAppContentList.vue.d.ts +28 -27
- package/dist/components/NcAppContentList/index.d.ts +4 -0
- package/dist/components/NcAppContentList/index.mjs +2 -2
- package/dist/components/NcAppNavigationItem/NcAppNavigationItem.vue.d.ts +0 -4
- package/dist/components/NcAppNavigationList/NcAppNavigationList.vue.d.ts +1 -57
- package/dist/components/NcAvatar/NcAvatar.vue.d.ts +26 -0
- package/dist/components/NcCollectionList/NcCollectionList.vue.d.ts +26 -0
- package/dist/components/NcCollectionList/NcCollectionListItem.vue.d.ts +13 -0
- package/dist/components/NcDashboardWidget/NcDashboardWidget.vue.d.ts +26 -0
- package/dist/components/NcDashboardWidgetItem/NcDashboardWidgetItem.vue.d.ts +13 -0
- package/dist/components/NcDateTimePicker/NcDateTimePicker.vue.d.ts +2 -2
- package/dist/components/NcFilePicker/NcFilePicker.vue.d.ts +7 -0
- package/dist/components/NcListItemIcon/NcListItemIcon.vue.d.ts +14 -1
- package/dist/components/NcModal/NcModal.vue.d.ts +3 -0
- package/dist/components/NcProfileHoverCard/NcProfileHoverCard.vue.d.ts +6 -0
- package/dist/components/NcRichText/NcReferencePicker/NcReferencePickerModal.vue.d.ts +8 -0
- package/dist/components/NcUploadPicker/NcUploadPicker.vue.d.ts +180 -0
- package/dist/components/NcUploadPicker/index.d.ts +6 -0
- package/dist/components/NcUploadPicker/index.mjs +5 -0
- package/dist/components/NcUploadPicker/index.mjs.map +1 -0
- package/dist/components/index.d.ts +3 -2
- package/dist/composables/useFormatDateTime/index.mjs +2 -2
- package/dist/index.mjs +169 -167
- package/dist/index.mjs.map +1 -1
- package/dist/utils/getAvatarUrl.d.ts +4 -0
- package/package.json +26 -12
- package/dist/chunks/NcAppContentList.mjs +0 -33
- package/dist/chunks/NcAppContentList.mjs.map +0 -1
- package/dist/chunks/highlight.mjs +0 -5
- package/dist/chunks/highlight.mjs.map +0 -1
- package/dist/components/NcAppNavigationList/highlight.d.ts +0 -12
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import '../assets/NcSettingsSection.css';
|
|
2
2
|
import { openBlock, createElementBlock, mergeProps, createElementVNode, toDisplayString, createCommentVNode, defineComponent, createTextVNode, unref, createVNode, renderSlot } from "vue";
|
|
3
3
|
import { _ as _export_sfc } from "./_plugin-vue_export-helper.mjs";
|
|
4
|
-
import { r as register,
|
|
4
|
+
import { r as register, F as t28, a as t } from "./_l10n.mjs";
|
|
5
5
|
const _sfc_main$1 = {
|
|
6
6
|
name: "HelpCircleIcon",
|
|
7
7
|
emits: ["click"],
|
|
@@ -45,7 +45,7 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
45
45
|
], 16, _hoisted_1$1);
|
|
46
46
|
}
|
|
47
47
|
const HelpCircle = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["render", _sfc_render]]);
|
|
48
|
-
register(
|
|
48
|
+
register(t28);
|
|
49
49
|
const _hoisted_1 = { class: "settings-section" };
|
|
50
50
|
const _hoisted_2 = { class: "settings-section__name" };
|
|
51
51
|
const _hoisted_3 = ["aria-label", "href", "title"];
|
|
@@ -3,11 +3,11 @@ import axios from "@nextcloud/axios";
|
|
|
3
3
|
import { generateOcsUrl } from "@nextcloud/router";
|
|
4
4
|
import debounce from "debounce";
|
|
5
5
|
import { N as NcSelect } from "./NcSelect.mjs";
|
|
6
|
-
import { r as register, i as
|
|
6
|
+
import { r as register, i as t52, a as t } from "./_l10n.mjs";
|
|
7
7
|
import { c as createElementId } from "./createElementId.mjs";
|
|
8
8
|
import { resolveComponent, openBlock, createElementBlock, toDisplayString, createCommentVNode, createVNode, withDirectives, createElementVNode, vShow } from "vue";
|
|
9
9
|
import { _ as _export_sfc } from "./_plugin-vue_export-helper.mjs";
|
|
10
|
-
register(
|
|
10
|
+
register(t52);
|
|
11
11
|
const _sfc_main = {
|
|
12
12
|
name: "NcSettingsSelectGroup",
|
|
13
13
|
components: {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { defineComponent, useModel, useTemplateRef, computed, openBlock, createBlock, unref, mergeProps, createSlots, withCtx, renderSlot, mergeModels } from "vue";
|
|
2
2
|
import { m as mdiArrowRight, a as mdiUndo, b as mdiClose } from "./mdi.mjs";
|
|
3
|
-
import { r as register, b as
|
|
3
|
+
import { r as register, b as t53, c as t19, a as t } from "./_l10n.mjs";
|
|
4
4
|
import { N as NcIconSvgWrapper } from "./NcIconSvgWrapper.mjs";
|
|
5
5
|
import { N as NcInputField } from "./NcInputField.mjs";
|
|
6
|
-
register(t19,
|
|
6
|
+
register(t19, t53);
|
|
7
7
|
const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
8
8
|
__name: "NcTextField",
|
|
9
9
|
props: /* @__PURE__ */ mergeModels({
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { defineComponent, useModel, computed, openBlock, createBlock, unref, mergeModels } from "vue";
|
|
2
2
|
import { N as NcSelect } from "./NcSelect.mjs";
|
|
3
|
-
import { r as register, h as
|
|
3
|
+
import { r as register, h as t47, a as t } from "./_l10n.mjs";
|
|
4
4
|
import { c as createElementId } from "./createElementId.mjs";
|
|
5
|
-
register(
|
|
5
|
+
register(t47);
|
|
6
6
|
function formatTimezoneId(timezoneId) {
|
|
7
7
|
return timezoneId.slice(timezoneId.indexOf("/") + 1).replaceAll("/", " - ").replaceAll("_", " ");
|
|
8
8
|
}
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
import '../assets/NcUploadPicker.css';
|
|
2
|
+
import { defineComponent, useTemplateRef, onBeforeMount, onUnmounted, watch, ref, computed, openBlock, createBlock, unref, withCtx, withDirectives, createElementVNode, normalizeClass, createVNode, createElementBlock, toDisplayString, createTextVNode, createCommentVNode, vShow } from "vue";
|
|
3
|
+
import { b as mdiClose, C as mdiPlus } from "./mdi.mjs";
|
|
4
|
+
import { openConflictPicker } from "@nextcloud/dialogs";
|
|
5
|
+
import { getUniqueName } from "@nextcloud/files";
|
|
6
|
+
import { getUploader, UploaderStatus, UploadStatus } from "@nextcloud/files/upload";
|
|
7
|
+
import { N as NcButton } from "./NcButton.mjs";
|
|
8
|
+
import { N as NcFilePicker } from "./NcFilePicker.mjs";
|
|
9
|
+
import { N as NcIconSvgWrapper } from "./NcIconSvgWrapper.mjs";
|
|
10
|
+
import { N as NcProgressBar } from "./NcProgressBar.mjs";
|
|
11
|
+
import { useFormatRelativeTime } from "../composables/useFormatDateTime/index.mjs";
|
|
12
|
+
import "../composables/useHotKey/index.mjs";
|
|
13
|
+
import "../composables/useIsDarkTheme/index.mjs";
|
|
14
|
+
import "../composables/useIsFullscreen/index.mjs";
|
|
15
|
+
import "../composables/useIsMobile/index.mjs";
|
|
16
|
+
import { r as register, E as t10, a as t } from "./_l10n.mjs";
|
|
17
|
+
import { c as createElementId } from "./createElementId.mjs";
|
|
18
|
+
import { l as logger } from "./logger.mjs";
|
|
19
|
+
import { _ as _export_sfc } from "./_plugin-vue_export-helper.mjs";
|
|
20
|
+
function basename(path, extname2) {
|
|
21
|
+
path = path.replace(/\\/g, "/").replace(/\/+$/g, "").replace(/.*\//, "");
|
|
22
|
+
return path;
|
|
23
|
+
}
|
|
24
|
+
register(t10);
|
|
25
|
+
const _hoisted_1 = ["id"];
|
|
26
|
+
const _hoisted_2 = { key: 0 };
|
|
27
|
+
const _hoisted_3 = { key: 1 };
|
|
28
|
+
const _hoisted_4 = ["title"];
|
|
29
|
+
const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
30
|
+
__name: "NcUploadPicker",
|
|
31
|
+
props: {
|
|
32
|
+
actions: { default: () => [] },
|
|
33
|
+
destination: {},
|
|
34
|
+
content: {},
|
|
35
|
+
accept: { default: () => [] },
|
|
36
|
+
disabled: { type: Boolean },
|
|
37
|
+
label: { default: () => t("New") },
|
|
38
|
+
multiple: { type: Boolean },
|
|
39
|
+
iconOnly: { type: Boolean },
|
|
40
|
+
variant: { default: "secondary" },
|
|
41
|
+
directory: { type: Boolean }
|
|
42
|
+
},
|
|
43
|
+
emits: ["upload:started", "upload:finished", "paused", "resumed", "finished"],
|
|
44
|
+
setup(__props, { expose: __expose, emit: __emit }) {
|
|
45
|
+
const props = __props;
|
|
46
|
+
const emit = __emit;
|
|
47
|
+
__expose({
|
|
48
|
+
reset
|
|
49
|
+
});
|
|
50
|
+
const filePickerElement = useTemplateRef("filePicker");
|
|
51
|
+
const progressTimeId = createElementId();
|
|
52
|
+
const uploadManager = getUploader();
|
|
53
|
+
onBeforeMount(() => {
|
|
54
|
+
window.addEventListener("beforeunload", onBeforePageUnload);
|
|
55
|
+
uploadManager.addEventListener("uploadFinished", onUploadFinished);
|
|
56
|
+
uploadManager.addEventListener("uploadStarted", onUploadStarted);
|
|
57
|
+
uploadManager.addEventListener("uploadProgress", updateEta);
|
|
58
|
+
uploadManager.addEventListener("finished", onUploaderFinished);
|
|
59
|
+
uploadManager.addEventListener("paused", onUploaderPaused);
|
|
60
|
+
uploadManager.addEventListener("reset", updateUploadStatus);
|
|
61
|
+
uploadManager.addEventListener("resumed", onUploaderResumed);
|
|
62
|
+
updateUploadStatus();
|
|
63
|
+
});
|
|
64
|
+
onUnmounted(() => {
|
|
65
|
+
window.removeEventListener("beforeunload", onBeforePageUnload);
|
|
66
|
+
uploadManager.removeEventListener("uploadFinished", onUploadFinished);
|
|
67
|
+
uploadManager.removeEventListener("uploadStarted", onUploadStarted);
|
|
68
|
+
uploadManager.removeEventListener("uploadProgress", updateEta);
|
|
69
|
+
uploadManager.removeEventListener("finished", onUploaderFinished);
|
|
70
|
+
uploadManager.removeEventListener("paused", onUploaderPaused);
|
|
71
|
+
uploadManager.removeEventListener("reset", updateUploadStatus);
|
|
72
|
+
uploadManager.removeEventListener("resumed", onUploaderResumed);
|
|
73
|
+
});
|
|
74
|
+
watch(() => props.destination, () => setDestination(props.destination), { immediate: true });
|
|
75
|
+
const isPaused = ref(uploadManager.status === UploaderStatus.PAUSED);
|
|
76
|
+
function onUploaderPaused() {
|
|
77
|
+
updateUploadStatus();
|
|
78
|
+
emit("paused", [...uploadManager.queue]);
|
|
79
|
+
}
|
|
80
|
+
function onUploaderResumed() {
|
|
81
|
+
updateUploadStatus();
|
|
82
|
+
emit("resumed", [...uploadManager.queue]);
|
|
83
|
+
}
|
|
84
|
+
const hasFailure = ref(false);
|
|
85
|
+
const isUploading = ref(false);
|
|
86
|
+
const isAssembling = ref(false);
|
|
87
|
+
const isOnlyAssembling = ref(false);
|
|
88
|
+
function updateUploadStatus() {
|
|
89
|
+
isPaused.value = uploadManager.status === UploaderStatus.PAUSED;
|
|
90
|
+
isUploading.value = uploadManager.status === UploaderStatus.UPLOADING || isPaused.value && uploadManager.queue.length > 0;
|
|
91
|
+
hasFailure.value = uploadManager.queue.some((upload) => upload.status === UploadStatus.FAILED);
|
|
92
|
+
isAssembling.value = uploadManager.queue.some((upload) => upload.status === UploadStatus.ASSEMBLING);
|
|
93
|
+
isOnlyAssembling.value = isAssembling.value && uploadManager.queue.every((upload) => upload.status >= UploadStatus.ASSEMBLING);
|
|
94
|
+
}
|
|
95
|
+
function reset() {
|
|
96
|
+
filePickerElement.value?.reset();
|
|
97
|
+
}
|
|
98
|
+
function setDestination(destination) {
|
|
99
|
+
if (!destination) {
|
|
100
|
+
logger.debug("Invalid destination");
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
uploadManager.destination = destination;
|
|
104
|
+
}
|
|
105
|
+
const etaProgress = ref(0);
|
|
106
|
+
const etaSpeed = ref("");
|
|
107
|
+
const etaRaw = ref(Infinity);
|
|
108
|
+
const etaTimeRaw = computed(() => etaRaw.value === Infinity ? Infinity : new Date(Date.now() + etaRaw.value));
|
|
109
|
+
const etaTimeFormatted = useFormatRelativeTime(etaTimeRaw, { ignoreSeconds: true });
|
|
110
|
+
const etaTime = computed(() => etaTimeRaw.value === Infinity ? t("Estimating …") : etaTimeFormatted.value);
|
|
111
|
+
function updateEta() {
|
|
112
|
+
etaRaw.value = uploadManager.statistics.eta === Infinity ? Infinity : uploadManager.statistics.eta * 1e3;
|
|
113
|
+
etaSpeed.value = uploadManager.statistics.speedReadable;
|
|
114
|
+
etaProgress.value = uploadManager.statistics.progress;
|
|
115
|
+
}
|
|
116
|
+
function onUploaderFinished() {
|
|
117
|
+
updateUploadStatus();
|
|
118
|
+
emit("finished");
|
|
119
|
+
}
|
|
120
|
+
function onUploadFinished(event) {
|
|
121
|
+
updateUploadStatus();
|
|
122
|
+
emit("upload:finished", event.detail);
|
|
123
|
+
}
|
|
124
|
+
function onUploadStarted(event) {
|
|
125
|
+
updateUploadStatus();
|
|
126
|
+
emit("upload:started", event.detail);
|
|
127
|
+
}
|
|
128
|
+
async function onPick(files) {
|
|
129
|
+
try {
|
|
130
|
+
await uploadManager.batchUpload("", files, { callback: handleConflicts });
|
|
131
|
+
} catch (error) {
|
|
132
|
+
logger.debug("Error while uploading", { error });
|
|
133
|
+
} finally {
|
|
134
|
+
reset();
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
async function handleConflicts(nodes, currentPath) {
|
|
138
|
+
try {
|
|
139
|
+
const content = await props.content(currentPath);
|
|
140
|
+
const conflicts = content.filter((node) => nodes.includes(node.displayname) || nodes.includes(node.basename));
|
|
141
|
+
const uploadMapping = Object.fromEntries(nodes.map((name) => [name, name]));
|
|
142
|
+
if (conflicts.length === 0) {
|
|
143
|
+
return uploadMapping;
|
|
144
|
+
}
|
|
145
|
+
const existingNodes = content.filter((node) => nodes.includes(node.displayname) || nodes.includes(node.basename));
|
|
146
|
+
const result = await openConflictPicker(basename(currentPath), conflicts, existingNodes, { recursive: props.directory });
|
|
147
|
+
if (result) {
|
|
148
|
+
const usedNames = content.map((node) => node.basename);
|
|
149
|
+
for (const node of conflicts) {
|
|
150
|
+
if (result.skipped.some((skipped) => skipped.basename === node.basename)) {
|
|
151
|
+
delete uploadMapping[node.basename];
|
|
152
|
+
} else if (result.renamed.some((renamed) => renamed.basename === node.basename)) {
|
|
153
|
+
const newName = getUniqueName(basename(node.basename), usedNames);
|
|
154
|
+
uploadMapping[node.basename] = newName;
|
|
155
|
+
usedNames.push(newName);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return uploadMapping;
|
|
159
|
+
}
|
|
160
|
+
} catch (error) {
|
|
161
|
+
logger.error("Error during conflict resolution - skipping upload", { error });
|
|
162
|
+
}
|
|
163
|
+
return false;
|
|
164
|
+
}
|
|
165
|
+
function onCancel() {
|
|
166
|
+
uploadManager.reset();
|
|
167
|
+
reset();
|
|
168
|
+
}
|
|
169
|
+
function onBeforePageUnload(event) {
|
|
170
|
+
if (uploadManager.queue.length > 0) {
|
|
171
|
+
event.preventDefault();
|
|
172
|
+
event.returnValue = "";
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
return (_ctx, _cache) => {
|
|
176
|
+
return openBlock(), createBlock(NcFilePicker, {
|
|
177
|
+
ref: "filePicker",
|
|
178
|
+
accept: __props.accept,
|
|
179
|
+
actionCaption: __props.actions.length > 0 || __props.directory ? unref(t)("Upload from device") : void 0,
|
|
180
|
+
actions: __props.actions,
|
|
181
|
+
directory: __props.directory,
|
|
182
|
+
disabled: __props.disabled,
|
|
183
|
+
iconOnly: __props.iconOnly,
|
|
184
|
+
label: __props.label,
|
|
185
|
+
multiple: __props.multiple,
|
|
186
|
+
variant: __props.variant,
|
|
187
|
+
onPick
|
|
188
|
+
}, {
|
|
189
|
+
icon: withCtx(() => [
|
|
190
|
+
createVNode(NcIconSvgWrapper, { path: unref(mdiPlus) }, null, 8, ["path"])
|
|
191
|
+
]),
|
|
192
|
+
default: withCtx(() => [
|
|
193
|
+
withDirectives(createElementVNode("div", {
|
|
194
|
+
class: normalizeClass([_ctx.$style.uploadPicker_progress, {
|
|
195
|
+
[_ctx.$style.uploadPicker_progress__uploading]: isUploading.value,
|
|
196
|
+
[_ctx.$style.uploadPicker_progress__paused]: isPaused.value
|
|
197
|
+
}])
|
|
198
|
+
}, [
|
|
199
|
+
createVNode(NcProgressBar, {
|
|
200
|
+
ariaLabel: unref(t)("Upload progress"),
|
|
201
|
+
ariaDescribedby: unref(progressTimeId),
|
|
202
|
+
error: hasFailure.value,
|
|
203
|
+
value: etaProgress.value,
|
|
204
|
+
size: "medium"
|
|
205
|
+
}, null, 8, ["ariaLabel", "ariaDescribedby", "error", "value"]),
|
|
206
|
+
createElementVNode("p", {
|
|
207
|
+
id: unref(progressTimeId),
|
|
208
|
+
class: normalizeClass(_ctx.$style.uploadPicker_progressLabel)
|
|
209
|
+
}, [
|
|
210
|
+
isPaused.value ? (openBlock(), createElementBlock("span", _hoisted_2, toDisplayString(
|
|
211
|
+
unref(t)("paused")
|
|
212
|
+
/* TRANSLATORS: State of the current upload - it is paused */
|
|
213
|
+
), 1)) : isOnlyAssembling.value ? (openBlock(), createElementBlock("span", _hoisted_3, toDisplayString(
|
|
214
|
+
unref(t)("assembling")
|
|
215
|
+
/* TRANSLATORS: State of the current upload - chunks of the uploaded files are being assembled into the final file */
|
|
216
|
+
), 1)) : (openBlock(), createElementBlock("span", {
|
|
217
|
+
key: 2,
|
|
218
|
+
title: `${etaTime.value} (${etaSpeed.value})`
|
|
219
|
+
}, [
|
|
220
|
+
createTextVNode(toDisplayString(etaTime.value) + " ", 1),
|
|
221
|
+
etaSpeed.value && etaRaw.value > 31e3 ? (openBlock(), createElementBlock("span", {
|
|
222
|
+
key: 0,
|
|
223
|
+
class: normalizeClass(_ctx.$style.uploadPicker_progressLabelSpeed)
|
|
224
|
+
}, " (" + toDisplayString(etaSpeed.value) + ") ", 3)) : createCommentVNode("", true)
|
|
225
|
+
], 8, _hoisted_4))
|
|
226
|
+
], 10, _hoisted_1)
|
|
227
|
+
], 2), [
|
|
228
|
+
[vShow, isUploading.value]
|
|
229
|
+
]),
|
|
230
|
+
isUploading.value && !isOnlyAssembling.value ? (openBlock(), createBlock(NcButton, {
|
|
231
|
+
key: 0,
|
|
232
|
+
class: normalizeClass(_ctx.$style.uploadPicker_cancelButton),
|
|
233
|
+
"aria-label": unref(t)("Cancel uploads"),
|
|
234
|
+
variant: "tertiary",
|
|
235
|
+
onClick: onCancel
|
|
236
|
+
}, {
|
|
237
|
+
icon: withCtx(() => [
|
|
238
|
+
createVNode(NcIconSvgWrapper, { path: unref(mdiClose) }, null, 8, ["path"])
|
|
239
|
+
]),
|
|
240
|
+
_: 1
|
|
241
|
+
}, 8, ["class", "aria-label"])) : createCommentVNode("", true)
|
|
242
|
+
]),
|
|
243
|
+
_: 1
|
|
244
|
+
}, 8, ["accept", "actionCaption", "actions", "directory", "disabled", "iconOnly", "label", "multiple", "variant"]);
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
const uploadPicker_progress = "_uploadPicker_progress_LchrN";
|
|
249
|
+
const uploadPicker_progress__uploading = "_uploadPicker_progress__uploading_RBQWf";
|
|
250
|
+
const uploadPicker_progress__paused = "_uploadPicker_progress__paused_t4TGj";
|
|
251
|
+
const breathing = "_breathing_B9q41";
|
|
252
|
+
const uploadPicker_progressLabel = "_uploadPicker_progressLabel_iEywW";
|
|
253
|
+
const uploadPicker_progressLabelSpeed = "_uploadPicker_progressLabelSpeed_dIEb3";
|
|
254
|
+
const style0 = {
|
|
255
|
+
uploadPicker_progress,
|
|
256
|
+
uploadPicker_progress__uploading,
|
|
257
|
+
uploadPicker_progress__paused,
|
|
258
|
+
breathing,
|
|
259
|
+
uploadPicker_progressLabel,
|
|
260
|
+
uploadPicker_progressLabelSpeed
|
|
261
|
+
};
|
|
262
|
+
const cssModules = {
|
|
263
|
+
"$style": style0
|
|
264
|
+
};
|
|
265
|
+
const NcUploadPicker = /* @__PURE__ */ _export_sfc(_sfc_main, [["__cssModules", cssModules]]);
|
|
266
|
+
export {
|
|
267
|
+
NcUploadPicker as N
|
|
268
|
+
};
|
|
269
|
+
//# sourceMappingURL=NcUploadPicker.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NcUploadPicker.mjs","sources":["../../node_modules/@nextcloud/paths/dist/index.mjs","../../src/components/NcUploadPicker/NcUploadPicker.vue"],"sourcesContent":["function encodePath(path) {\n if (!path) {\n return path;\n }\n return path.split(\"/\").map(encodeURIComponent).join(\"/\");\n}\nfunction basename(path, extname2) {\n path = path.replace(/\\\\/g, \"/\").replace(/\\/+$/g, \"\").replace(/.*\\//, \"\");\n if (extname2 && extname2 !== path && path.endsWith(extname2)) {\n return path.substring(0, path.length - extname2.length);\n }\n return path;\n}\nfunction dirname(path) {\n path = path.replaceAll(/\\\\/g, \"/\");\n const sections = path.split(\"/\");\n if (sections.length <= 1) {\n return \".\";\n }\n sections.pop();\n if (sections.length === 1 && sections[0] === \"\") {\n return \"/\";\n }\n return sections.join(\"/\");\n}\nfunction extname(path) {\n const base = basename(path);\n const index = base.lastIndexOf(\".\");\n if (index > 0) {\n return base.substring(index);\n }\n return \"\";\n}\nfunction join(...args) {\n if (arguments.length < 1) {\n return \"\";\n }\n const nonEmptyArgs = args.filter((arg) => arg.length > 0);\n if (nonEmptyArgs.length < 1) {\n return \"\";\n }\n const lastArg = nonEmptyArgs[nonEmptyArgs.length - 1];\n const leadingSlash = nonEmptyArgs[0].charAt(0) === \"/\";\n const trailingSlash = lastArg.charAt(lastArg.length - 1) === \"/\";\n const sections = nonEmptyArgs.reduce((acc, section) => acc.concat(section.split(\"/\")), []);\n let first = !leadingSlash;\n const path = sections.reduce((acc, section) => {\n if (section === \"\") {\n return acc;\n }\n if (first) {\n first = false;\n return acc + section;\n }\n return acc + \"/\" + section;\n }, \"\");\n if (trailingSlash) {\n return path + \"/\";\n }\n return path;\n}\nfunction isSamePath(path1, path2) {\n const pathSections1 = (path1 || \"\").split(\"/\").filter((p) => p !== \".\");\n const pathSections2 = (path2 || \"\").split(\"/\").filter((p) => p !== \".\");\n path1 = join(...pathSections1);\n path2 = join(...pathSections2);\n return path1 === path2;\n}\nfunction normalize(path) {\n const sections = path.split(\"/\").filter((p, index, arr) => p !== \"\" || index === 0 || index === arr.length - 1).filter((p) => p !== \".\");\n const sanitizedSections = [];\n for (const section of sections) {\n const lastSection = sanitizedSections.at(-1);\n if (section === \"..\" && lastSection !== \"..\") {\n if (lastSection === void 0) {\n sanitizedSections.push(section);\n } else if (lastSection !== \"\") {\n sanitizedSections.pop();\n }\n } else {\n sanitizedSections.push(section);\n }\n }\n return sanitizedSections.join(\"/\");\n}\nexport {\n basename,\n dirname,\n encodePath,\n extname,\n isSamePath,\n join,\n normalize\n};\n//# sourceMappingURL=index.mjs.map\n","<!--\n - SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors\n - SPDX-License-Identifier: AGPL-3.0-or-later\n-->\n\n<script setup lang=\"ts\">\nimport type { Folder, IFolder, INode } from '@nextcloud/files'\nimport type { IUpload } from '@nextcloud/files/upload'\nimport type { FilePickerItem, FilePickerItemGroup } from '../NcFilePicker/NcFilePicker.vue'\n\nimport { mdiClose, mdiPlus } from '@mdi/js'\nimport { openConflictPicker } from '@nextcloud/dialogs'\nimport { getUniqueName } from '@nextcloud/files'\nimport { getUploader, UploaderStatus, UploadStatus } from '@nextcloud/files/upload'\nimport { basename } from '@nextcloud/paths'\nimport { computed, onBeforeMount, onUnmounted, ref, useTemplateRef, watch } from 'vue'\nimport NcButton from '../NcButton/NcButton.vue'\nimport NcFilePicker from '../NcFilePicker/NcFilePicker.vue'\nimport NcIconSvgWrapper from '../NcIconSvgWrapper/NcIconSvgWrapper.vue'\nimport NcProgressBar from '../NcProgressBar/NcProgressBar.vue'\nimport { useFormatRelativeTime } from '../../composables/index.ts'\nimport { t } from '../../l10n.ts'\nimport { createElementId } from '../../utils/createElementId.ts'\nimport { logger } from '../../utils/logger.ts'\n\nconst props = withDefaults(defineProps<{\n\t/**\n\t * Actions to be shown in the upload picker menu.\n\t */\n\tactions?: FilePickerItem[] | FilePickerItemGroup[]\n\n\t/**\n\t * The upload destination folder\n\t */\n\tdestination: IFolder\n\n\t/**\n\t * A callback function to get the list of files present in the destination folder.\n\t */\n\tcontent: (relativePath?: string) => Promise<INode[]>\n\n\t/**\n\t * Allowed MIME types to upload\n\t */\n\taccept?: string[]\n\n\t/**\n\t * Disable the upload picker\n\t */\n\tdisabled?: boolean\n\n\t/**\n\t * The label of the upload picker button\n\t */\n\tlabel?: string\n\n\t/**\n\t * Allow uploading multiple files\n\t */\n\tmultiple?: boolean\n\n\t/**\n\t * Only show the icon without text label\n\t */\n\ticonOnly?: boolean\n\n\t/**\n\t * The variant of the menu button\n\t */\n\tvariant?: 'primary' | 'secondary' | 'tertiary'\n\n\t/**\n\t * Allow uploading directories\n\t */\n\tdirectory?: boolean\n}>(), {\n\tactions: () => [],\n\taccept: () => [],\n\tlabel: () => t('New'),\n\tvariant: 'secondary',\n})\n\nconst emit = defineEmits<{\n\t/**\n\t * Emitted when an upload has started.\n\t */\n\t'upload:started': [upload: IUpload]\n\t/**\n\t * Emitted when an upload has finished successfully.\n\t */\n\t'upload:finished': [upload: IUpload]\n\t/**\n\t * The queue has been paused, and no more uploads will be processed until resumed.\n\t */\n\tpaused: [queue: IUpload[]]\n\t/**\n\t * The queue has resumed uploading after being paused.\n\t */\n\tresumed: [queue: IUpload[]]\n\t/**\n\t * The queue has finished uploading all files.\n\t */\n\tfinished: []\n}>()\n\ndefineExpose({\n\treset,\n})\n\nconst filePickerElement = useTemplateRef('filePicker')\nconst progressTimeId = createElementId()\n\nconst uploadManager = getUploader()\nonBeforeMount(() => {\n\twindow.addEventListener('beforeunload', onBeforePageUnload)\n\tuploadManager.addEventListener('uploadFinished', onUploadFinished)\n\tuploadManager.addEventListener('uploadStarted', onUploadStarted)\n\tuploadManager.addEventListener('uploadProgress', updateEta)\n\tuploadManager.addEventListener('finished', onUploaderFinished)\n\tuploadManager.addEventListener('paused', onUploaderPaused)\n\tuploadManager.addEventListener('reset', updateUploadStatus)\n\tuploadManager.addEventListener('resumed', onUploaderResumed)\n\tupdateUploadStatus()\n})\nonUnmounted(() => {\n\twindow.removeEventListener('beforeunload', onBeforePageUnload)\n\tuploadManager.removeEventListener('uploadFinished', onUploadFinished)\n\tuploadManager.removeEventListener('uploadStarted', onUploadStarted)\n\tuploadManager.removeEventListener('uploadProgress', updateEta)\n\tuploadManager.removeEventListener('finished', onUploaderFinished)\n\tuploadManager.removeEventListener('paused', onUploaderPaused)\n\tuploadManager.removeEventListener('reset', updateUploadStatus)\n\tuploadManager.removeEventListener('resumed', onUploaderResumed)\n})\n\nwatch(() => props.destination, () => setDestination(props.destination), { immediate: true })\n\nconst isPaused = ref(uploadManager.status === UploaderStatus.PAUSED)\n/** Handle uploader paused event */\nfunction onUploaderPaused() {\n\tupdateUploadStatus()\n\temit('paused', [...uploadManager.queue])\n}\n/** Handle uploader resumed event */\nfunction onUploaderResumed() {\n\tupdateUploadStatus()\n\temit('resumed', [...uploadManager.queue])\n}\n\nconst hasFailure = ref(false)\nconst isUploading = ref(false)\nconst isAssembling = ref(false)\nconst isOnlyAssembling = ref(false)\n\n/**\n * Update the upload status flags based on the current queue\n */\nfunction updateUploadStatus() {\n\tisPaused.value = uploadManager.status === UploaderStatus.PAUSED\n\t// While paused the queue is not processed, but the queued uploads are still pending\n\tisUploading.value = uploadManager.status === UploaderStatus.UPLOADING\n\t\t|| (isPaused.value && uploadManager.queue.length > 0)\n\thasFailure.value = uploadManager.queue.some((upload: IUpload) => upload.status === UploadStatus.FAILED)\n\tisAssembling.value = uploadManager.queue.some((upload: IUpload) => upload.status === UploadStatus.ASSEMBLING)\n\t// only assembling if assembling at all AND all other uploads are already finished (or failed)\n\tisOnlyAssembling.value = isAssembling.value\n\t\t&& uploadManager.queue.every((upload: IUpload) => upload.status >= UploadStatus.ASSEMBLING)\n}\n\n/**\n * Reset the file input form\n */\nfunction reset() {\n\tfilePickerElement.value?.reset()\n}\n\n/**\n * Set the upload destination\n *\n * @param destination - The new upload destination\n */\nfunction setDestination(destination: IFolder) {\n\tif (!destination) {\n\t\tlogger.debug('Invalid destination')\n\t\treturn\n\t}\n\n\tuploadManager.destination = destination as Folder\n}\n\nconst etaProgress = ref(0)\nconst etaSpeed = ref('')\nconst etaRaw = ref<number>(Infinity)\nconst etaTimeRaw = computed(() => etaRaw.value === Infinity ? Infinity : new Date(Date.now() + etaRaw.value))\nconst etaTimeFormatted = useFormatRelativeTime(etaTimeRaw, { ignoreSeconds: true })\nconst etaTime = computed(() => etaTimeRaw.value === Infinity ? t('Estimating …') : etaTimeFormatted.value)\n/** Update the ETA and speed values */\nfunction updateEta() {\n\tetaRaw.value = uploadManager.statistics.eta === Infinity ? Infinity : (uploadManager.statistics.eta * 1000)\n\tetaSpeed.value = uploadManager.statistics.speedReadable\n\tetaProgress.value = uploadManager.statistics.progress\n}\n\n/**\n * Handle uploader finished event\n */\nfunction onUploaderFinished() {\n\tupdateUploadStatus()\n\temit('finished')\n}\n\n/**\n * Handle upload finished event\n *\n * @param event - The upload finished event\n */\nfunction onUploadFinished(event: CustomEvent<IUpload>) {\n\tupdateUploadStatus()\n\temit('upload:finished', event.detail)\n}\n\n/**\n * Handle upload started event\n *\n * @param event - The upload started event\n */\nfunction onUploadStarted(event: CustomEvent<IUpload>) {\n\tupdateUploadStatus()\n\temit('upload:started', event.detail)\n}\n\n/**\n * Start uploading\n *\n * @param files - The files to upload\n */\nasync function onPick(files: File[]) {\n\ttry {\n\t\tawait uploadManager\n\t\t\t.batchUpload('', files, { callback: handleConflicts })\n\t} catch (error) {\n\t\tlogger.debug('Error while uploading', { error })\n\t} finally {\n\t\treset()\n\t}\n}\n\n/**\n * Handle conflicts during upload\n *\n * @param nodes - The nodes that might conflict\n * @param currentPath - The path of the current directory\n */\nasync function handleConflicts(nodes: string[], currentPath: string): Promise<Record<string, string> | false> {\n\ttry {\n\t\tconst content = await props.content(currentPath)\n\t\tconst conflicts = content.filter((node) => nodes.includes(node.displayname) || nodes.includes(node.basename))\n\t\tconst uploadMapping = Object.fromEntries(nodes.map((name) => [name, name]))\n\t\tif (conflicts.length === 0) {\n\t\t\treturn uploadMapping\n\t\t}\n\n\t\t// The conflict picker requires the incoming and the existing nodes to be aligned,\n\t\t// so the existing content has to be filtered to only contain the conflicting nodes.\n\t\tconst existingNodes = content.filter((node) => nodes.includes(node.displayname) || nodes.includes(node.basename))\n\t\tconst result = await openConflictPicker(basename(currentPath), conflicts, existingNodes, { recursive: props.directory })\n\t\tif (result) {\n\t\t\tconst usedNames = content.map((node) => node.basename)\n\t\t\tfor (const node of conflicts) {\n\t\t\t\tif ((result.skipped as unknown as INode[]).some((skipped) => skipped.basename === node.basename)) {\n\t\t\t\t\tdelete uploadMapping[node.basename]\n\t\t\t\t} else if ((result.renamed as unknown as INode[]).some((renamed) => renamed.basename === node.basename)) {\n\t\t\t\t\tconst newName = getUniqueName(basename(node.basename), usedNames)\n\t\t\t\t\tuploadMapping[node.basename] = newName\n\t\t\t\t\tusedNames.push(newName)\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn uploadMapping\n\t\t}\n\t} catch (error) {\n\t\tlogger.error('Error during conflict resolution - skipping upload', { error })\n\t}\n\treturn false\n}\n\n/**\n * Cancel ongoing queue\n */\nfunction onCancel() {\n\tuploadManager.reset()\n\treset()\n}\n\n/**\n * Handle page unload.\n * Block the unload if there are ongoing uploads.\n *\n * @param event - The event\n */\nfunction onBeforePageUnload(event: BeforeUnloadEvent) {\n\tif (uploadManager.queue.length > 0) {\n\t\tevent.preventDefault()\n\t\tevent.returnValue = ''\n\t}\n}\n</script>\n\n<template>\n\t<NcFilePicker\n\t\tref=\"filePicker\"\n\t\t:accept\n\t\t:actionCaption=\"actions.length > 0 || directory ? t('Upload from device') : undefined\"\n\t\t:actions\n\t\t:directory\n\t\t:disabled\n\t\t:iconOnly\n\t\t:label\n\t\t:multiple\n\t\t:variant\n\t\t@pick=\"onPick\">\n\t\t<template #icon>\n\t\t\t<NcIconSvgWrapper :path=\"mdiPlus\" />\n\t\t</template>\n\n\t\t<!-- Progressbar and status -->\n\t\t<div\n\t\t\tv-show=\"isUploading\"\n\t\t\t:class=\"[$style.uploadPicker_progress, {\n\t\t\t\t[$style.uploadPicker_progress__uploading]: isUploading,\n\t\t\t\t[$style.uploadPicker_progress__paused]: isPaused,\n\t\t\t}]\">\n\t\t\t<NcProgressBar\n\t\t\t\t:ariaLabel=\"t('Upload progress')\"\n\t\t\t\t:ariaDescribedby=\"progressTimeId\"\n\t\t\t\t:error=\"hasFailure\"\n\t\t\t\t:value=\"etaProgress\"\n\t\t\t\tsize=\"medium\" />\n\t\t\t<p :id=\"progressTimeId\" :class=\"$style.uploadPicker_progressLabel\">\n\t\t\t\t<span v-if=\"isPaused\">\n\t\t\t\t\t{{ t('paused') /* TRANSLATORS: State of the current upload - it is paused */ }}\n\t\t\t\t</span>\n\t\t\t\t<span v-else-if=\"isOnlyAssembling\">\n\t\t\t\t\t{{ t('assembling') /* TRANSLATORS: State of the current upload - chunks of the uploaded files are being assembled into the final file */ }}\n\t\t\t\t</span>\n\t\t\t\t<span v-else :title=\"`${etaTime} (${etaSpeed})`\">\n\t\t\t\t\t{{ etaTime }}\n\t\t\t\t\t<!-- the speed is included in the tooltip / title so we only show it in the text content if there is enough space (not showing \"a few seconds left\") -->\n\t\t\t\t\t<span v-if=\"etaSpeed && etaRaw > 31000\" :class=\"$style.uploadPicker_progressLabelSpeed\">\n\t\t\t\t\t\t({{ etaSpeed }})\n\t\t\t\t\t</span>\n\t\t\t\t</span>\n\t\t\t</p>\n\t\t</div>\n\n\t\t<!-- Cancel upload button -->\n\t\t<NcButton\n\t\t\tv-if=\"isUploading && !isOnlyAssembling\"\n\t\t\t:class=\"$style.uploadPicker_cancelButton\"\n\t\t\t:aria-label=\"t('Cancel uploads')\"\n\t\t\tvariant=\"tertiary\"\n\t\t\t@click=\"onCancel\">\n\t\t\t<template #icon>\n\t\t\t\t<NcIconSvgWrapper :path=\"mdiClose\" />\n\t\t\t</template>\n\t\t</NcButton>\n\t</NcFilePicker>\n</template>\n\n<style module>\n.uploadPicker_progress {\n\t--upload-picker-progress-width: 200px;\n\twidth: var(--upload-picker-progress-width);\n\t/* Animate show/hide */\n\tmax-width: 0;\n\ttransition: max-width var(--animation-quick) ease-in-out;\n\t/* Align progress/text separation with the middle */\n\tmargin-top: 8px;\n}\n\n.uploadPicker_progress__uploading {\n\tmax-width: var(--upload-picker-progress-width);\n\n\t/* Visually more pleasing spacing */\n\tmargin-inline: 8px 20px;\n}\n\n.uploadPicker_progress__paused {\n\tanimation: breathing 3s ease-out infinite normal;\n}\n\n.uploadPicker_progressLabel {\n\toverflow: hidden;\n\twhite-space: nowrap;\n\ttext-overflow: ellipsis;\n}\n\n.uploadPicker_progressLabelSpeed{\n\tcolor: var(--color-text-maxcontrast);\n}\n\n@keyframes breathing {\n\t0% {\n\t\topacity: .5;\n\t}\n\t25% {\n\t\topacity: 1;\n\t}\n\t60% {\n\t\topacity: .5;\n\t}\n\t100% {\n\t\topacity: .5;\n\t}\n}\n</style>\n\n<docs>\n## Requirements\n\nTo use the `NcUploadPicker` component, you need to install the following packages:\n- `@nextcloud/dialogs`\n- `@nextcloud/files`\n\n## Usage\n\nThe upload picker lets users pick files – or whole directories – from their device and uploads them\nto a folder on the Nextcloud server, using the shared uploader of `@nextcloud/files/upload`.\nWhile uploading it shows the progress, the estimated remaining time and a button to cancel all queued uploads.\n\nTwo props are required to set it up:\n\n- `destination`: The folder to upload into, as an `IFolder` of `@nextcloud/files`.\n- `content`: A callback that resolves with the nodes that already exist in a folder that is uploaded into.\n It is called with the path relative to the `destination` – the empty string for the destination itself –\n and is used to detect upload conflicts. If there are conflicts, the user is asked to skip or rename\n the conflicting files.\n\n### Exposed methods\n\n- `function reset(): void`\n Reset the internal state of the picker, e.g. to clear the current selection.\n\n**Note**: All upload pickers share the global uploader instance of `getUploader()`,\nincluding its queue and its destination. Because of that only a single upload picker\nshould be mounted at a time – in the examples below the picker that was mounted last defines the destination.\n\n**Note about the examples**: There is no Nextcloud server behind the styleguide,\nso the examples use a fake WebDAV server that simulates slow – but always successful – uploads.\nUploading a file called `Photo.jpg` or `Notes.md` triggers the conflict dialog,\nfiles larger than 10 MiB are uploaded in chunks.\n\n### Basic usage\n\n```vue\n<template>\n\t<div>\n\t\t<NcUploadPicker\n\t\t\t:content=\"fetchContent\"\n\t\t\t:destination=\"destination\"\n\t\t\tmultiple\n\t\t\t@finished=\"log('finished')\"\n\t\t\t@upload:finished=\"log('upload:finished', $event)\"\n\t\t\t@upload:started=\"log('upload:started', $event)\" />\n\n\t\t<NcNoteCard v-if=\"events.length === 0\" type=\"info\">\n\t\t\tPick some files to upload them to <code>{{ destination.path }}</code>.\n\t\t</NcNoteCard>\n\t\t<ul v-else>\n\t\t\t<li v-for=\"(event, index) in events\" :key=\"index\">\n\t\t\t\t{{ event }}\n\t\t\t</li>\n\t\t</ul>\n\t</div>\n</template>\n<script>\nimport { File as NcFile, Folder, Permission } from '@nextcloud/files'\nimport { generateRemoteUrl } from '@nextcloud/router'\nimport { ref } from 'vue'\n\n// The folder the picked files are uploaded into\nconst destination = new Folder({\n\tid: 42,\n\towner: 'admin',\n\tpermissions: Permission.ALL,\n\troot: '/files/admin',\n\tsource: generateRemoteUrl('dav/files/admin/Uploads'),\n})\n\n// The nodes that already exist in the destination, in a real app this is the result of a PROPFIND\nconst existingNodes = ['Photo.jpg', 'Notes.md'].map((name) => new NcFile({\n\tmime: 'application/octet-stream',\n\towner: 'admin',\n\troot: '/files/admin',\n\tsource: `${destination.source}/${name}`,\n}))\n\nexport default {\n\tsetup() {\n\t\tconst events = ref([])\n\n\t\treturn {\n\t\t\tdestination,\n\t\t\tevents,\n\n\t\t\t// Provide the content of the folder that is uploaded into to allow detecting conflicts\n\t\t\tasync fetchContent(relativePath) {\n\t\t\t\t// Folders created by the upload itself are empty, so they never conflict\n\t\t\t\treturn relativePath ? [] : existingNodes\n\t\t\t},\n\n\t\t\tlog(name, upload) {\n\t\t\t\t// One `upload:*` event is emitted for the destination itself - shown as `/` - and one per picked file\n\t\t\t\tconst path = upload && decodeURIComponent(upload.source.slice(destination.source.length))\n\t\t\t\tevents.value.unshift(upload ? `${name}: ${path}` : name)\n\t\t\t},\n\t\t}\n\t},\n}\n</script>\n```\n\n### Directories and custom actions\n\nSetting `directory` adds an entry to upload a whole directory tree, which is recreated in the destination.\nAdditional entries – like the \"New folder\" action of the Files app – can be added using the `actions` prop,\neither as a flat list or grouped with a caption.\nThe `accept` prop restricts the file types that can be picked.\n\n```vue\n<template>\n\t<div>\n\t\t<NcUploadPicker\n\t\t\t:accept=\"['image/jpeg', 'image/png']\"\n\t\t\t:actions=\"actions\"\n\t\t\t:content=\"fetchContent\"\n\t\t\t:destination=\"destination\"\n\t\t\tdirectory\n\t\t\tlabel=\"Add media\"\n\t\t\tmultiple\n\t\t\tvariant=\"primary\" />\n\n\t\t<NcNoteCard v-if=\"lastAction\" type=\"success\">\n\t\t\t{{ lastAction }}\n\t\t</NcNoteCard>\n\t</div>\n</template>\n<script>\nimport svgFolderPlus from '@mdi/svg/svg/folder-plus-outline.svg?raw'\nimport svgLink from '@mdi/svg/svg/link-plus.svg?raw'\nimport { Folder, Permission } from '@nextcloud/files'\nimport { generateRemoteUrl } from '@nextcloud/router'\nimport { ref } from 'vue'\n\nconst destination = new Folder({\n\tid: 42,\n\towner: 'admin',\n\tpermissions: Permission.ALL,\n\troot: '/files/admin',\n\tsource: generateRemoteUrl('dav/files/admin/Uploads'),\n})\n\nexport default {\n\tsetup() {\n\t\tconst lastAction = ref('')\n\n\t\treturn {\n\t\t\tdestination,\n\t\t\tlastAction,\n\n\t\t\t// The destination is empty, so no upload will ever conflict\n\t\t\tasync fetchContent() {\n\t\t\t\treturn []\n\t\t\t},\n\n\t\t\tactions: [\n\t\t\t\t{\n\t\t\t\t\tcaption: 'Create new',\n\t\t\t\t\tactions: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tlabel: 'New folder',\n\t\t\t\t\t\t\ticonSvg: svgFolderPlus,\n\t\t\t\t\t\t\tonClick: () => {\n\t\t\t\t\t\t\t\tlastAction.value = 'Clicked \"New folder\"'\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tlabel: 'Add from link',\n\t\t\t\t\t\t\ticonSvg: svgLink,\n\t\t\t\t\t\t\tonClick: () => {\n\t\t\t\t\t\t\t\tlastAction.value = 'Clicked \"Add from link\"'\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t],\n\t\t}\n\t},\n}\n</script>\n```\n\n### Controlling the uploader\n\nThe uploader itself is not owned by the picker, so it can also be controlled directly.\nThis is useful to pause the queue – picked files are queued but not uploaded until it is resumed –\nor to change the destination while the picker is mounted.\n\n```vue\n<template>\n\t<div class=\"uploader-controls\">\n\t\t<NcUploadPicker\n\t\t\tref=\"picker\"\n\t\t\t:content=\"fetchContent\"\n\t\t\t:destination=\"destination\"\n\t\t\tmultiple />\n\n\t\t<NcButton @click=\"uploader.pause()\">\n\t\t\tPause\n\t\t</NcButton>\n\t\t<NcButton @click=\"uploader.start()\">\n\t\t\tResume\n\t\t</NcButton>\n\t</div>\n</template>\n<script>\nimport { Folder, Permission } from '@nextcloud/files'\nimport { getUploader } from '@nextcloud/files/upload'\nimport { generateRemoteUrl } from '@nextcloud/router'\n\n/**\n * Create a folder for the given path within the users files.\n *\n * @param {string} path - Path of the folder, e.g. `/Documents`\n */\nfunction createFolder(path) {\n\treturn new Folder({\n\t\tid: 42,\n\t\towner: 'admin',\n\t\tpermissions: Permission.ALL,\n\t\troot: '/files/admin',\n\t\tsource: generateRemoteUrl(`dav/files/admin${path}`),\n\t})\n}\n\nexport default {\n\tsetup() {\n\t\treturn {\n\t\t\tdestination: createFolder('/Uploads'),\n\t\t\totherDestination: createFolder('/Documents'),\n\t\t\tuploader: getUploader(),\n\n\t\t\tasync fetchContent() {\n\t\t\t\treturn []\n\t\t\t},\n\t\t}\n\t},\n}\n</script>\n<style scoped>\n.uploader-controls {\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\tgap: 8px;\n\talign-items: center;\n}\n</style>\n```\n</docs>\n"],"names":["_createBlock","_unref","_createVNode","_createElementVNode","_normalizeClass","$style","_openBlock","_createElementBlock","_createTextVNode","_toDisplayString"],"mappings":"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","x_google_ignoreList":[0]}
|
|
@@ -3,7 +3,7 @@ import { defineComponent, useModel, computed, watch, openBlock, createElementBlo
|
|
|
3
3
|
import axios from "@nextcloud/axios";
|
|
4
4
|
import { getCapabilities } from "@nextcloud/capabilities";
|
|
5
5
|
import { generateOcsUrl } from "@nextcloud/router";
|
|
6
|
-
import { r as register,
|
|
6
|
+
import { r as register, S as t54, T as t12, a as t } from "./_l10n.mjs";
|
|
7
7
|
import { l as logger } from "./logger.mjs";
|
|
8
8
|
import { _ as _export_sfc } from "./_plugin-vue_export-helper.mjs";
|
|
9
9
|
const awaySvg = '<!--\n - SPDX-FileCopyrightText: 2020 Google Inc.\n - SPDX-License-Identifier: Apache-2.0\n-->\n<svg viewBox="0 -960 960 960" width="24px" height="24px" xmlns="http://www.w3.org/2000/svg">\n <path\n fill="var(--user-status-color-away, var(--color-warning, #C88800))"\n d="m612-292 56-56-148-148v-184h-80v216l172 172ZM480-80q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Z"/>\n</svg>\n';
|
|
@@ -11,7 +11,7 @@ const busySvg = '<!--\n - SPDX-FileCopyrightText: 2020 Google Inc.\n - SPDX-Li
|
|
|
11
11
|
const dndSvg = '<!--\n - SPDX-FileCopyrightText: 2020 Google Inc.\n - SPDX-License-Identifier: Apache-2.0\n-->\n<svg viewBox="0 -960 960 960" width="24px" height="24px" xmlns="http://www.w3.org/2000/svg">\n <path\n fill="var(--user-status-color-busy, var(--color-error, #DB0606))"\n d="M280-440h400v-80H280v80ZM480-80q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Z"/>\n</svg>\n';
|
|
12
12
|
const invisibleSvg = '<!--\n - SPDX-FileCopyrightText: 2020 Google Inc.\n - SPDX-License-Identifier: Apache-2.0\n-->\n<svg viewBox="0 -960 960 960" width="24px" height="24px" xmlns="http://www.w3.org/2000/svg">\n <path\n fill="var(--user-status-color-offline, var(--color-text-maxcontrast, #6B6B6B))"\n d="M480-80q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/>\n</svg>\n';
|
|
13
13
|
const onlineSvg = '<!--\n - SPDX-FileCopyrightText: 2020 Google Inc.\n - SPDX-License-Identifier: Apache-2.0\n-->\n<svg viewBox="0 -960 960 960" width="24px" height="24px" xmlns="http://www.w3.org/2000/svg">\n <path\n fill="var(--user-status-color-online, var(--color-success, #2D7B41))"\n d="m424-296 282-282-56-56-226 226-114-114-56 56 170 170Zm56 216q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Z"/>\n</svg>\n';
|
|
14
|
-
register(
|
|
14
|
+
register(t54);
|
|
15
15
|
register(t12);
|
|
16
16
|
function getUserStatusText(status) {
|
|
17
17
|
switch (status) {
|