Version Entry update and Version Download
This commit is contained in:
parent
aeddbb6869
commit
758a3484ea
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,5 +1,5 @@
|
||||||
<!--
|
<!--
|
||||||
- @copyright Copyright (c) 2021 Enoch <enoch@nextcloud.com>
|
- @copyright Copyright (c) 2021 Enoch <enoch@nextcloud.com>
|
||||||
-
|
-
|
||||||
- @author Enoch <enoch@nextcloud.com>
|
- @author Enoch <enoch@nextcloud.com>
|
||||||
-
|
-
|
||||||
|
@ -19,35 +19,49 @@
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<ul>
|
<li>
|
||||||
|
|
||||||
<ListItemIcon
|
<ListItemIcon
|
||||||
:title="version.lastmod"
|
v-if="!isLatestChange"
|
||||||
:subtitle="version.size">
|
:title="relativeDate"
|
||||||
<Actions
|
:subtitle="formattedSize"
|
||||||
menu-align="right"
|
:url="iconUrl"
|
||||||
class="version-entry__actions">
|
class="version-entry">
|
||||||
<ActionButton icon="icon-history" @click="alert('Edit')">
|
<Actions class="version-entry__actions">
|
||||||
|
<ActionButton v-if="canRevert" icon="icon-history" @click="restoreVersion">
|
||||||
{{ t('files_versions','Restore') }}
|
{{ t('files_versions','Restore') }}
|
||||||
</ActionButton>
|
</ActionButton>
|
||||||
|
<ActionLink icon="icon-download" :href="versionUrl">
|
||||||
|
{{ t('files_versions','Download') }}
|
||||||
|
</ActionLink>
|
||||||
</Actions>
|
</Actions>
|
||||||
</ListItemIcon>
|
</ListItemIcon>
|
||||||
</ul>
|
</div>
|
||||||
|
</li>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Avatar from '@nextcloud/vue/dist/Components/Avatar'
|
import moment from '@nextcloud/moment'
|
||||||
import Actions from '@nextcloud/vue/dist/Components/Actions'
|
import Actions from '@nextcloud/vue/dist/Components/Actions'
|
||||||
|
import ActionButton from '@nextcloud/vue/dist/Components/ActionButton'
|
||||||
|
import ActionLink from '@nextcloud/vue/dist/Components/ActionLink'
|
||||||
import Tooltip from '@nextcloud/vue/dist/Directives/Tooltip'
|
import Tooltip from '@nextcloud/vue/dist/Directives/Tooltip'
|
||||||
import ListItemIcon from '@nextcloud/vue/dist/Components/ListItemIcon'
|
import ListItemIcon from '@nextcloud/vue/dist/Components/ListItemIcon'
|
||||||
import moment from '@nextcloud/moment'
|
|
||||||
|
import { generateUrl } from '@nextcloud/router'
|
||||||
|
import { getCurrentUser } from '@nextcloud/auth'
|
||||||
|
import client from "../services/DavClient";
|
||||||
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'VersionEntry',
|
name: 'VersionEntry',
|
||||||
|
|
||||||
components: {
|
components: {
|
||||||
Actions,
|
Actions,
|
||||||
|
ActionButton,
|
||||||
|
ActionLink,
|
||||||
ListItemIcon,
|
ListItemIcon,
|
||||||
Avatar,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
directives: {
|
directives: {
|
||||||
|
@ -63,27 +77,48 @@ export default {
|
||||||
type: Object,
|
type: Object,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
|
tooltip: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
iconUrl,
|
|
||||||
version: {},
|
|
||||||
moment,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
computed: {
|
||||||
|
// Does the current user have permissions to revert this file
|
||||||
|
canRevert () {
|
||||||
|
// TODO: implement permission check
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* If the basename is just the file id,
|
||||||
|
* this is the latest file version entry
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
isLatestChange() {
|
||||||
|
return this.fileInfo.id === this.version.basename
|
||||||
|
},
|
||||||
|
versionUrl() {
|
||||||
|
return generateUrl('/remote.php/dav/versions/{user}' + this.version.filename, {
|
||||||
|
user: getCurrentUser().uid,
|
||||||
|
})
|
||||||
|
},
|
||||||
iconUrl() {
|
iconUrl() {
|
||||||
return OC.MimeType.getIconUrl(this.MimeType)
|
return OC.MimeType.getIconUrl(this.fileInfo.mimetype)
|
||||||
console.log(iconUrl)
|
},
|
||||||
|
formattedSize() {
|
||||||
|
return OC.Util.humanFileSize(this.version.size, true)
|
||||||
},
|
},
|
||||||
relativeDate() {
|
relativeDate() {
|
||||||
return (timestamp) => {
|
return moment(this.version.lastmod).fromNow()
|
||||||
const diff = moment(this.$root.time).diff(moment(timestamp))
|
},
|
||||||
if (diff >= 0 && diff < 45000) {
|
},
|
||||||
return t('core', 'seconds ago')
|
methods: {
|
||||||
}
|
// Restores the original file to this revision
|
||||||
return moment(timestamp).fromNow()
|
restoreVersion () {
|
||||||
}
|
// TODO: implement restore request and loading
|
||||||
|
return client.move('/remote.php/dav/versions/{user}' + this.version.basename, {
|
||||||
|
user: getCurrentUser().uid,
|
||||||
|
},'/restore/target', true)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -94,25 +129,27 @@ export default {
|
||||||
.version-entry {
|
.version-entry {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
min-height: 44px;
|
height: 44px;
|
||||||
&__desc {
|
&__desc {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
line-height: 1.2em;
|
line-height: 1.6em;
|
||||||
position: relative;
|
|
||||||
flex: 1 1;
|
|
||||||
min-width: 0;
|
|
||||||
h5 {
|
|
||||||
white-space: nowrap;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
overflow: hidden;
|
|
||||||
max-width: inherit;
|
|
||||||
}
|
|
||||||
p {
|
p {
|
||||||
color: var(--color-text-maxcontrast);
|
color: var(--color-text-maxcontrast);
|
||||||
}
|
}
|
||||||
|
&-unique {
|
||||||
|
color: var(--color-text-maxcontrast);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
&__actions {
|
&__actions {
|
||||||
margin-left: auto !important;
|
margin-left: auto;
|
||||||
}
|
}
|
||||||
|
// Remove avatar border-radius around file type icon
|
||||||
|
::v-deep .avatardiv img {
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -40,6 +40,7 @@ window.addEventListener('DOMContentLoaded', function() {
|
||||||
id: 'version_new',
|
id: 'version_new',
|
||||||
name: t('files_versions', 'VueVersions'),
|
name: t('files_versions', 'VueVersions'),
|
||||||
icon: 'icon-version',
|
icon: 'icon-version',
|
||||||
|
|
||||||
async mount(el, fileInfo, context) {
|
async mount(el, fileInfo, context) {
|
||||||
if (TabInstance) {
|
if (TabInstance) {
|
||||||
TabInstance.$destroy()
|
TabInstance.$destroy()
|
||||||
|
|
|
@ -22,32 +22,23 @@
|
||||||
import client from './DavClient'
|
import client from './DavClient'
|
||||||
import { genFileInfo } from '../utils/fileUtils'
|
import { genFileInfo } from '../utils/fileUtils'
|
||||||
|
|
||||||
const FileVersion = async function(fileId) {
|
export const fetchFileVersions = async function(fileId) {
|
||||||
|
|
||||||
// init params
|
// init params
|
||||||
const VersionsUrl = '/versions/' + fileId
|
const VersionsUrl = '/versions/' + fileId
|
||||||
const response = await client.getDirectoryContents(VersionsUrl, {
|
const response = await client.getDirectoryContents(VersionsUrl, {
|
||||||
data: `<?xml version="1.0"?>
|
data: `<?xml version="1.0"?>
|
||||||
<d:propfind xmlns:d="DAV:" xmlns:oc="http://owncloud.org/ns">
|
<d:propfind xmlns:d="DAV:" xmlns:oc="http://owncloud.org/ns">
|
||||||
<d:prop>
|
<d:prop>
|
||||||
<d:getcontentlength />
|
<d:getcontentlength />
|
||||||
<d:getcontenttype />
|
<d:getcontenttype />
|
||||||
<d:getlastmodified />
|
<d:getlastmodified />
|
||||||
</d:prop>
|
</d:prop>
|
||||||
</d:propfind>`,
|
</d:propfind>`,
|
||||||
details: true,
|
details: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
/** return response.data.map(FileVersion); */
|
/** return response.data.map(FileVersion); */
|
||||||
|
|
||||||
return response.data.map(genFileInfo)
|
return response.data.map(genFileInfo)
|
||||||
|
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* Retrieve the files list
|
|
||||||
*
|
|
||||||
* @param {String} path the path relative to the user root
|
|
||||||
* @param {Object} [options] optional options for axios
|
|
||||||
* @returns {Array} the file list
|
|
||||||
*/
|
|
||||||
export default FileVersion
|
|
||||||
|
|
|
@ -23,75 +23,77 @@
|
||||||
<template>
|
<template>
|
||||||
<div :class="{ 'icon-loading': loading }">
|
<div :class="{ 'icon-loading': loading }">
|
||||||
<!-- error message -->
|
<!-- error message -->
|
||||||
<div v-if="error" class="emptycontent">
|
<EmptyContent v-if="error" icon="icon-error">
|
||||||
<div class="icon icon-error" />
|
{{ t('files_versions', 'Cannot load versions list')}}
|
||||||
<h2>{{ error }}</h2>
|
<template #desc>
|
||||||
</div>
|
{{error}}
|
||||||
|
</template>
|
||||||
|
</EmptyContent>
|
||||||
<ul>
|
<ul>
|
||||||
<!-- Version information -->
|
<!-- Version information -->
|
||||||
<VersionEntry v-for="version in versionsList" :file-info="_fileInfo" :version="version" />
|
<VersionEntry v-for="version in versionsList"
|
||||||
|
:key="version.basename"
|
||||||
|
:file-info="fileInfo"
|
||||||
|
:version="version" />
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import EmptyContent from '@nextcloud/vue/dist/Components/EmptyContent'
|
||||||
|
import { showError } from '@nextcloud/dialogs'
|
||||||
|
|
||||||
import VersionEntry from '../components/VersionEntry'
|
import VersionEntry from '../components/VersionEntry'
|
||||||
import fetchFileVersions from '../services/FileVersion'
|
import { fetchFileVersions } from '../services/FileVersion'
|
||||||
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'VersionTab',
|
name: 'VersionTab',
|
||||||
|
|
||||||
components: {
|
components: {
|
||||||
VersionEntry,
|
VersionEntry,
|
||||||
|
EmptyContent,
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
error: '',
|
error: '',
|
||||||
loading: true,
|
loading: true,
|
||||||
client: null,
|
fileInfo: null,
|
||||||
_fileInfo: null,
|
|
||||||
|
|
||||||
// version object
|
// version object
|
||||||
versionsList: [],
|
versionsList: [],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
beforeMount(){
|
||||||
this.getVersions()
|
this.getVersions()
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
setFileInfo(fileInfo) {
|
|
||||||
this._fileInfo = fileInfo
|
|
||||||
},
|
|
||||||
getFileInfo() {
|
|
||||||
return this._fileInfo
|
|
||||||
},
|
|
||||||
setClient(client) {
|
|
||||||
this._client = client
|
|
||||||
},
|
|
||||||
/**
|
/**
|
||||||
* Update current fileInfo and fetch new data
|
* Update current fileInfo and fetch new data
|
||||||
* @param {Object} fileInfo the current file FileInfo
|
* @param {Object} fileInfo the current file FileInfo
|
||||||
*/
|
*/
|
||||||
async update(fileInfo) {
|
async update(fileInfo) {
|
||||||
this._fileInfo = fileInfo
|
this.fileInfo = fileInfo
|
||||||
/** name = this._fileInfo.get('name') */
|
|
||||||
},
|
},
|
||||||
|
|
||||||
async getVersions() {
|
async getVersions() {
|
||||||
|
this.loading = true
|
||||||
try {
|
try {
|
||||||
this.loading = true
|
const fetchVersions = await fetchFileVersions(this.fileInfo.id)
|
||||||
const fetchVersions = await fetchFileVersions(this._fileInfo.get('id'))
|
|
||||||
this.versionsList = fetchVersions
|
this.versionsList = fetchVersions
|
||||||
console.log(fetchVersions)
|
console.debug(fetchVersions)
|
||||||
} catch (e) {
|
} catch (error) {
|
||||||
console.log(error)
|
this.error = t('files_versions', 'There was an error fetching the list of versions for the file {file}', {
|
||||||
|
file: this.fileInfo.basename,
|
||||||
|
})
|
||||||
|
showError(this.error)
|
||||||
|
console.error(error)
|
||||||
|
} finally {
|
||||||
|
this.loading = false
|
||||||
}
|
}
|
||||||
this.loading = false
|
|
||||||
},
|
},
|
||||||
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
Loading…
Reference in New Issue