aboutsummaryrefslogtreecommitdiffstats
path: root/apps/files_versions/src/components/Version.vue
diff options
context:
space:
mode:
Diffstat (limited to 'apps/files_versions/src/components/Version.vue')
-rw-r--r--apps/files_versions/src/components/Version.vue147
1 files changed, 90 insertions, 57 deletions
diff --git a/apps/files_versions/src/components/Version.vue b/apps/files_versions/src/components/Version.vue
index 144aae33922..dc36e4134f9 100644
--- a/apps/files_versions/src/components/Version.vue
+++ b/apps/files_versions/src/components/Version.vue
@@ -5,12 +5,13 @@
<template>
<NcListItem class="version"
:force-display-actions="true"
+ :actions-aria-label="t('files_versions', 'Actions for version from {versionHumanExplicitDate}', { versionHumanExplicitDate })"
:data-files-versions-version="version.fileVersion"
@click="click">
<!-- Icon -->
<template #icon>
<div v-if="!(loadPreview || previewLoaded)" class="version__image" />
- <img v-else-if="(isCurrent || version.hasPreview) && !previewErrored"
+ <img v-else-if="version.previewUrl && !previewErrored"
:src="version.previewUrl"
alt=""
decoding="async"
@@ -28,16 +29,26 @@
<!-- author -->
<template #name>
<div class="version__info">
- <div v-if="versionLabel" class="version__info__label">{{ versionLabel }}</div>
- <div v-if="versionAuthor" class="version__info">
- <div v-if="versionLabel">•</div>
+ <div v-if="versionLabel"
+ class="version__info__label"
+ data-cy-files-version-label
+ :title="versionLabel">
+ {{ versionLabel }}
+ </div>
+ <div v-if="versionAuthor"
+ class="version__info"
+ data-cy-files-version-author-name>
+ <span v-if="versionLabel">•</span>
<NcAvatar class="avatar"
:user="version.author"
- :size="16"
- :disable-menu="true"
- :disable-tooltip="true"
+ :size="20"
+ disable-menu
+ disable-tooltip
:show-user-status="false" />
- <div>{{ versionAuthor }}</div>
+ <div class="version__info__author_name"
+ :title="versionAuthor">
+ {{ versionAuthor }}
+ </div>
</div>
</div>
</template>
@@ -45,10 +56,12 @@
<!-- Version file size as subline -->
<template #subname>
<div class="version__info version__info__subline">
- <span :title="formattedDate">{{ version.mtime | humanDateFromNow }}</span>
- <!-- Separate dot to improve alignement -->
+ <NcDateTime class="version__info__date"
+ relative-time="short"
+ :timestamp="version.mtime" />
+ <!-- Separate dot to improve alignment -->
<span>•</span>
- <span>{{ version.size | humanReadableSize }}</span>
+ <span>{{ humanReadableSize }}</span>
</div>
</template>
@@ -103,31 +116,35 @@
</template>
</NcListItem>
</template>
-
<script lang="ts">
+import type { PropType } from 'vue'
import type { Version } from '../utils/versions'
+import { getCurrentUser } from '@nextcloud/auth'
+import { Permission, formatFileSize } from '@nextcloud/files'
+import { loadState } from '@nextcloud/initial-state'
+import { t } from '@nextcloud/l10n'
+import { joinPaths } from '@nextcloud/paths'
+import { getRootUrl, generateUrl } from '@nextcloud/router'
+import { defineComponent } from 'vue'
+
+import axios from '@nextcloud/axios'
+import moment from '@nextcloud/moment'
+import logger from '../utils/logger'
+
import BackupRestore from 'vue-material-design-icons/BackupRestore.vue'
import Delete from 'vue-material-design-icons/Delete.vue'
import Download from 'vue-material-design-icons/Download.vue'
import FileCompare from 'vue-material-design-icons/FileCompare.vue'
import ImageOffOutline from 'vue-material-design-icons/ImageOffOutline.vue'
-import Pencil from 'vue-material-design-icons/Pencil.vue'
+import Pencil from 'vue-material-design-icons/PencilOutline.vue'
-import NcActionButton from '@nextcloud/vue/dist/Components/NcActionButton.js'
-import NcActionLink from '@nextcloud/vue/dist/Components/NcActionLink.js'
-import NcAvatar from '@nextcloud/vue/dist/Components/NcAvatar.js'
-import NcListItem from '@nextcloud/vue/dist/Components/NcListItem.js'
-import Tooltip from '@nextcloud/vue/dist/Directives/Tooltip.js'
-
-import { defineComponent, type PropType } from 'vue'
-import axios from '@nextcloud/axios'
-import { getRootUrl, generateOcsUrl } from '@nextcloud/router'
-import { joinPaths } from '@nextcloud/paths'
-import { loadState } from '@nextcloud/initial-state'
-import { Permission, formatFileSize } from '@nextcloud/files'
-import { translate as t } from '@nextcloud/l10n'
-import moment from '@nextcloud/moment'
+import NcActionButton from '@nextcloud/vue/components/NcActionButton'
+import NcActionLink from '@nextcloud/vue/components/NcActionLink'
+import NcAvatar from '@nextcloud/vue/components/NcAvatar'
+import NcDateTime from '@nextcloud/vue/components/NcDateTime'
+import NcListItem from '@nextcloud/vue/components/NcListItem'
+import Tooltip from '@nextcloud/vue/directives/Tooltip'
const hasPermission = (permissions: number, permission: number): boolean => (permissions & permission) !== 0
@@ -138,6 +155,7 @@ export default defineComponent({
NcActionLink,
NcActionButton,
NcAvatar,
+ NcDateTime,
NcListItem,
BackupRestore,
Download,
@@ -151,20 +169,6 @@ export default defineComponent({
tooltip: Tooltip,
},
- created() {
- this.fetchDisplayName()
- },
-
- filters: {
- humanReadableSize(bytes: number): string {
- return formatFileSize(bytes)
- },
-
- humanDateFromNow(timestamp: number): string {
- return moment(timestamp).fromNow()
- },
- },
-
props: {
version: {
type: Object as PropType<Version>,
@@ -203,11 +207,15 @@ export default defineComponent({
previewLoaded: false,
previewErrored: false,
capabilities: loadState('core', 'capabilities', { files: { version_labeling: false, version_deletion: false } }),
- versionAuthor: '',
+ versionAuthor: '' as string | null,
}
},
computed: {
+ humanReadableSize() {
+ return formatFileSize(this.version.size)
+ },
+
versionLabel(): string {
const label = this.version.label ?? ''
@@ -226,6 +234,10 @@ export default defineComponent({
return label
},
+ versionHumanExplicitDate(): string {
+ return moment(this.version.mtime).format('LLLL')
+ },
+
downloadURL(): string {
if (this.isCurrent) {
return getRootUrl() + joinPaths('/remote.php/webdav', this.fileInfo.path, this.fileInfo.name)
@@ -234,10 +246,6 @@ export default defineComponent({
}
},
- formattedDate(): string {
- return moment(this.version.mtime).format('LLL')
- },
-
enableLabeling(): boolean {
return this.capabilities.files.version_labeling === true
},
@@ -264,7 +272,7 @@ export default defineComponent({
const downloadAttribute = this.fileInfo.shareAttributes
.find((attribute) => attribute.scope === 'permissions' && attribute.key === 'download') || {}
// If the download attribute is set to false, the file is not downloadable
- if (downloadAttribute?.enabled === false) {
+ if (downloadAttribute?.value === false) {
return false
}
}
@@ -273,6 +281,10 @@ export default defineComponent({
},
},
+ created() {
+ this.fetchDisplayName()
+ },
+
methods: {
labelUpdate() {
this.$emit('label-update-request')
@@ -291,21 +303,26 @@ export default defineComponent({
},
async fetchDisplayName() {
- // check to make sure that we have a valid author - in case database did not migrate, null author, etc.
- if (this.version.author) {
+ this.versionAuthor = null
+ if (!this.version.author) {
+ return
+ }
+
+ if (this.version.author === getCurrentUser()?.uid) {
+ this.versionAuthor = t('files_versions', 'You')
+ } else {
try {
- const { data } = await axios.get(generateOcsUrl(`/cloud/users/${this.version.author}`))
- this.versionAuthor = data.ocs.data.displayname
- } catch (e) {
- // Promise got rejected - default to null author to not try to load author profile
- this.versionAuthor = null
+ const { data } = await axios.post(generateUrl('/displaynames'), { users: [this.version.author] })
+ this.versionAuthor = data.users[this.version.author]
+ } catch (error) {
+ logger.warn('Could not load user display name', { error })
}
}
},
click() {
if (!this.canView) {
- window.location = this.downloadURL
+ window.location.href = this.downloadURL
return
}
this.$emit('click', { version: this.version })
@@ -335,14 +352,30 @@ export default defineComponent({
gap: 0.5rem;
color: var(--color-main-text);
font-weight: 500;
+ overflow: hidden;
&__label {
font-weight: 700;
+ // Fix overflow on narrow screens
+ overflow: hidden;
+ text-overflow: ellipsis;
+ min-width: 110px;
+ }
+
+ &__author_name {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+
+ &__date {
+ // Fix overflow on narrow screens
+ overflow: hidden;
+ text-overflow: ellipsis;
}
&__subline {
- color: var(--color-text-maxcontrast)
- }
+ color: var(--color-text-maxcontrast)
+ }
}
&__image {