aboutsummaryrefslogtreecommitdiffstats
path: root/apps/files/src
diff options
context:
space:
mode:
authorJohn Molakvoæ <skjnldsv@protonmail.com>2023-07-13 09:58:24 +0200
committerJohn Molakvoæ <skjnldsv@protonmail.com>2023-08-01 16:38:06 +0200
commit38480fda3cd1f10652bc1e854207b074921e66b8 (patch)
treec4c9112123f649802c9f86d056fe6da5e89be068 /apps/files/src
parent385f987a28a535e8b6b0020693daa5347093c186 (diff)
downloadnextcloud-server-38480fda3cd1f10652bc1e854207b074921e66b8.tar.gz
nextcloud-server-38480fda3cd1f10652bc1e854207b074921e66b8.zip
feat(files_external): migrate to vue
Signed-off-by: John Molakvoæ <skjnldsv@protonmail.com>
Diffstat (limited to 'apps/files/src')
-rw-r--r--apps/files/src/components/CustomElementRender.vue31
-rw-r--r--apps/files/src/components/FileEntry.vue31
-rw-r--r--apps/files/src/services/FileAction.ts2
-rw-r--r--apps/files/src/views/FilesList.vue27
4 files changed, 59 insertions, 32 deletions
diff --git a/apps/files/src/components/CustomElementRender.vue b/apps/files/src/components/CustomElementRender.vue
index b5bcb8daf2c..62e33b06acf 100644
--- a/apps/files/src/components/CustomElementRender.vue
+++ b/apps/files/src/components/CustomElementRender.vue
@@ -23,7 +23,7 @@
<span />
</template>
-<script>
+<script lang="ts">
/**
* This component is used to render custom
* elements provided by an API. Vue doesn't allow
@@ -46,20 +46,29 @@ export default {
required: true,
},
},
- computed: {
- element() {
- return this.render(this.source, this.currentView)
- },
- },
watch: {
- element() {
- this.$el.replaceWith(this.element)
- this.$el = this.element
+ source() {
+ this.updateRootElement()
+ },
+ currentView() {
+ this.updateRootElement()
},
},
mounted() {
- this.$el.replaceWith(this.element)
- this.$el = this.element
+ this.updateRootElement()
+ },
+ methods: {
+ async updateRootElement() {
+ const span = document.createElement('span') as HTMLSpanElement
+ this.$el.replaceWith(span)
+ this.$el = span
+
+ const element = await this.render(this.source, this.currentView)
+ if (element) {
+ this.$el.replaceWith(element)
+ this.$el = element
+ }
+ },
},
}
</script>
diff --git a/apps/files/src/components/FileEntry.vue b/apps/files/src/components/FileEntry.vue
index 3257e161046..53928b961c2 100644
--- a/apps/files/src/components/FileEntry.vue
+++ b/apps/files/src/components/FileEntry.vue
@@ -91,8 +91,12 @@
<!-- Actions -->
<td v-show="!isRenamingSmallScreen" :class="`files-list__row-actions-${uniqueId}`" class="files-list__row-actions">
- <!-- Inline actions -->
- <!-- TODO: implement CustomElementRender -->
+ <!-- Render actions -->
+ <CustomElementRender v-for="action in enabledRenderActions"
+ :key="action.id"
+ :current-view="currentView"
+ :render="action.renderInline"
+ :source="source" />
<!-- Menu actions -->
<NcActions v-if="active"
@@ -301,15 +305,16 @@ export default Vue.extend({
return formatFileSize(size, true)
},
sizeOpacity() {
- const size = parseInt(this.source.size, 10) || 0
- if (!size || size < 0) {
- return 1
- }
-
// Whatever theme is active, the contrast will pass WCAG AA
// with color main text over main background and an opacity of 0.7
const minOpacity = 0.7
const maxOpacitySize = 10 * 1024 * 1024
+
+ const size = parseInt(this.source.size, 10) || 0
+ if (!size || size < 0) {
+ return minOpacity
+ }
+
return minOpacity + (1 - minOpacity) * Math.pow((this.source.size / maxOpacitySize), 2)
},
@@ -396,9 +401,17 @@ export default Vue.extend({
return this.enabledActions.filter(action => action?.inline?.(this.source, this.currentView))
},
+ // Enabled action that are displayed inline with a custom render function
+ enabledRenderActions() {
+ if (!this.active) {
+ return []
+ }
+ return this.enabledActions.filter(action => typeof action.renderInline === 'function')
+ },
+
// Default actions
enabledDefaultActions() {
- return this.enabledActions.filter(action => !!action.default)
+ return this.enabledActions.filter(action => !!action?.default)
},
// Actions shown in the menu
@@ -407,7 +420,7 @@ export default Vue.extend({
// Showing inline first for the NcActions inline prop
...this.enabledInlineActions,
// Then the rest
- ...this.enabledActions.filter(action => action.default !== DefaultType.HIDDEN),
+ ...this.enabledActions.filter(action => action.default !== DefaultType.HIDDEN && typeof action.renderInline !== 'function'),
].filter((value, index, self) => {
// Then we filter duplicates to prevent inline actions to be shown twice
return index === self.findIndex(action => action.id === value.id)
diff --git a/apps/files/src/services/FileAction.ts b/apps/files/src/services/FileAction.ts
index 4798128671c..a4f7e3ddf17 100644
--- a/apps/files/src/services/FileAction.ts
+++ b/apps/files/src/services/FileAction.ts
@@ -74,7 +74,7 @@ interface FileActionData {
* If defined, the returned html element will be
* appended before the actions menu.
*/
- renderInline?: (file: Node, view: Navigation) => HTMLElement,
+ renderInline?: (file: Node, view: Navigation) => Promise<HTMLElement | null>,
}
export class FileAction {
diff --git a/apps/files/src/views/FilesList.vue b/apps/files/src/views/FilesList.vue
index b14e3287939..99d7767ebc7 100644
--- a/apps/files/src/views/FilesList.vue
+++ b/apps/files/src/views/FilesList.vue
@@ -183,19 +183,24 @@ export default Vue.extend({
return this.isAscSorting ? results : results.reverse()
}
+ const identifiers = [
+ // Sort favorites first if enabled
+ ...this.userConfig.sort_favorites_first ? [v => v.attributes?.favorite !== 1] : [],
+ // Sort folders first if sorting by name
+ ...this.sortingMode === 'basename' ? [v => v.type !== 'folder'] : [],
+ // Use sorting mode if NOT basename (to be able to use displayName too)
+ ...this.sortingMode !== 'basename' ? [v => v[this.sortingMode]] : [],
+ // Use displayName if available, fallback to name
+ v => v.attributes?.displayName || v.basename,
+ // Finally, use basename if all previous sorting methods failed
+ v => v.basename,
+ ]
+ const orders = new Array(identifiers.length).fill(this.isAscSorting ? 'asc' : 'desc')
+
return orderBy(
[...(this.currentFolder?._children || []).map(this.getNode).filter(file => file)],
- [
- // Sort favorites first if enabled
- ...this.userConfig.sort_favorites_first ? [v => v.attributes?.favorite !== 1] : [],
- // Sort folders first if sorting by name
- ...this.sortingMode === 'basename' ? [v => v.type !== 'folder'] : [],
- // Use sorting mode
- v => v[this.sortingMode],
- // Finally, fallback to name
- v => v.basename,
- ],
- this.isAscSorting ? ['asc', 'asc', 'asc'] : ['desc', 'desc', 'desc'],
+ identifiers,
+ orders,
)
},