123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222 |
- <!--
- - @copyright 2022 Carl Schwan <carl@carlschwan.eu>
- - @license AGPL-3.0-or-later
- -
- - This program is free software: you can redistribute it and/or modify
- - it under the terms of the GNU Affero General Public License as
- - published by the Free Software Foundation, either version 3 of the
- - License, or (at your option) any later version.
- -
- - This program is distributed in the hope that it will be useful,
- - but WITHOUT ANY WARRANTY; without even the implied warranty of
- - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- - GNU Affero General Public License for more details.
- -
- - You should have received a copy of the GNU Affero General Public License
- - along with this program. If not, see <http://www.gnu.org/licenses/>.
- -->
- <template>
- <div>
- <ul>
- <li v-for="version in versions" class="version">
- <img lazy="true"
- :src="version.preview"
- height="256"
- width="256"
- class="version-image">
- <div class="version-info">
- <a v-tooltip="version.dateTime" :href="version.url">{{ version.relativeTime }}</a>
- <div class="version-info-size">
- {{ version.size }}
- </div>
- </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 #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)">
- <template #icon>
- <BackupRestore :size="22" />
- </template>
- </NcButton>
- </li>
- </ul>
- </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 { showError, showSuccess } from '@nextcloud/dialogs'
- import moment from '@nextcloud/moment'
- import { basename, joinPaths } from '@nextcloud/paths'
- /**
- *
- */
- function getDavRequest() {
- return `<?xml version="1.0"?>
- <d:propfind xmlns:d="DAV:"
- xmlns:oc="http://owncloud.org/ns"
- xmlns:nc="http://nextcloud.org/ns"
- xmlns:ocs="http://open-collaboration-services.org/ns">
- <d:prop>
- <d:getcontentlength />
- <d:getcontenttype />
- <d:getlastmodified />
- </d:prop>
- </d:propfind>`
- }
- /**
- *
- * @param version
- * @param fileInfo
- */
- function formatVersion(version, fileInfo) {
- const fileVersion = basename(version.filename)
- const preview = generateUrl('/apps/files_versions/preview?file={file}&version={fileVersion}', {
- file: joinPaths(fileInfo.path, fileInfo.name),
- fileVersion,
- })
- return {
- displayVersionName: fileVersion,
- fileName: version.filename,
- mimeType: version.mime,
- size: OC.Util.humanFileSize(version.size),
- type: version.type,
- dateTime: moment(version.lastmod),
- relativeTime: moment(version.lastmod).fromNow(),
- preview,
- url: joinPaths('/remote.php/dav', version.filename),
- fileVersion,
- }
- }
- export default {
- name: 'VersionTab',
- components: {
- NcButton,
- 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,
- }
- },
- methods: {
- /**
- * Update current fileInfo and fetch new data
- *
- * @param {object} fileInfo the current file FileInfo
- */
- async update(fileInfo) {
- this.fileInfo = fileInfo
- this.resetState()
- this.fetchVersions()
- },
- /**
- * Get the existing versions infos
- */
- 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))
- },
- /**
- * Restore the given version
- *
- * @param version
- */
- async restoreVersion(version) {
- try {
- console.debug('restore version', version.url)
- const response = await this.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)
- showError(t('files_versions', 'Could not restore version'))
- }
- },
- /**
- * Reset the current view to its default state
- */
- resetState() {
- this.versions = []
- },
- },
- }
- </script>
- <style scopped lang="scss">
- .version {
- display: flex;
- flex-direction: row;
- &-info {
- display: flex;
- flex-direction: column;
- &-size {
- color: var(--color-text-lighter);
- }
- }
- &-image {
- width: 3rem;
- height: 3rem;
- filter: drop-shadow(0 1px 2px var(--color-box-shadow));
- margin-right: 1rem;
- border-radius: var(--border-radius);
- }
- .restore-button {
- margin-left: 1rem;
- align-self: center;
- }
- .download-button {
- margin-left: auto;
- align-self: center;
- }
- }
- </style>
|