-->
<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"?>
}
/**
- *
- * @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: {
*/
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
+ }
},
/**
*/
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'))
}
},
flex-direction: row;
&-info {
display: flex;
- flex-direction: column;
+ flex-direction: row;
+ align-items: center;
+ gap: 0.5rem;
&-size {
color: var(--color-text-lighter);
}
&-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>