Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,23 +1,25 @@
<template>
<div id="oc-file-details-sidebar" class="p-2">
<div v-if="hasContent">
<div class="flex items-center justify-center bg-role-surface-container rounded-xl p-4 mb-4">
<div v-if="preview || isPreviewLoading" data-testid="preview">
<oc-spinner v-if="isPreviewLoading" :aria-label="$gettext('Loading preview')" />
<img
v-else
key="file-thumbnail"
:src="preview"
class="details-preview h-[160px]"
alt=""
/>
<div
class="relative flex items-center justify-center bg-role-surface-container rounded-xl p-4 mb-4"
>
<div v-if="preview" data-testid="preview">
<img key="file-thumbnail" :src="preview" class="details-preview h-[160px]" alt="" />
</div>
<resource-icon
v-else
class="details-icon h-[160px]"
:resource="resource"
size-class="size-22"
/>
<div
v-if="isPreviewLoading"
data-testid="preview-loading"
class="absolute inset-0 z-10 flex items-center justify-center bg-role-surface/70"
>
<oc-spinner :aria-label="$gettext('Loading preview')" />
</div>
</div>
<div
v-if="!publicLinkContextReady && shareIndicators.length"
Expand All @@ -28,11 +30,23 @@
<oc-status-indicators :resource="resource" :indicators="shareIndicators" />
<p class="my-0 mx-2" v-text="detailSharingInformation" />
</div>
<div v-if="detailsLoading" class="flex justify-center">
<oc-spinner :aria-label="$gettext('Loading details')" />
<div class="flex justify-end min-h-5">
<oc-spinner
v-if="versionsLoading"
v-oc-tooltip="$gettext('Loading version information')"
size="small"
:aria-label="$gettext('Loading version information')"
/>
<oc-icon
v-else-if="versionsError"
v-oc-tooltip="$gettext('Version information could not be loaded')"
name="error-warning"
fill-type="line"
size="small"
class="text-role-error"
/>
</div>
<dl
v-else
class="details-list"
:aria-label="$gettext('Overview of the information about the selected file')"
>
Expand Down Expand Up @@ -89,10 +103,12 @@
<dd data-testid="sizeInfo">{{ resourceSize }}</dd>
</template>
<web-dav-details v-if="showWebDavDetails" :space="space" />
<template v-if="showVersions">
<template v-if="versionsRowVisible">
<dt>{{ $gettext('Version') }}</dt>
<dd data-testid="versionsInfo">
<span v-if="versionsPlaceholder" aria-hidden="true">&nbsp;</span>
<oc-button
v-else
v-oc-tooltip="seeVersionsLabel"
appearance="raw"
:aria-label="seeVersionsLabel"
Expand Down Expand Up @@ -181,7 +197,8 @@ const { user } = storeToRefs(userStore)

const resource = inject<Ref<Resource>>('resource')
const versions = inject<Ref<Resource[]>>('versions')
const versionsLoading = inject<Ref<boolean>>('versionsLoading')
const versionsLoading = inject<Ref<boolean>>('versionsLoading', ref(false))
const versionsError = inject<Ref<boolean>>('versionsError', ref(false))
const space = inject<Ref<SpaceResource>>('space')
Comment thread
Copilot marked this conversation as resolved.

const preview = ref<string>(undefined)
Expand All @@ -190,7 +207,6 @@ const authStore = useAuthStore()
const { publicLinkContextReady } = storeToRefs(authStore)

const isPreviewLoading = computed(() => previewEnabled && unref(previewsLoading))
const detailsLoading = computed(() => unref(versionsLoading))

const sharedAncestor = computed(() => {
return Object.values(unref(ancestorMetaData)).find(
Expand Down Expand Up @@ -304,6 +320,22 @@ const showVersions = computed(() => {
}
return unref(versions).length > 0
})
// Reserve the version row as an empty placeholder during load only if the
// previous resource had one, so the layout does not shift.
const stickyShowVersions = ref(false)
watch(
versionsLoading,
(loading) => {
if (!loading) {
stickyShowVersions.value = !!unref(showVersions)
}
},
{ immediate: true }
)
const versionsPlaceholder = computed(() => unref(versionsLoading) && unref(stickyShowVersions))
const versionsRowVisible = computed(() =>
unref(versionsLoading) ? unref(stickyShowVersions) : !!unref(showVersions)
)
const seeVersionsLabel = computed(() => {
return $gettext('See all versions')
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ const getResourceMock = ({
const selectors = {
ownerDisplayName: '[data-testid="ownerDisplayName"]',
preview: '[data-testid="preview"]',
previewLoading: '[data-testid="preview-loading"]',
resourceIcon: '.details-icon',
lockedBy: '[data-testid="locked-by"]',
sharedBy: '[data-testid="shared-by"]',
Expand All @@ -60,19 +61,16 @@ const selectors = {

describe('Details SideBar Panel', () => {
describe('preview', () => {
describe('shows preview area', () => {
it('while trying to load a preview', () => {
const resource = getResourceMock()
const { wrapper } = createWrapper({ resource })
expect(wrapper.find(selectors.preview).exists()).toBeTruthy()
expect(wrapper.find(selectors.resourceIcon).exists()).toBeFalsy()
})
it('for allowed mime types', () => {
const resource = getResourceMock()
const { wrapper } = createWrapper({ resource })
expect(wrapper.find(selectors.preview).exists()).toBeTruthy()
expect(wrapper.find(selectors.resourceIcon).exists()).toBeFalsy()
})
it('shows the resource icon while the preview is loading', () => {
const resource = getResourceMock()
const { wrapper } = createWrapper({ resource })
expect(wrapper.find(selectors.resourceIcon).exists()).toBeTruthy()
expect(wrapper.find(selectors.preview).exists()).toBeFalsy()
})
it('shows a loading overlay while the preview is loading', () => {
const resource = getResourceMock()
const { wrapper } = createWrapper({ resource })
expect(wrapper.find(selectors.previewLoading).exists()).toBeTruthy()
})
})
describe('status indicators', () => {
Expand Down
13 changes: 12 additions & 1 deletion packages/web-pkg/src/components/SideBar/FileSideBar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ const { loadSharesTask, availableExternalShareRoles, availableInternalShareRoles

const loadedResource = ref<Resource>()
const versions = ref<Resource[]>([])
const versionsError = ref(false)

const { selectedResources } = useSelectedResources()

Expand Down Expand Up @@ -147,7 +148,13 @@ const loadGraphPermissionsTask = useTask(function* (signal) {
})

const loadVersionsTask = useTask(function* (signal, resource: Resource) {
versions.value = yield clientService.webdav.listFileVersions(resource.id, { signal })
try {
versions.value = yield clientService.webdav.listFileVersions(resource.id, { signal })
versionsError.value = false
} catch (e) {
versionsError.value = true
throw e
}
})

const currentResourceMtime = ref<string>() // used to check if we need to load new versions
Expand All @@ -163,6 +170,8 @@ function loadVersions(resource: Resource) {
return
}

versions.value = []
versionsError.value = false
loadedVersionsResourceId.value = resource.id
currentResourceMtime.value = resource.mdate

Expand Down Expand Up @@ -242,6 +251,7 @@ function resetSidebarResource() {
loadedSharesResourceId.value = undefined
loadedVersionsResourceId.value = undefined
versions.value = []
versionsError.value = false
sharesStore.pruneShares()
loadedResource.value = null
}
Expand Down Expand Up @@ -318,4 +328,5 @@ provide(
'versionsLoading',
computed(() => loadVersionsTask.isRunning)
)
provide('versionsError', readonly(versionsError))
</script>