Files
nextcloud-server-mirror/dist/files-settings-admin.mjs.map
2026-10-07 08:58:40 +00:00

1 line
16 KiB
Plaintext

{"version":3,"file":"files-settings-admin.mjs","sources":["../build/frontend/apps/files/src/models/SanitizeFilenameStatus.ts","../build/frontend/apps/files/src/components/Settings/SettingsSanitizeFilenames.vue","../build/frontend/apps/files/src/views/SettingsAdmin.vue","../build/frontend/apps/files/src/main-settings-admin.ts"],"sourcesContent":["/*!\n * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\n/**\n * The current status of the filename sanitization\n */\nexport enum SanitizeFilenameStatus {\n\tUnknown = 0,\n\tScheduled = 1,\n\tRunning = 2,\n\tDone = 3,\n\tError = 4,\n}\n","<!--\n - SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors\n - SPDX-License-Identifier: AGPL-3.0-or-later\n-->\n\n<script setup lang=\"ts\">\nimport type { OCSResponse } from '@nextcloud/typings/ocs'\n\nimport axios, { isAxiosError } from '@nextcloud/axios'\nimport { showError } from '@nextcloud/dialogs'\nimport { loadState } from '@nextcloud/initial-state'\nimport { t } from '@nextcloud/l10n'\nimport { generateOcsUrl } from '@nextcloud/router'\nimport { computed, ref, shallowRef } from 'vue'\nimport NcButton from '@nextcloud/vue/components/NcButton'\nimport NcInputField from '@nextcloud/vue/components/NcInputField'\nimport NcLoadingIcon from '@nextcloud/vue/components/NcLoadingIcon'\nimport NcNoteCard from '@nextcloud/vue/components/NcNoteCard'\nimport NcProgressBar from '@nextcloud/vue/components/NcProgressBar'\nimport { SanitizeFilenameStatus } from '../../models/SanitizeFilenameStatus.ts'\nimport { logger } from '../../utils/logger.ts'\n\ntype ApiStatus = { total: number, processed: number, errors?: Record<string, string[]>, status: SanitizeFilenameStatus }\n\nconst { status: initialStatus } = loadState<{ isRunningSanitization: boolean, status: ApiStatus }>('files', 'filesCompatibilitySettings')\n\nconst loading = ref(false)\nconst renameLimit = ref(10)\nconst status = ref(initialStatus.status)\nconst processedUsers = ref(initialStatus.processed)\nconst totalUsers = ref(initialStatus.total)\nconst errors = shallowRef<ApiStatus['errors']>(initialStatus.errors || {})\n\nconst progress = computed(() => processedUsers.value > 0 ? Math.round((processedUsers.value * 100) / totalUsers.value) : 0)\nconst isRunning = computed(() => status.value === SanitizeFilenameStatus.Scheduled || status.value === SanitizeFilenameStatus.Running)\n\n/**\n * Start the sanitization process\n */\nasync function startSanitization() {\n\tif (isRunning.value) {\n\t\treturn\n\t}\n\n\ttry {\n\t\tloading.value = true\n\t\tawait axios.post(generateOcsUrl('apps/files/api/v1/filenames/sanitization'), {\n\t\t\tlimit: renameLimit.value,\n\t\t})\n\t\tstatus.value = SanitizeFilenameStatus.Scheduled\n\t} catch (error) {\n\t\tlogger.error('Failed to start filename sanitization.', { error })\n\n\t\tif (isAxiosError(error) && error.response?.data?.ocs) {\n\t\t\tshowError((error.response.data as OCSResponse).ocs.meta.message!)\n\t\t} else {\n\t\t\tshowError(t('files', 'Failed to start filename sanitization.'))\n\t\t}\n\t} finally {\n\t\tloading.value = false\n\t}\n}\n\n/**\n * Refresh the filename sanitization status\n */\nasync function refreshStatus() {\n\tif (loading.value) {\n\t\treturn\n\t}\n\n\ttry {\n\t\tloading.value = true\n\t\tconst { data } = await axios.get<OCSResponse<ApiStatus>>(generateOcsUrl('apps/files/api/v1/filenames/sanitization'))\n\t\tstatus.value = data.ocs.data.status\n\t\ttotalUsers.value = data.ocs.data.total\n\t\tprocessedUsers.value = data.ocs.data.processed\n\t\terrors.value = data.ocs.data.errors || {}\n\t} catch (error) {\n\t\tlogger.error('Failed to refresh filename sanitization status.', { error })\n\t\tshowError(t('files', 'Failed to refresh filename sanitization status.'))\n\t} finally {\n\t\tloading.value = false\n\t}\n}\n</script>\n\n<template>\n\t<NcNoteCard v-if=\"isRunning\">\n\t\t<div class=\"sanitize-filenames__progress-container\">\n\t\t\t<p>\n\t\t\t\t{{ t('files', 'Filename sanitization in progress.') }}\n\t\t\t\t<br>\n\t\t\t\t<template v-if=\"processedUsers > 0\">\n\t\t\t\t\t{{ t('files', 'Currently {processedUsers} of {totalUsers} accounts are already processed.', { processedUsers, totalUsers }) }}\n\t\t\t\t</template>\n\t\t\t\t<template v-else>\n\t\t\t\t\t{{ t('files', 'Preparing …') }}\n\t\t\t\t</template>\n\t\t\t</p>\n\t\t\t<NcProgressBar :value=\"progress\" :size=\"12\" />\n\t\t\t<NcButton variant=\"tertiary\" @click=\"refreshStatus\">\n\t\t\t\t<template v-if=\"loading\" #icon>\n\t\t\t\t\t<NcLoadingIcon />\n\t\t\t\t</template>\n\t\t\t\t{{ t('files', 'Refresh') }}\n\t\t\t</NcButton>\n\t\t</div>\n\t</NcNoteCard>\n\n\t<NcNoteCard v-else-if=\"status === SanitizeFilenameStatus.Done\" type=\"success\">\n\t\t{{ t('files', 'All files have been sanitized for Windows filename support.') }}\n\t</NcNoteCard>\n\n\t<form\n\t\tv-else\n\t\tclass=\"sanitize-filenames__form\"\n\t\t:disabled=\"loading\"\n\t\t@submit.stop.prevent=\"startSanitization\">\n\t\t<NcNoteCard v-if=\"status === SanitizeFilenameStatus.Error\" type=\"error\">\n\t\t\t{{ t('files', 'Some files could not be sanitized, please check your logs.') }}\n\t\t\t<ul class=\"sanitize-filenames__errors\" :aria-label=\"t('files', 'Sanitization errors')\">\n\t\t\t\t<li v-for=\"[user, failedFiles] of Object.entries(errors)\" :key=\"user\">\n\t\t\t\t\t<h4>{{ user }}:</h4>\n\t\t\t\t\t<ul :aria-label=\"t('files', 'Not sanitized filenames')\">\n\t\t\t\t\t\t<li v-for=\"file of failedFiles\" :key=\"file\">\n\t\t\t\t\t\t\t{{ file }}\n\t\t\t\t\t\t</li>\n\t\t\t\t\t</ul>\n\t\t\t\t</li>\n\t\t\t</ul>\n\t\t</NcNoteCard>\n\t\t<NcNoteCard>\n\t\t\t{{ t('files', 'Windows filename support has been enabled.') }}\n\t\t\t<br>\n\t\t\t{{ t('files', 'While this blocks users from creating new files with unsupported filenames, existing files are not yet renamed and thus still may break sync on Windows.') }}\n\t\t\t{{ t('files', 'You can trigger a rename of files with invalid filenames, this will be done in the background and may take some time.') }}\n\t\t\t{{ t('files', 'Please note that this may cause high workload on the sync clients.') }}\n\t\t</NcNoteCard>\n\n\t\t<fieldset class=\"sanitize-filenames__fields\">\n\t\t\t<NcInputField\n\t\t\t\tv-model=\"renameLimit\"\n\t\t\t\t:label=\"t('files', 'Limit')\"\n\t\t\t\t:helperText=\"t('files', 'This allows to configure how many users should be processed in one background job run.')\"\n\t\t\t\tmin=\"1\"\n\t\t\t\ttype=\"number\" />\n\n\t\t\t<NcButton type=\"submit\" variant=\"error\">\n\t\t\t\t<template v-if=\"loading\" #icon>\n\t\t\t\t\t<NcLoadingIcon />\n\t\t\t\t</template>\n\t\t\t\t{{ t('files', 'Sanitize filenames') }}\n\t\t\t\t<span v-if=\"loading\" class=\"hidden-visually\">\n\t\t\t\t\t{{ t('files', '(starting)') }}\n\t\t\t\t</span>\n\t\t\t</NcButton>\n\t\t</fieldset>\n\t</form>\n</template>\n\n<style scoped>\n.sanitize-filenames__progress-container {\n\talign-items: end;\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: var(--default-grid-baseline);\n}\n\n.sanitize-filenames__form {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: var(--default-grid-baseline);\n}\n\n.sanitize-filenames__fields {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: var(--default-grid-baseline);\n\n\talign-items: end;\n\tmax-width: 400px;\n}\n</style>\n","<!--\n - SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors\n - SPDX-License-Identifier: AGPL-3.0-or-later\n-->\n\n<script setup lang=\"ts\">\nimport axios from '@nextcloud/axios'\nimport { showError } from '@nextcloud/dialogs'\nimport { loadState } from '@nextcloud/initial-state'\nimport { t } from '@nextcloud/l10n'\nimport { generateOcsUrl } from '@nextcloud/router'\nimport { ref } from 'vue'\nimport NcCheckboxRadioSwitch from '@nextcloud/vue/components/NcCheckboxRadioSwitch'\nimport NcSettingsSection from '@nextcloud/vue/components/NcSettingsSection'\nimport SettingsSanitizeFilenames from '../components/Settings/SettingsSanitizeFilenames.vue'\nimport { logger } from '../utils/logger.ts'\n\nconst {\n\tdocUrl,\n\tisRunningSanitization,\n\twindowsSupport,\n} = loadState<{ docUrl: string, isRunningSanitization: boolean, windowsSupport: boolean }>('files', 'filesCompatibilitySettings')\n\nconst description = t('files', 'Allow to restrict filenames to ensure files can be synced with all clients. By default all filenames valid on POSIX (e.g. Linux or macOS) are allowed.')\n\t+ '\\n' + t('files', 'After enabling the Windows compatible filenames, existing files cannot be modified anymore but can be renamed to valid new names by their owner.')\n\nconst loading = ref(false)\nconst hasWindowsSupport = ref(windowsSupport)\n\n/**\n * Toggle the Windows filename support on the backend.\n *\n * @param enabled - The new state to be set\n */\nasync function toggleWindowsFilenameSupport(enabled: boolean) {\n\tif (loading.value) {\n\t\treturn\n\t}\n\n\ttry {\n\t\tloading.value = true\n\t\tawait axios.post(generateOcsUrl('apps/files/api/v1/filenames/windows-compatibility'), { enabled })\n\t\thasWindowsSupport.value = enabled\n\t} catch (error) {\n\t\tshowError(t('files', 'Failed to toggle Windows filename support'))\n\t\tlogger.error('Failed to toggle Windows filename support', { error })\n\t} finally {\n\t\tloading.value = false\n\t}\n}\n</script>\n\n<template>\n\t<NcSettingsSection\n\t\t:docUrl=\"docUrl\"\n\t\t:name=\"t('files', 'Files compatibility')\"\n\t\t:description=\"description\">\n\t\t<NcCheckboxRadioSwitch\n\t\t\t:modelValue=\"hasWindowsSupport\"\n\t\t\t:disabled=\"isRunningSanitization\"\n\t\t\t:loading=\"loading\"\n\t\t\ttype=\"switch\"\n\t\t\t@update:modelValue=\"toggleWindowsFilenameSupport\">\n\t\t\t{{ t('files', 'Enforce Windows compatibility') }}\n\t\t</NcCheckboxRadioSwitch>\n\t\t<p class=\"hint\">\n\t\t\t{{ t('files', 'This will block filenames not valid on Windows systems, like using reserved names or special characters. But this will not enforce compatibility of case sensitivity.') }}\n\t\t</p>\n\n\t\t<SettingsSanitizeFilenames v-if=\"hasWindowsSupport\" />\n\t</NcSettingsSection>\n</template>\n\n<style scoped>\n.hint {\n\tcolor: var(--color-text-maxcontrast);\n\tmargin-inline-start: var(--border-radius-element);\n\tmargin-block-end: 1em;\n}\n</style>\n","/**\n * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\nimport { t } from '@nextcloud/l10n'\nimport { createApp } from 'vue'\nimport PersonalSettings from './views/SettingsAdmin.vue'\n\nimport 'vite/modulepreload-polyfill'\n\nconst app = createApp(PersonalSettings)\napp.config.globalProperties.t = t\napp.mount('#files-admin-settings')\n"],"names":["SanitizeFilenameStatus","initialStatus","loadState","loading","ref","renameLimit","status","processedUsers","totalUsers","errors","shallowRef","progress","computed","isRunning","startSanitization","axios","generateOcsUrl","error","logger","isAxiosError","showError","t","refreshStatus","data","_createBlock","_unref","NcNoteCard","_createElementVNode","_hoisted_1","_createTextVNode","_toDisplayString","_createElementBlock","_Fragment","_createVNode","NcProgressBar","NcButton","NcLoadingIcon","_renderList","user","failedFiles","file","_openBlock","_hoisted_5","NcInputField","$event","_hoisted_6","docUrl","isRunningSanitization","windowsSupport","description","hasWindowsSupport","toggleWindowsFilenameSupport","enabled","NcSettingsSection","NcCheckboxRadioSwitch","SettingsSanitizeFilenames","app","createApp","PersonalSettings"],"mappings":"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"}