aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>2020-10-04 00:30:50 +0200
committerJohn Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>2020-10-07 09:40:58 +0200
commit843d799a2e2c884026883e3f41b81066801a877d (patch)
treeb427d0296556488e34e0892f01c858ed5294b954
parent678ef8466d5d1788bab1cf66786e47515a1bcbd9 (diff)
downloadnextcloud-server-843d799a2e2c884026883e3f41b81066801a877d.tar.gz
nextcloud-server-843d799a2e2c884026883e3f41b81066801a877d.zip
Move Files Sidebar to proper javascript standard
Signed-off-by: John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>
-rw-r--r--apps/files/js/filelist.js11
-rw-r--r--apps/files/src/components/SidebarTab.vue (renamed from apps/files/src/components/LegacyTab.vue)67
-rw-r--r--apps/files/src/models/Tab.js59
-rw-r--r--apps/files/src/sidebar.js3
-rw-r--r--apps/files/src/views/Sidebar.vue40
-rw-r--r--apps/files_sharing/src/files_sharing_tab.js26
-rw-r--r--apps/files_sharing/src/views/SharingTab.vue35
7 files changed, 124 insertions, 117 deletions
diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js
index 5e6225a48e9..3f144cc1f24 100644
--- a/apps/files/js/filelist.js
+++ b/apps/files/js/filelist.js
@@ -3700,7 +3700,16 @@
console.warn('registerTabView is deprecated! It will be removed in nextcloud 20.');
const enabled = tabView.canDisplay || undefined
if (tabView.id) {
- OCA.Files.Sidebar.registerTab(new OCA.Files.Sidebar.Tab(tabView.id, tabView, enabled, true))
+ OCA.Files.Sidebar.registerTab(new OCA.Files.Sidebar.Tab({
+ id: tabView.id,
+ name: tabView.getLabel(),
+ icon: tabView.getIcon(),
+ render: function(el, fileInfo) {
+ tabView.setFileInfo(fileInfo)
+ el.appendChild(tabView.el)
+ },
+ enabled,
+ }))
}
},
diff --git a/apps/files/src/components/LegacyTab.vue b/apps/files/src/components/SidebarTab.vue
index c8308dd6209..ecf04e9c9b3 100644
--- a/apps/files/src/components/LegacyTab.vue
+++ b/apps/files/src/components/SidebarTab.vue
@@ -1,3 +1,4 @@
+
<!--
- @copyright Copyright (c) 2019 John Molakvoæ <skjnldsv@protonmail.com>
-
@@ -19,74 +20,74 @@
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-->
-
<template>
<AppSidebarTab
:id="id"
- :icon="icon"
:name="name"
- :active-tab="activeTab" />
+ :icon="icon">
+ <!-- Using a dummy div as Vue mount replace the element directly
+ It does NOT append to the content -->
+ <div ref="mount"></div>
+ </AppSidebarTab>
</template>
+
<script>
import AppSidebarTab from '@nextcloud/vue/dist/Components/AppSidebarTab'
-
export default {
- name: 'LegacyTab',
+ name: 'SidebarTab',
+
components: {
AppSidebarTab,
},
+
props: {
- component: {
+ fileInfo: {
type: Object,
+ default: () => {},
required: true,
},
id: {
type: String,
required: true,
},
- fileInfo: {
- type: Object,
- default: () => {},
+ name: {
+ type: String,
required: true,
},
- },
- computed: {
- icon() {
- return this.component.getIcon()
- },
- name() {
- return this.component.getLabel()
+ icon: {
+ type: String,
+ required: true,
},
- order() {
- return this.component.order
- ? this.component.order
- : 0
+ render: {
+ type: Function,
+ required: true,
},
- // needed because AppSidebarTab also uses $parent.activeTab
+ },
+
+ computed: {
+ // TODO: implement a better way to force pass a prop fromm Sidebar
activeTab() {
return this.$parent.activeTab
},
},
+
watch: {
- fileInfo(fileInfo) {
- if (fileInfo) {
- this.setFileInfo(fileInfo)
+ fileInfo(newFile, oldFile) {
+ if (newFile.id !== oldFile.id) {
+ this.mountTab()
}
},
},
+
mounted() {
- // append the backbone element and set the FileInfo
- this.component.$el.appendTo(this.$el)
- },
- beforeDestroy() {
- this.component.remove()
+ this.mountTab()
},
+
methods: {
- setFileInfo(fileInfo) {
- this.component.setFileInfo(new OCA.Files.FileInfoModel(fileInfo))
+ mountTab() {
+ // Mount the tab into this component
+ this.render(this.$refs.mount, this.fileInfo)
},
},
}
</script>
-<style>
-</style>
diff --git a/apps/files/src/models/Tab.js b/apps/files/src/models/Tab.js
index fd1ea9888d9..753b9c9c282 100644
--- a/apps/files/src/models/Tab.js
+++ b/apps/files/src/models/Tab.js
@@ -22,32 +22,49 @@
export default class Tab {
- #component
- #legacy
#id
+ #name
+ #icon
+ #render
#enabled
/**
* Create a new tab instance
*
- * @param {string} id the unique id of this tab
- * @param {Object} component the vue component
- * @param {Function} [enabled] function that returns if the tab should be shown or not
- * @param {boolean} [legacy] is this a legacy tab
+ * @param {Object} options destructuring object
+ * @param {string} options.id the unique id of this tab
+ * @param {string} options.name the translated tab name
+ * @param {string} options.icon the vue component
+ * @param {Function} options.render function to render the tab
+ * @param {Function} [options.enabled] define conditions whether this tab is active. Must returns a boolean
*/
- constructor(id, component, enabled = () => true, legacy) {
+ constructor({ id, name, icon, render, enabled }) {
+ if (enabled === undefined) {
+ enabled = () => true
+ }
+
+ // Sanity checks
+ if (typeof id !== 'string' || id.trim() === '') {
+ throw new Error('The id argument is not a valid string')
+ }
+ if (typeof name !== 'string' || name.trim() === '') {
+ throw new Error('The name argument is not a valid string')
+ }
+ if (typeof icon !== 'string' || icon.trim() === '') {
+ throw new Error('The icon argument is not a valid string')
+ }
+ if (typeof render !== 'function') {
+ throw new Error('The render argument should be a function')
+ }
if (typeof enabled !== 'function') {
throw new Error('The enabled argument should be a function')
}
this.#id = id
- this.#component = component
+ this.#name = name
+ this.#icon = icon
+ this.#render = render
this.#enabled = enabled
- this.#legacy = legacy === true
-
- if (this.#legacy) {
- console.warn('Legacy tabs are deprecated! They will be removed in nextcloud 20.')
- }
}
@@ -55,16 +72,20 @@ export default class Tab {
return this.#id
}
- get component() {
- return this.#component
+ get name() {
+ return this.#name
}
- get isEnabled() {
- return this.#enabled
+ get icon() {
+ return this.#icon
}
- get isLegacyTab() {
- return this.#legacy === true
+ get render() {
+ return this.#render
+ }
+
+ get enabled() {
+ return this.#enabled
}
}
diff --git a/apps/files/src/sidebar.js b/apps/files/src/sidebar.js
index f815a498938..508093465d4 100644
--- a/apps/files/src/sidebar.js
+++ b/apps/files/src/sidebar.js
@@ -24,9 +24,6 @@ import Vue from 'vue'
import SidebarView from './views/Sidebar.vue'
import Sidebar from './services/Sidebar'
import Tab from './models/Tab'
-import VueClipboard from 'vue-clipboard2'
-
-Vue.use(VueClipboard)
Vue.prototype.t = t
diff --git a/apps/files/src/views/Sidebar.vue b/apps/files/src/views/Sidebar.vue
index 1fc89c6a7ee..6fa5c35dca2 100644
--- a/apps/files/src/views/Sidebar.vue
+++ b/apps/files/src/views/Sidebar.vue
@@ -58,15 +58,14 @@
</div>
<!-- If fileInfo fetch is complete, display tabs -->
- <template v-for="tab in tabs" v-else-if="fileInfo">
- <component
- :is="tabComponent(tab).is"
- v-if="canDisplay(tab)"
+ <template v-else-if="fileInfo" v-for="tab in tabs">
+ <SidebarTab
+ v-if="tab.enabled(fileInfo)"
:id="tab.id"
:key="tab.id"
- :component="tabComponent(tab).component"
:name="tab.name"
- :dav-path="davPath"
+ :icon="tab.icon"
+ :render="tab.render"
:file-info="fileInfo" />
</template>
</AppSidebar>
@@ -77,7 +76,7 @@ import axios from '@nextcloud/axios'
import AppSidebar from '@nextcloud/vue/dist/Components/AppSidebar'
import ActionButton from '@nextcloud/vue/dist/Components/ActionButton'
import FileInfo from '../services/FileInfo'
-import LegacyTab from '../components/LegacyTab'
+import SidebarTab from '../components/SidebarTab'
import LegacyView from '../components/LegacyView'
import { encodePath } from '@nextcloud/paths'
@@ -87,6 +86,7 @@ export default {
components: {
ActionButton,
AppSidebar,
+ SidebarTab,
LegacyView,
},
@@ -258,8 +258,8 @@ export default {
})
this.$nextTick(() => {
- if (this.$refs.sidebar) {
- this.$refs.sidebar.updateTabs()
+ if (this.$refs.tabs) {
+ this.$refs.tabs.updateTabs()
}
})
} catch (error) {
@@ -278,14 +278,14 @@ export default {
* @returns {boolean}
*/
canDisplay(tab) {
- return tab.isEnabled(this.fileInfo)
+ return tab.enabled(this.fileInfo)
},
resetData() {
this.error = null
this.fileInfo = null
this.$nextTick(() => {
- if (this.$refs.sidebar) {
- this.$refs.sidebar.updateTabs()
+ if (this.$refs.tabs) {
+ this.$refs.tabs.updateTabs()
}
})
},
@@ -327,18 +327,6 @@ export default {
return OC.MimeType.getIconUrl(mimeType)
},
- tabComponent(tab) {
- if (tab.isLegacyTab) {
- return {
- is: LegacyTab,
- component: tab.component,
- }
- }
- return {
- is: tab.component,
- }
- },
-
/**
* Set current active tab
*
@@ -430,8 +418,8 @@ export default {
})
this.$nextTick(() => {
- if (this.$refs.sidebar) {
- this.$refs.sidebar.updateTabs()
+ if (this.$refs.tabs) {
+ this.$refs.tabs.updateTabs()
}
})
} catch (error) {
diff --git a/apps/files_sharing/src/files_sharing_tab.js b/apps/files_sharing/src/files_sharing_tab.js
index ffb6cdec30a..e8988e8c40a 100644
--- a/apps/files_sharing/src/files_sharing_tab.js
+++ b/apps/files_sharing/src/files_sharing_tab.js
@@ -19,11 +19,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
+import Vue from 'vue'
+import VueClipboard from 'vue-clipboard2'
+import { translate as t, translatePlural as n } from '@nextcloud/l10n'
import SharingTab from './views/SharingTab'
import ShareSearch from './services/ShareSearch'
import ExternalLinkActions from './services/ExternalLinkActions'
-
import TabSections from './services/TabSections'
// Init Sharing Tab Service
@@ -34,8 +36,28 @@ Object.assign(window.OCA.Sharing, { ShareSearch: new ShareSearch() })
Object.assign(window.OCA.Sharing, { ExternalLinkActions: new ExternalLinkActions() })
Object.assign(window.OCA.Sharing, { ShareTabSections: new TabSections() })
+Vue.prototype.t = t
+Vue.prototype.n = n
+Vue.use(VueClipboard)
+
+// Init Sharing tab component
+const View = Vue.extend(SharingTab)
+
window.addEventListener('DOMContentLoaded', function() {
if (OCA.Files && OCA.Files.Sidebar) {
- OCA.Files.Sidebar.registerTab(new OCA.Files.Sidebar.Tab('sharing', SharingTab))
+ OCA.Files.Sidebar.registerTab(new OCA.Files.Sidebar.Tab({
+ id: 'sharing',
+ name: t('files_sharing', 'Sharing'),
+ icon: 'icon-share',
+
+ render: (el, fileInfo) => {
+ new View({
+ propsData: {
+ fileInfo,
+ },
+ }).$mount(el)
+ console.info(el)
+ },
+ }))
}
})
diff --git a/apps/files_sharing/src/views/SharingTab.vue b/apps/files_sharing/src/views/SharingTab.vue
index 40c8572912f..c92aac40d0a 100644
--- a/apps/files_sharing/src/views/SharingTab.vue
+++ b/apps/files_sharing/src/views/SharingTab.vue
@@ -21,10 +21,7 @@
-->
<template>
- <Tab :id="id"
- :icon="icon"
- :name="name"
- :class="{ 'icon-loading': loading }">
+ <div :class="{ 'icon-loading': loading }">
<!-- error message -->
<div v-if="error" class="emptycontent">
<div class="icon icon-error" />
@@ -84,7 +81,7 @@
<component :is="section($refs['section-'+index], fileInfo)" :file-info="fileInfo" />
</div>
</template>
- </Tab>
+ </div>
</template>
<script>
@@ -92,7 +89,6 @@ import { CollectionList } from 'nextcloud-vue-collections'
import { generateOcsUrl } from '@nextcloud/router'
import Avatar from '@nextcloud/vue/dist/Components/Avatar'
import axios from '@nextcloud/axios'
-import Tab from '@nextcloud/vue/dist/Components/AppSidebarTab'
import { shareWithTitle } from '../utils/SharedWithMe'
import Share from '../models/Share'
@@ -117,7 +113,6 @@ export default {
SharingInput,
SharingLinkList,
SharingList,
- Tab,
},
mixins: [ShareTypes],
@@ -134,9 +129,7 @@ export default {
return {
error: '',
expirationInterval: null,
- icon: 'icon-share',
loading: true,
- name: t('files_sharing', 'Sharing'),
// reshare Share object
reshare: null,
sharedWithMe: {},
@@ -148,26 +141,6 @@ export default {
computed: {
/**
- * Needed to differenciate the tabs
- * pulled from the AppSidebarTab component
- *
- * @returns {string}
- */
- id() {
- return 'sharing'
- },
-
- /**
- * Returns the current active tab
- * needed because AppSidebarTab also uses $parent.activeTab
- *
- * @returns {string}
- */
- activeTab() {
- return this.$parent.activeTab
- },
-
- /**
* Is this share shared with me?
*
* @returns {boolean}
@@ -341,7 +314,3 @@ export default {
},
}
</script>
-
-<style lang="scss" scoped>
-
-</style>