diff --git a/app/src/components/v-upload/v-upload.vue b/app/src/components/v-upload/v-upload.vue index 0b0d3b69e8..0fad1a6123 100644 --- a/app/src/components/v-upload/v-upload.vue +++ b/app/src/components/v-upload/v-upload.vue @@ -88,6 +88,7 @@ + + diff --git a/app/src/modules/files/routes/item.vue b/app/src/modules/files/routes/item.vue index 35a624ae57..67fb6bd885 100644 --- a/app/src/modules/files/routes/item.vue +++ b/app/src/modules/files/routes/item.vue @@ -119,15 +119,13 @@ :width="item.width" :height="item.height" :title="item.title" - @click="previewActive = true" + @click="replaceFileDialogActive = true" /> - - @@ -156,7 +154,7 @@ - + + + @@ -184,7 +184,6 @@ import SaveOptions from '@/views/private/components/save-options'; import FilePreview from '@/views/private/components/file-preview'; import ImageEditor from '@/views/private/components/image-editor'; import { nanoid } from 'nanoid'; -import FileLightbox from '@/views/private/components/file-lightbox'; import { useFieldsStore } from '@/stores/'; import { Field } from '@/types'; import FileInfoSidebarDetail from '../components/file-info-sidebar-detail.vue'; @@ -194,6 +193,7 @@ import api from '@/api'; import getRootPath from '@/utils/get-root-path'; import FilesNotFound from './not-found.vue'; import useShortcut from '@/composables/use-shortcut'; +import ReplaceFile from '../components/replace-file.vue'; type Values = { [field: string]: any; @@ -220,10 +220,10 @@ export default defineComponent({ SaveOptions, FilePreview, ImageEditor, - FileLightbox, FileInfoSidebarDetail, FolderPicker, FilesNotFound, + ReplaceFile, }, props: { primaryKey: { @@ -236,6 +236,7 @@ export default defineComponent({ const { primaryKey } = toRefs(props); const { breadcrumb } = useBreadcrumb(); const fieldsStore = useFieldsStore(); + const replaceFileDialogActive = ref(false); const revisionsDrawerDetail = ref(null); @@ -256,13 +257,15 @@ export default defineComponent({ const hasEdits = computed(() => Object.keys(edits.value).length > 0); const confirmDelete = ref(false); - const cacheBuster = ref(nanoid()); const editActive = ref(false); - const previewActive = ref(false); const fileSrc = computed(() => { - return ( - getRootPath() + `assets/${props.primaryKey}?cache-buster=${cacheBuster.value}&key=system-large-contain` - ); + if (item.value && item.value.modified_on) { + return ( + getRootPath() + + `assets/${props.primaryKey}?cache-buster=${item.value.modified_on}&key=system-large-contain` + ); + } + return getRootPath() + `assets/${props.primaryKey}?key=system-large-contain`; }); // These are the fields that will be prevented from showing up in the form because they'll be shown in the sidebar @@ -318,10 +321,7 @@ export default defineComponent({ saveAndStay, saveAsCopyAndNavigate, isBatch, - changeCacheBuster, - cacheBuster, editActive, - previewActive, revisionsDrawerDetail, formFields, confirmLeave, @@ -335,12 +335,10 @@ export default defineComponent({ fileSrc, form, to, + replaceFileDialogActive, + refresh, }; - function changeCacheBuster() { - cacheBuster.value = nanoid(); - } - function useBreadcrumb() { const breadcrumb = computed(() => { if (!item?.value?.folder) { @@ -405,7 +403,7 @@ export default defineComponent({ const selectedFolder = ref(); watch(item, () => { - selectedFolder.value = item.value.folder; + selectedFolder.value = item.value?.folder || null; }); return { moveToDialogActive, moving, moveToFolder, selectedFolder }; diff --git a/app/src/modules/settings/routes/roles/item/item.vue b/app/src/modules/settings/routes/roles/item/item.vue index fd7161f136..3cbacd5f55 100644 --- a/app/src/modules/settings/routes/roles/item/item.vue +++ b/app/src/modules/settings/routes/roles/item/item.vue @@ -133,7 +133,7 @@ export default defineComponent({ const values = { ...item.value, ...edits.value, - }; + } as Record; return !!values.admin_access; }); diff --git a/app/src/modules/settings/routes/webhooks/item.vue b/app/src/modules/settings/routes/webhooks/item.vue index bbcb6bd156..5744bb66c0 100644 --- a/app/src/modules/settings/routes/webhooks/item.vue +++ b/app/src/modules/settings/routes/webhooks/item.vue @@ -115,7 +115,7 @@ export default defineComponent({ const title = computed(() => { if (loading.value) return i18n.t('loading'); if (isNew.value) return i18n.t('creating_webhook'); - return item.value.name; + return item.value?.name; }); return { diff --git a/app/src/modules/users/routes/item.vue b/app/src/modules/users/routes/item.vue index 9c44f53655..24c42cd262 100644 --- a/app/src/modules/users/routes/item.vue +++ b/app/src/modules/users/routes/item.vue @@ -384,7 +384,7 @@ export default defineComponent({ } async function refreshCurrentUser() { - if (userStore.state.currentUser!.id === item.value.id) { + if (userStore.state.currentUser!.id === item.value?.id) { await userStore.hydrate(); } } diff --git a/app/src/utils/is-allowed.ts b/app/src/utils/is-allowed.ts index 904b10c379..6555154264 100644 --- a/app/src/utils/is-allowed.ts +++ b/app/src/utils/is-allowed.ts @@ -2,7 +2,7 @@ import { usePermissionsStore, useUserStore } from '@/stores'; import { Permission } from '@/types'; import generateJoi from '@/utils/generate-joi'; -export function isAllowed(collection: string, action: Permission['action'], value: Record) { +export function isAllowed(collection: string, action: Permission['action'], value: Record | null) { const permissionsStore = usePermissionsStore(); const userStore = useUserStore(); diff --git a/app/src/utils/upload-file/upload-file.ts b/app/src/utils/upload-file/upload-file.ts index 138b4e8e3b..9043ad7808 100644 --- a/app/src/utils/upload-file/upload-file.ts +++ b/app/src/utils/upload-file/upload-file.ts @@ -11,6 +11,7 @@ export default async function uploadFile( onProgressChange?: (percentage: number) => void; notifications?: boolean; preset?: Record; + fileId?: string; } ) { const progressHandler = options?.onProgressChange || (() => undefined); @@ -25,9 +26,17 @@ export default async function uploadFile( formData.append('file', file); try { - const response = await api.post(`/files`, formData, { - onUploadProgress, - }); + let response = null; + + if (options?.fileId !== undefined) { + response = await api.patch(`/files/${options.fileId}`, formData, { + onUploadProgress, + }); + } else { + response = await api.post(`/files`, formData, { + onUploadProgress, + }); + } if (options?.notifications) { notify({ diff --git a/app/src/views/private/components/file-preview/file-preview.vue b/app/src/views/private/components/file-preview/file-preview.vue index 4ccc07b16d..e6c3b9cd23 100644 --- a/app/src/views/private/components/file-preview/file-preview.vue +++ b/app/src/views/private/components/file-preview/file-preview.vue @@ -1,16 +1,21 @@ - + - + @@ -106,9 +111,9 @@ audio { } img { - max-height: inherit; z-index: 1; display: block; + max-height: inherit; margin: 0 auto; }