Skip to content

Commit a81bcd1

Browse files
committed
refactor(files_versions): Migrate to Vue3
Signed-off-by: Louis Chmn <[email protected]>
1 parent d2a42c6 commit a81bcd1

18 files changed

+642
-643
lines changed

apps/files_versions/lib/Listener/LoadAdditionalListener.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ public function handle(Event $event): void {
2323

2424
// TODO: make sure to only include the sidebar script when
2525
// we properly split it between files list and sidebar
26-
Util::addScript(Application::APP_ID, 'files_versions');
26+
Util::addStyle(Application::APP_ID, 'sidebar-tab');
27+
Util::addScript(Application::APP_ID, 'sidebar-tab');
2728
}
2829
}

apps/files_versions/lib/Listener/LoadSidebarListener.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ public function handle(Event $event): void {
2323

2424
// TODO: make sure to only include the sidebar script when
2525
// we properly split it between files list and sidebar
26-
Util::addScript(Application::APP_ID, 'files_versions');
26+
Util::addStyle(Application::APP_ID, 'sidebar-tab');
27+
Util::addScript(Application::APP_ID, 'sidebar-tab');
2728
}
2829
}

apps/files_versions/src/components/VersionEntry.vue

Lines changed: 161 additions & 178 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
<span v-if="versionLabel">•</span>
4747
<NcAvatar
4848
class="avatar"
49-
:user="version.author"
49+
:user="version.author ?? undefined"
5050
:size="20"
5151
disable-menu
5252
disable-tooltip
@@ -130,8 +130,9 @@
130130
</NcListItem>
131131
</template>
132132

133-
<script lang="ts">
133+
<script lang="ts" setup>
134134
import type { PropType } from 'vue'
135+
import type { LegacyFileInfo } from '../../../files/src/services/FileInfo.ts'
135136
import type { Version } from '../utils/versions.ts'
136137
137138
import { getCurrentUser } from '@nextcloud/auth'
@@ -141,8 +142,7 @@ import { t } from '@nextcloud/l10n'
141142
import moment from '@nextcloud/moment'
142143
import { joinPaths } from '@nextcloud/paths'
143144
import { getRootUrl } from '@nextcloud/router'
144-
import Tooltip from '@nextcloud/vue/directives/Tooltip'
145-
import { defineComponent } from 'vue'
145+
import { computed, nextTick, ref } from 'vue'
146146
import NcActionButton from '@nextcloud/vue/components/NcActionButton'
147147
import NcActionLink from '@nextcloud/vue/components/NcActionLink'
148148
import NcAvatar from '@nextcloud/vue/components/NcAvatar'
@@ -155,193 +155,176 @@ import Pencil from 'vue-material-design-icons/PencilOutline.vue'
155155
import Delete from 'vue-material-design-icons/TrashCanOutline.vue'
156156
import Download from 'vue-material-design-icons/TrayArrowDown.vue'
157157
158-
const hasPermission = (permissions: number, permission: number): boolean => (permissions & permission) !== 0
159-
160-
export default defineComponent({
161-
name: 'VersionEntry',
162-
163-
components: {
164-
NcActionLink,
165-
NcActionButton,
166-
NcAvatar,
167-
NcDateTime,
168-
NcListItem,
169-
BackupRestore,
170-
Download,
171-
FileCompare,
172-
Pencil,
173-
Delete,
174-
ImageOffOutline,
158+
const props = defineProps({
159+
version: {
160+
type: Object as PropType<Version>,
161+
required: true,
175162
},
176163
177-
directives: {
178-
tooltip: Tooltip,
164+
fileInfo: {
165+
type: Object as PropType<LegacyFileInfo>,
166+
required: true,
179167
},
180168
181-
props: {
182-
version: {
183-
type: Object as PropType<Version>,
184-
required: true,
185-
},
186-
187-
fileInfo: {
188-
type: Object,
189-
required: true,
190-
},
191-
192-
isCurrent: {
193-
type: Boolean,
194-
default: false,
195-
},
196-
197-
isFirstVersion: {
198-
type: Boolean,
199-
default: false,
200-
},
201-
202-
loadPreview: {
203-
type: Boolean,
204-
default: false,
205-
},
206-
207-
canView: {
208-
type: Boolean,
209-
default: false,
210-
},
211-
212-
canCompare: {
213-
type: Boolean,
214-
default: false,
215-
},
169+
isCurrent: {
170+
type: Boolean,
171+
default: false,
216172
},
217173
218-
emits: ['click', 'compare', 'restore', 'delete', 'label-update-request'],
174+
isFirstVersion: {
175+
type: Boolean,
176+
default: false,
177+
},
219178
220-
data() {
221-
return {
222-
previewLoaded: false,
223-
previewErrored: false,
224-
capabilities: loadState('core', 'capabilities', { files: { version_labeling: false, version_deletion: false } }),
225-
}
179+
loadPreview: {
180+
type: Boolean,
181+
default: false,
226182
},
227183
228-
computed: {
229-
humanReadableSize() {
230-
return formatFileSize(this.version.size)
231-
},
232-
233-
versionLabel(): string {
234-
const label = this.version.label ?? ''
235-
236-
if (this.isCurrent) {
237-
if (label === '') {
238-
return t('files_versions', 'Current version')
239-
} else {
240-
return `${label} (${t('files_versions', 'Current version')})`
241-
}
242-
}
243-
244-
if (this.isFirstVersion && label === '') {
245-
return t('files_versions', 'Initial version')
246-
}
247-
248-
return label
249-
},
250-
251-
versionAuthor() {
252-
if (!this.version.author || !this.version.authorName) {
253-
return ''
254-
}
255-
256-
if (this.version.author === getCurrentUser()?.uid) {
257-
return t('files_versions', 'You')
258-
}
259-
260-
return this.version.authorName ?? this.version.author
261-
},
262-
263-
versionHumanExplicitDate(): string {
264-
return moment(this.version.mtime).format('LLLL')
265-
},
266-
267-
downloadURL(): string {
268-
if (this.isCurrent) {
269-
return getRootUrl() + joinPaths('/remote.php/webdav', this.fileInfo.path, this.fileInfo.name)
270-
} else {
271-
return getRootUrl() + this.version.url
272-
}
273-
},
274-
275-
enableLabeling(): boolean {
276-
return this.capabilities.files.version_labeling === true
277-
},
278-
279-
enableDeletion(): boolean {
280-
return this.capabilities.files.version_deletion === true
281-
},
282-
283-
hasDeletePermissions(): boolean {
284-
return hasPermission(this.fileInfo.permissions, Permission.DELETE)
285-
},
286-
287-
hasUpdatePermissions(): boolean {
288-
return hasPermission(this.fileInfo.permissions, Permission.UPDATE)
289-
},
290-
291-
isDownloadable(): boolean {
292-
if ((this.fileInfo.permissions & Permission.READ) === 0) {
293-
return false
294-
}
295-
296-
// If the mount type is a share, ensure it got download permissions.
297-
if (this.fileInfo.mountType === 'shared') {
298-
const downloadAttribute = this.fileInfo.shareAttributes
299-
.find((attribute) => attribute.scope === 'permissions' && attribute.key === 'download') || {}
300-
// If the download attribute is set to false, the file is not downloadable
301-
if (downloadAttribute?.value === false) {
302-
return false
303-
}
304-
}
305-
306-
return true
307-
},
184+
canView: {
185+
type: Boolean,
186+
default: false,
308187
},
309188
310-
methods: {
311-
labelUpdate() {
312-
this.$emit('label-update-request')
313-
},
314-
315-
restoreVersion() {
316-
this.$emit('restore', this.version)
317-
},
318-
319-
async deleteVersion() {
320-
// Let @nc-vue properly remove the popover before we delete the version.
321-
// This prevents @nc-vue from throwing a error.
322-
await this.$nextTick()
323-
await this.$nextTick()
324-
this.$emit('delete', this.version)
325-
},
326-
327-
click() {
328-
if (!this.canView) {
329-
window.location.href = this.downloadURL
330-
return
331-
}
332-
this.$emit('click', { version: this.version })
333-
},
334-
335-
compareVersion() {
336-
if (!this.canView) {
337-
throw new Error('Cannot compare version of this file')
338-
}
339-
this.$emit('compare', { version: this.version })
340-
},
341-
342-
t,
189+
canCompare: {
190+
type: Boolean,
191+
default: false,
343192
},
344193
})
194+
195+
const emit = defineEmits(['click', 'compare', 'restore', 'delete', 'label-update-request'])
196+
197+
const hasPermission = (permissions: number, permission: number): boolean => (permissions & permission) !== 0
198+
199+
const previewLoaded = ref(false)
200+
const previewErrored = ref(false)
201+
const capabilities = ref(loadState('core', 'capabilities', { files: { version_labeling: false, version_deletion: false } }))
202+
203+
const humanReadableSize = computed(() => {
204+
return formatFileSize(props.version.size)
205+
})
206+
207+
const versionLabel = computed(() => {
208+
const label = props.version.label ?? ''
209+
210+
if (props.isCurrent) {
211+
if (label === '') {
212+
return t('files_versions', 'Current version')
213+
} else {
214+
return `${label} (${t('files_versions', 'Current version')})`
215+
}
216+
}
217+
218+
if (props.isFirstVersion && label === '') {
219+
return t('files_versions', 'Initial version')
220+
}
221+
222+
return label
223+
})
224+
225+
const versionAuthor = computed(() => {
226+
if (!props.version.author || !props.version.authorName) {
227+
return ''
228+
}
229+
230+
if (props.version.author === getCurrentUser()?.uid) {
231+
return t('files_versions', 'You')
232+
}
233+
234+
return props.version.authorName ?? props.version.author
235+
})
236+
237+
const versionHumanExplicitDate = computed(() => {
238+
return moment(props.version.mtime).format('LLLL')
239+
})
240+
241+
const downloadURL = computed(() => {
242+
if (props.isCurrent) {
243+
return getRootUrl() + joinPaths('/remote.php/webdav', props.fileInfo.path, props.fileInfo.name)
244+
} else {
245+
return getRootUrl() + props.version.url
246+
}
247+
})
248+
249+
const enableLabeling = computed(() => {
250+
return capabilities.value.files.version_labeling === true
251+
})
252+
253+
const enableDeletion = computed(() => {
254+
return capabilities.value.files.version_deletion === true
255+
})
256+
257+
const hasDeletePermissions = computed(() => {
258+
return hasPermission(props.fileInfo.permissions, Permission.DELETE)
259+
})
260+
261+
const hasUpdatePermissions = computed(() => {
262+
return hasPermission(props.fileInfo.permissions, Permission.UPDATE)
263+
})
264+
265+
const isDownloadable = computed(() => {
266+
if ((props.fileInfo.permissions & Permission.READ) === 0) {
267+
return false
268+
}
269+
270+
// If the mount type is a share, ensure it got download permissions.
271+
if (props.fileInfo.mountType === 'shared') {
272+
const downloadAttribute = props.fileInfo.shareAttributes
273+
.find((attribute) => attribute.scope === 'permissions' && attribute.key === 'download') || {}
274+
// If the download attribute is set to false, the file is not downloadable
275+
if (downloadAttribute?.value === false) {
276+
return false
277+
}
278+
}
279+
280+
return true
281+
})
282+
283+
/**
284+
*
285+
*/
286+
function labelUpdate() {
287+
emit('label-update-request')
288+
}
289+
290+
/**
291+
*
292+
*/
293+
function restoreVersion() {
294+
emit('restore', props.version)
295+
}
296+
297+
/**
298+
*
299+
*/
300+
async function deleteVersion() {
301+
// Let @nc-vue properly remove the popover before we delete the version.
302+
// This prevents @nc-vue from throwing a error.
303+
await nextTick()
304+
await nextTick()
305+
emit('delete', props.version)
306+
}
307+
308+
/**
309+
*
310+
*/
311+
function click() {
312+
if (!props.canView) {
313+
window.location.href = downloadURL.value
314+
return
315+
}
316+
emit('click', { version: props.version })
317+
}
318+
319+
/**
320+
*
321+
*/
322+
function compareVersion() {
323+
if (!props.canView) {
324+
throw new Error('Cannot compare version of this file')
325+
}
326+
emit('compare', { version: props.version })
327+
}
345328
</script>
346329

347330
<style scoped lang="scss">

0 commit comments

Comments
 (0)