Merge pull request #48893 from nextcloud/backport/48625/stable30

[stable30] fix(files): handle empty view with error
This commit is contained in:
Grigorii K. Shartsev 2024-10-25 20:55:20 +05:00 committed by GitHub
commit 5c188bf977
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
21 changed files with 90 additions and 42 deletions

View file

@ -33,7 +33,7 @@
<script>
import { encodePath } from '@nextcloud/paths'
import { generateUrl } from '@nextcloud/router'
import { getToken, isPublic } from '../utils/davUtils.js'
import { isPublicShare, getSharingToken } from '@nextcloud/sharing/public'
// preview width generation
const previewWidth = 256
@ -107,8 +107,8 @@ export default {
return this.previewUrl
}
// TODO: find a nicer standard way of doing this?
if (isPublic()) {
return generateUrl(`/apps/files_sharing/publicpreview/${getToken()}?fileId=${this.fileid}&file=${encodePath(this.filename)}&x=${previewWidth}&y=${previewWidth}&a=1`)
if (isPublicShare()) {
return generateUrl(`/apps/files_sharing/publicpreview/${getSharingToken()}?fileId=${this.fileid}&file=${encodePath(this.filename)}&x=${previewWidth}&y=${previewWidth}&a=1`)
}
return generateUrl(`/core/preview?fileId=${this.fileid}&x=${previewWidth}&y=${previewWidth}&a=1`)
},

View file

@ -1,14 +0,0 @@
/**
* SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import { getCurrentUser } from '@nextcloud/auth'
export const isPublic = function() {
return !getCurrentUser()
}
export const getToken = function() {
return document.getElementById('sharingToken') && document.getElementById('sharingToken').value
}

View file

@ -0,0 +1,41 @@
/**
* SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import { t } from '@nextcloud/l10n'
import type { WebDAVClientError } from 'webdav'
/**
* Whether error is a WebDAVClientError
* @param error - Any exception
* @return {boolean} - Whether error is a WebDAVClientError
*/
function isWebDAVClientError(error: unknown): error is WebDAVClientError {
return error instanceof Error && 'status' in error && 'response' in error
}
/**
* Get a localized error message from webdav request
* @param error - An exception from webdav request
* @return {string} Localized error message for end user
*/
export function humanizeWebDAVError(error: unknown) {
if (error instanceof Error) {
if (isWebDAVClientError(error)) {
const status = error.status || error.response?.status || 0
if ([400, 404, 405].includes(status)) {
return t('files', 'Folder not found')
} else if (status === 403) {
return t('files', 'This operation is forbidden')
} else if (status === 500) {
return t('files', 'This directory is unavailable, please check the logs or contact the administrator')
} else if (status === 503) {
return t('files', 'Storage is temporarily not available')
}
}
return t('files', 'Unexpected error: {error}', { error: error.message })
}
return t('files', 'Unknown error')
}

View file

@ -75,16 +75,32 @@
<!-- Empty content placeholder -->
<template v-else-if="!loading && isEmptyDir">
<div v-if="currentView?.emptyView" class="files-list__empty-view-wrapper">
<!-- Empty due to error -->
<NcEmptyContent v-if="error" :name="error" data-cy-files-content-error>
<template #action>
<NcButton type="secondary" @click="fetchContent">
<template #icon>
<IconReload :size="20" />
</template>
{{ t('files', 'Retry') }}
</NcButton>
</template>
<template #icon>
<IconAlertCircleOutline />
</template>
</NcEmptyContent>
<!-- Custom empty view -->
<div v-else-if="currentView?.emptyView" class="files-list__empty-view-wrapper">
<div ref="customEmptyView" />
</div>
<!-- Default empty directory view -->
<NcEmptyContent v-else
:name="currentView?.emptyTitle || t('files', 'No files in here')"
:description="currentView?.emptyCaption || t('files', 'Upload some content or sync with your devices!')"
data-cy-files-content-empty>
<template v-if="directory !== '/'" #action>
<!-- Uploader -->
<UploadPicker v-if="currentFolder && canUpload && !isQuotaExceeded"
<UploadPicker v-if="canUpload && !isQuotaExceeded"
allow-folders
class="files-list__header-upload-button"
:content="getContent"
@ -93,10 +109,7 @@
multiple
@failed="onUploadFail"
@uploaded="onUpload" />
<NcButton v-else
:aria-label="t('files', 'Go to the previous folder')"
:to="toPreviousDir"
type="primary">
<NcButton v-else :to="toPreviousDir" type="primary">
{{ t('files', 'Go back') }}
</NcButton>
</template>
@ -134,6 +147,8 @@ import { UploadPicker, UploadStatus } from '@nextcloud/upload'
import { loadState } from '@nextcloud/initial-state'
import { defineComponent } from 'vue'
import IconAlertCircleOutline from 'vue-material-design-icons/AlertCircleOutline.vue'
import IconReload from 'vue-material-design-icons/Reload.vue'
import LinkIcon from 'vue-material-design-icons/Link.vue'
import ListViewIcon from 'vue-material-design-icons/FormatListBulletedSquare.vue'
import NcAppContent from '@nextcloud/vue/dist/Components/NcAppContent.js'
@ -161,6 +176,7 @@ import filesListWidthMixin from '../mixins/filesListWidth.ts'
import filesSortingMixin from '../mixins/filesSorting.ts'
import logger from '../logger.ts'
import DragAndDropNotice from '../components/DragAndDropNotice.vue'
import { humanizeWebDAVError } from '../utils/davUtils.ts'
const isSharingEnabled = (getCapabilities() as { files_sharing?: boolean })?.files_sharing !== undefined
@ -182,6 +198,8 @@ export default defineComponent({
AccountPlusIcon,
UploadPicker,
ViewGridIcon,
IconAlertCircleOutline,
IconReload,
},
mixins: [
@ -227,6 +245,7 @@ export default defineComponent({
data() {
return {
loading: true,
error: null as string | null,
promise: null as CancelablePromise<ContentsWithRoot> | Promise<ContentsWithRoot> | null,
dirContentsFiltered: [] as INode[],
@ -482,6 +501,7 @@ export default defineComponent({
methods: {
async fetchContent() {
this.loading = true
this.error = null
const dir = this.directory
const currentView = this.currentView
@ -530,6 +550,7 @@ export default defineComponent({
})
} catch (error) {
logger.error('Error while fetching content', { error })
this.error = humanizeWebDAVError(error)
} finally {
this.loading = false
}

2
dist/3235-3235.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1 +0,0 @@
3235-3235.js.license

2
dist/9918-9918.js vendored Normal file

File diff suppressed because one or more lines are too long

1
dist/9918-9918.js.map vendored Normal file

File diff suppressed because one or more lines are too long

1
dist/9918-9918.js.map.license vendored Symbolic link
View file

@ -0,0 +1 @@
9918-9918.js.license

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

4
dist/core-common.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

4
dist/files-init.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

4
dist/files-main.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long