Handle case with empty version list

Signed-off-by: Carl Schwan <carl@carlschwan.eu>
Signed-off-by: Louis Chemineau <louis@chmn.me>
This commit is contained in:
Carl Schwan 2022-10-25 14:19:53 +02:00 committed by Louis Chemineau
parent 2c50153618
commit 7888aaf34f
1 changed files with 90 additions and 63 deletions

View File

@ -17,58 +17,78 @@
-->
<template>
<div>
<ul>
<li v-for="version in versions" class="version">
<NcListItem v-for="version in versions"
class="version"
key="version.url"
:title="version.title"
:href="version.url">
<template #icon>
<img lazy="true"
:src="version.preview"
alt=""
height="256"
width="256"
class="version-image">
</template>
<template #subtitle>
<div class="version-info">
<a v-tooltip="version.dateTime" :href="version.url">{{ version.relativeTime }}</a>
<div class="version-info-size">
<span class="version-info-size"></span>
<span class="version-info-size">
{{ version.size }}
</div>
</span>
</div>
<NcButton v-tooltip="t('files_versions', `Download file ${fileInfo.name} with version ${version.displayVersionName}`)"
type="secondary"
class="download-button"
:href="version.url"
:aria-label="t('files_versions', `Download file ${fileInfo.name} with version ${version.displayVersionName}`)">
</template>
<template #actions>
<NcActionLink :href="version.url">
<template #icon>
<Download :size="22" />
</template>
</NcButton>
<NcButton v-tooltip="t('files_versions', `Restore file ${fileInfo.name} with version ${version.displayVersionName}`)"
type="secondary"
class="restore-button"
:aria-label="t('files_versions', `Restore file ${fileInfo.name} with version ${version.displayVersionName}`)"
@click="restoreVersion(version)">
{{ t('files_versions', `Download file ${fileInfo.name} with version ${version.displayVersionName}`) }}
</NcActionLink>
<NcActionButton @click="restoreVersion(version)" v-if="!version.isCurrent">
<template #icon>
<BackupRestore :size="22" />
</template>
</NcButton>
</li>
</ul>
{{ t('files_versions', `Restore file ${fileInfo.name} with version ${version.displayVersionName}`) }}
</NcActionButton>
</template>
</NcListItem>
<NcEmptyContent v-if="!loading && versions.length === 1"
:title="t('files_version', 'No versions yet')">
<!-- length === 1, since we don't want to show versions if there is only the current file -->
<template #icon>
<BackupRestore />
</template>
</NcEmptyContent>
</div>
</template>
<script>
import { createClient, getPatcher } from 'webdav'
import axios from '@nextcloud/axios'
import parseUrl from 'url-parse'
import { generateRemoteUrl, generateUrl } from '@nextcloud/router'
import { getCurrentUser } from '@nextcloud/auth'
import { translate } from '@nextcloud/l10n'
import BackupRestore from 'vue-material-design-icons/BackupRestore.vue'
import Download from 'vue-material-design-icons/Download.vue'
import NcButton from '@nextcloud/vue/dist/Components/NcButton.js'
import NcActionButton from '@nextcloud/vue/dist/Components/NcActionButton.js'
import NcActionLink from '@nextcloud/vue/dist/Components/NcActionLink.js'
import NcListItem from '@nextcloud/vue/dist/Components/NcListItem.js'
import NcEmptyContent from '@nextcloud/vue/dist/Components/NcEmptyContent.js'
import { showError, showSuccess } from '@nextcloud/dialogs'
import moment from '@nextcloud/moment'
import { basename, joinPaths } from '@nextcloud/paths'
import { getLoggerBuilder } from '@nextcloud/logger'
import { translate } from '@nextcloud/l10n'
const logger = getLoggerBuilder()
.setApp('files_version')
.detectUser()
.build()
/**
*
* Get WebDAV request body for version list
*/
function getDavRequest() {
return `<?xml version="1.0"?>
@ -85,55 +105,64 @@ function getDavRequest() {
}
/**
*
* @param version
* @param fileInfo
* Format version
*/
function formatVersion(version, fileInfo) {
const fileVersion = basename(version.filename)
const isCurrent = version.mime === ''
const preview = generateUrl('/apps/files_versions/preview?file={file}&version={fileVersion}', {
file: joinPaths(fileInfo.path, fileInfo.name),
fileVersion,
})
const preview = isCurrent
? generateUrl('/core/preview?fileId={fileId}&c={fileEtag}&x=250&y=250&forceIcon=0&a=0', {
fileId: fileInfo.id,
fileEtag: fileInfo.etag,
}) : generateUrl('/apps/files_versions/preview?file={file}&version={fileVersion}', {
file: joinPaths(fileInfo.path, fileInfo.name),
fileVersion,
})
return {
displayVersionName: fileVersion,
title: isCurrent ? translate('files_versions', 'Current version') : '',
fileName: version.filename,
mimeType: version.mime,
size: OC.Util.humanFileSize(version.size),
size: OC.Util.humanFileSize(isCurrent ? fileInfo.size : version.size),
type: version.type,
dateTime: moment(version.lastmod),
relativeTime: moment(version.lastmod).fromNow(),
dateTime: moment(isCurrent ? fileInfo.mtime : version.lastmod),
relativeTime: moment(isCurrent ? fileInfo.mtime : version.lastmod).fromNow(),
preview,
url: joinPaths('/remote.php/dav', version.filename),
url: isCurrent ? joinPaths('/remote.php/dav', version.filename) : joinPaths('/remote.php/dav', fileInfo.path, fileInfo.name),
fileVersion,
isCurrent,
}
}
const rootPath = 'dav'
// force our axios
const patcher = getPatcher()
patcher.patch('request', axios)
// init webdav client on default dav endpoint
const remote = generateRemoteUrl(rootPath)
const client = createClient(remote)
export default {
name: 'VersionTab',
components: {
NcButton,
NcEmptyContent,
NcActionLink,
NcActionButton,
NcListItem,
BackupRestore,
Download,
},
data() {
const rootPath = 'dav'
// force our axios
const patcher = getPatcher()
patcher.patch('request', axios)
// init webdav client on default dav endpoint
const remote = generateRemoteUrl(rootPath)
const client = createClient(remote)
return {
fileInfo: null,
versions: [],
client,
remote,
loading: true,
}
},
methods: {
@ -153,13 +182,17 @@ export default {
*/
async fetchVersions() {
const path = `/versions/${getCurrentUser().uid}/versions/${this.fileInfo.id}`
const remotePath = parseUrl(this.remote).pathname
const response = await this.client.getDirectoryContents(path, {
data: getDavRequest(),
})
this.versions = response.filter(version => version.mime !== '')
.map(version => formatVersion(version, this.fileInfo))
try {
const response = await client.getDirectoryContents(path, {
data: getDavRequest(),
})
this.versions = response.map(version => formatVersion(version, this.fileInfo))
this.loading = false
} catch (exception) {
logger.error('Could not fetch version', {exception})
this.loading = false
}
},
/**
@ -169,15 +202,15 @@ export default {
*/
async restoreVersion(version) {
try {
console.debug('restore version', version.url)
const response = await this.client.moveFile(
logger.debug('restoring version', version.url)
const response = await client.moveFile(
`/versions/${getCurrentUser().uid}/versions/${this.fileInfo.id}/${version.fileVersion}`,
`/versions/${getCurrentUser().uid}/restore/target`
)
showSuccess(t('files_versions', 'Version restored'))
await this.fetchVersions()
} catch (exception) {
console.error('Could not restore version', exception)
logger.error('Could not restore version', {exception})
showError(t('files_versions', 'Could not restore version'))
}
},
@ -198,7 +231,9 @@ export default {
flex-direction: row;
&-info {
display: flex;
flex-direction: column;
flex-direction: row;
align-items: center;
gap: 0.5rem;
&-size {
color: var(--color-text-lighter);
}
@ -206,17 +241,9 @@ export default {
&-image {
width: 3rem;
height: 3rem;
filter: drop-shadow(0 1px 2px var(--color-box-shadow));
border: 1px solid var(--color-border);
margin-right: 1rem;
border-radius: var(--border-radius);
}
.restore-button {
margin-left: 1rem;
align-self: center;
}
.download-button {
margin-left: auto;
align-self: center;
border-radius: var(--border-radius-large);
}
}
</style>