Merge pull request #23164 from nextcloud/feat/files-sidebar-cleanup-standards

This commit is contained in:
John Molakvoæ 2020-10-07 11:13:14 +02:00 committed by GitHub
commit fd178b92f6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
57 changed files with 306 additions and 241 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -3700,7 +3700,22 @@
console.warn('registerTabView is deprecated! It will be removed in nextcloud 20.'); console.warn('registerTabView is deprecated! It will be removed in nextcloud 20.');
const enabled = tabView.canDisplay || undefined const enabled = tabView.canDisplay || undefined
if (tabView.id) { 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(),
mount: function(el, fileInfo) {
tabView.setFileInfo(fileInfo)
el.appendChild(tabView.el)
},
update: function(fileInfo) {
tabView.setFileInfo(fileInfo)
},
destroy: function() {
tabView.el.remove()
},
enabled: enabled
}))
} }
}, },

View File

@ -1,3 +1,4 @@
<!-- <!--
- @copyright Copyright (c) 2019 John Molakvoæ <skjnldsv@protonmail.com> - @copyright Copyright (c) 2019 John Molakvoæ <skjnldsv@protonmail.com>
- -
@ -19,74 +20,106 @@
- along with this program. If not, see <http://www.gnu.org/licenses/>. - along with this program. If not, see <http://www.gnu.org/licenses/>.
- -
--> -->
<template> <template>
<AppSidebarTab <AppSidebarTab
:id="id" :id="id"
:icon="icon" ref="tab"
:name="name" :name="name"
:active-tab="activeTab" /> :icon="icon">
<!-- Fallback loading -->
<EmptyContent v-if="loading" icon="icon-loading" />
<!-- Using a dummy div as Vue mount replace the element directly
It does NOT append to the content -->
<div ref="mount" />
</AppSidebarTab>
</template> </template>
<script> <script>
import AppSidebarTab from '@nextcloud/vue/dist/Components/AppSidebarTab' import AppSidebarTab from '@nextcloud/vue/dist/Components/AppSidebarTab'
import EmptyContent from '@nextcloud/vue/dist/Components/EmptyContent'
export default { export default {
name: 'LegacyTab', name: 'SidebarTab',
components: { components: {
AppSidebarTab, AppSidebarTab,
EmptyContent,
}, },
props: { props: {
component: { fileInfo: {
type: Object, type: Object,
default: () => {},
required: true, required: true,
}, },
id: { id: {
type: String, type: String,
required: true, required: true,
}, },
fileInfo: { name: {
type: Object, type: String,
default: () => {}, required: true,
},
icon: {
type: String,
required: true,
},
/**
* Lifecycle methods.
* They are prefixed with `on` to avoid conflict with Vue
* methods like this.destroy
*/
onMount: {
type: Function,
required: true,
},
onUpdate: {
type: Function,
required: true,
},
onDestroy: {
type: Function,
required: true, required: true,
}, },
}, },
data() {
return {
loading: true,
}
},
computed: { computed: {
icon() { // TODO: implement a better way to force pass a prop from Sidebar
return this.component.getIcon()
},
name() {
return this.component.getLabel()
},
order() {
return this.component.order
? this.component.order
: 0
},
// needed because AppSidebarTab also uses $parent.activeTab
activeTab() { activeTab() {
return this.$parent.activeTab return this.$parent.activeTab
}, },
}, },
watch: { watch: {
fileInfo(fileInfo) { async fileInfo(newFile, oldFile) {
if (fileInfo) { // Update fileInfo on change
this.setFileInfo(fileInfo) if (newFile.id !== oldFile.id) {
this.loading = true
await this.onUpdate(this.fileInfo)
this.loading = false
} }
}, },
}, },
mounted() {
// append the backbone element and set the FileInfo async mounted() {
this.component.$el.appendTo(this.$el) this.loading = true
// Mount the tab: mounting point, fileInfo, vue context
await this.onMount(this.$refs.mount, this.fileInfo, this.$refs.tab)
this.loading = false
}, },
beforeDestroy() {
this.component.remove() async beforeDestroy() {
}, // unmount the tab
methods: { await this.onDestroy()
setFileInfo(fileInfo) {
this.component.setFileInfo(new OCA.Files.FileInfoModel(fileInfo))
},
}, },
} }
</script> </script>
<style>
</style>

View File

@ -22,32 +22,61 @@
export default class Tab { export default class Tab {
#component
#legacy
#id #id
#name
#icon
#mount
#update
#destroy
#enabled #enabled
/** /**
* Create a new tab instance * Create a new tab instance
* *
* @param {string} id the unique id of this tab * @param {Object} options destructuring object
* @param {Object} component the vue component * @param {string} options.id the unique id of this tab
* @param {Function} [enabled] function that returns if the tab should be shown or not * @param {string} options.name the translated tab name
* @param {boolean} [legacy] is this a legacy tab * @param {string} options.icon the vue component
* @param {Function} options.mount function to mount the tab
* @param {Function} options.update function to update the tab
* @param {Function} options.destroy function to destroy 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, mount, update, destroy, 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 mount !== 'function') {
throw new Error('The mount argument should be a function')
}
if (typeof update !== 'function') {
throw new Error('The update argument should be a function')
}
if (typeof destroy !== 'function') {
throw new Error('The destroy argument should be a function')
}
if (typeof enabled !== 'function') { if (typeof enabled !== 'function') {
throw new Error('The enabled argument should be a function') throw new Error('The enabled argument should be a function')
} }
this.#id = id this.#id = id
this.#component = component this.#name = name
this.#icon = icon
this.#mount = mount
this.#update = update
this.#destroy = destroy
this.#enabled = enabled 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 +84,28 @@ export default class Tab {
return this.#id return this.#id
} }
get component() { get name() {
return this.#component return this.#name
} }
get isEnabled() { get icon() {
return this.#icon
}
get mount() {
return this.#mount
}
get update() {
return this.#update
}
get destroy() {
return this.#destroy
}
get enabled() {
return this.#enabled return this.#enabled
} }
get isLegacyTab() {
return this.#legacy === true
}
} }

View File

@ -21,12 +21,11 @@
*/ */
import Vue from 'vue' import Vue from 'vue'
import { translate as t } from '@nextcloud/l10n'
import SidebarView from './views/Sidebar.vue' import SidebarView from './views/Sidebar.vue'
import Sidebar from './services/Sidebar' import Sidebar from './services/Sidebar'
import Tab from './models/Tab' import Tab from './models/Tab'
import VueClipboard from 'vue-clipboard2'
Vue.use(VueClipboard)
Vue.prototype.t = t Vue.prototype.t = t

View File

@ -52,34 +52,38 @@
</template> </template>
<!-- Error display --> <!-- Error display -->
<div v-if="error" class="emptycontent"> <EmptyContent v-if="error" icon="icon-error">
<div class="icon-error" /> {{ error }}
<h2>{{ error }}</h2> </EmptyContent>
</div>
<!-- If fileInfo fetch is complete, display tabs --> <!-- If fileInfo fetch is complete, render tabs -->
<template v-for="tab in tabs" v-else-if="fileInfo"> <template v-for="tab in tabs" v-else-if="fileInfo">
<component <!-- Hide them if we're loading another file but keep them mounted -->
:is="tabComponent(tab).is" <SidebarTab
v-if="canDisplay(tab)" v-if="tab.enabled(fileInfo)"
v-show="!loading"
:id="tab.id" :id="tab.id"
:key="tab.id" :key="tab.id"
:component="tabComponent(tab).component"
:name="tab.name" :name="tab.name"
:dav-path="davPath" :icon="tab.icon"
:on-mount="tab.mount"
:on-update="tab.update"
:on-destroy="tab.destroy"
:file-info="fileInfo" /> :file-info="fileInfo" />
</template> </template>
</AppSidebar> </AppSidebar>
</template> </template>
<script> <script>
import { encodePath } from '@nextcloud/paths'
import $ from 'jquery' import $ from 'jquery'
import axios from '@nextcloud/axios' import axios from '@nextcloud/axios'
import AppSidebar from '@nextcloud/vue/dist/Components/AppSidebar' import AppSidebar from '@nextcloud/vue/dist/Components/AppSidebar'
import ActionButton from '@nextcloud/vue/dist/Components/ActionButton' import ActionButton from '@nextcloud/vue/dist/Components/ActionButton'
import EmptyContent from '@nextcloud/vue/dist/Components/EmptyContent'
import FileInfo from '../services/FileInfo' import FileInfo from '../services/FileInfo'
import LegacyTab from '../components/LegacyTab' import SidebarTab from '../components/SidebarTab'
import LegacyView from '../components/LegacyView' import LegacyView from '../components/LegacyView'
import { encodePath } from '@nextcloud/paths'
export default { export default {
name: 'Sidebar', name: 'Sidebar',
@ -87,7 +91,9 @@ export default {
components: { components: {
ActionButton, ActionButton,
AppSidebar, AppSidebar,
EmptyContent,
LegacyView, LegacyView,
SidebarTab,
}, },
data() { data() {
@ -95,6 +101,7 @@ export default {
// reactive state // reactive state
Sidebar: OCA.Files.Sidebar.state, Sidebar: OCA.Files.Sidebar.state,
error: null, error: null,
loading: true,
fileInfo: null, fileInfo: null,
starLoading: false, starLoading: false,
} }
@ -185,15 +192,16 @@ export default {
appSidebar() { appSidebar() {
if (this.fileInfo) { if (this.fileInfo) {
return { return {
background: this.background, 'data-mimetype': this.fileInfo.mimetype,
'star-loading': this.starLoading,
active: this.activeTab, active: this.activeTab,
background: this.background,
class: { 'has-preview': this.fileInfo.hasPreview }, class: { 'has-preview': this.fileInfo.hasPreview },
compact: !this.fileInfo.hasPreview, compact: !this.fileInfo.hasPreview,
'star-loading': this.starLoading, loading: this.loading,
starred: this.fileInfo.isFavourited, starred: this.fileInfo.isFavourited,
subtitle: this.subtitle, subtitle: this.subtitle,
title: this.fileInfo.name, title: this.fileInfo.name,
'data-mimetype': this.fileInfo.mimetype,
} }
} else if (this.error) { } else if (this.error) {
return { return {
@ -201,12 +209,12 @@ export default {
subtitle: '', subtitle: '',
title: '', title: '',
} }
} else { }
return { // no fileInfo yet, showing empty data
class: 'icon-loading', return {
subtitle: '', loading: this.loading,
title: '', subtitle: '',
} title: '',
} }
}, },
@ -241,35 +249,6 @@ export default {
}, },
}, },
watch: {
// update the sidebar data
async file(curr, prev) {
this.resetData()
if (curr && curr.trim() !== '') {
try {
this.fileInfo = await FileInfo(this.davPath)
// adding this as fallback because other apps expect it
this.fileInfo.dir = this.file.split('/').slice(0, -1).join('/')
// DEPRECATED legacy views
// TODO: remove
this.views.forEach(view => {
view.setFileInfo(this.fileInfo)
})
this.$nextTick(() => {
if (this.$refs.sidebar) {
this.$refs.sidebar.updateTabs()
}
})
} catch (error) {
this.error = t('files', 'Error while loading the file data')
console.error('Error while loading the file data', error)
}
}
},
},
methods: { methods: {
/** /**
* Can this tab be displayed ? * Can this tab be displayed ?
@ -278,14 +257,14 @@ export default {
* @returns {boolean} * @returns {boolean}
*/ */
canDisplay(tab) { canDisplay(tab) {
return tab.isEnabled(this.fileInfo) return tab.enabled(this.fileInfo)
}, },
resetData() { resetData() {
this.error = null this.error = null
this.fileInfo = null this.fileInfo = null
this.$nextTick(() => { this.$nextTick(() => {
if (this.$refs.sidebar) { if (this.$refs.tabs) {
this.$refs.sidebar.updateTabs() this.$refs.tabs.updateTabs()
} }
}) })
}, },
@ -327,18 +306,6 @@ export default {
return OC.MimeType.getIconUrl(mimeType) return OC.MimeType.getIconUrl(mimeType)
}, },
tabComponent(tab) {
if (tab.isLegacyTab) {
return {
is: LegacyTab,
component: tab.component,
}
}
return {
is: tab.component,
}
},
/** /**
* Set current active tab * Set current active tab
* *
@ -415,9 +382,11 @@ export default {
// update current opened file // update current opened file
this.Sidebar.file = path this.Sidebar.file = path
// reset previous data
this.resetData()
if (path && path.trim() !== '') { if (path && path.trim() !== '') {
// reset data, keep old fileInfo to not reload all tabs and just hide them
this.error = null
this.loading = true
try { try {
this.fileInfo = await FileInfo(this.davPath) this.fileInfo = await FileInfo(this.davPath)
// adding this as fallback because other apps expect it // adding this as fallback because other apps expect it
@ -430,8 +399,8 @@ export default {
}) })
this.$nextTick(() => { this.$nextTick(() => {
if (this.$refs.sidebar) { if (this.$refs.tabs) {
this.$refs.sidebar.updateTabs() this.$refs.tabs.updateTabs()
} }
}) })
} catch (error) { } catch (error) {
@ -439,6 +408,8 @@ export default {
console.error('Error while loading the file data', error) console.error('Error while loading the file data', error)
throw new Error(error) throw new Error(error)
} finally {
this.loading = false
} }
} }
}, },

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,2 +1,2 @@
!function(e){var n={};function t(r){if(n[r])return n[r].exports;var o=n[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}t.m=e,t.c=n,t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{enumerable:!0,get:r})},t.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},t.t=function(e,n){if(1&n&&(e=t(e)),8&n)return e;if(4&n&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(t.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&n&&"string"!=typeof e)for(var o in e)t.d(r,o,function(n){return e[n]}.bind(null,o));return r},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},t.p="/js/",t(t.s=152)}({152:function(e,n,r){r.p=OC.linkTo("files_sharing","js/dist/"),r.nc=btoa(OC.requestToken),window.OCP.Collaboration.registerType("file",{action:function(){return new Promise((function(e,n){OC.dialogs.filepicker(t("files_sharing","Link to a file"),(function(t){OC.Files.getClient().getFileInfo(t).then((function(n,t){e(t.id)})).fail((function(){n(new Error("Cannot get fileinfo"))}))}),!1,null,!1,OC.dialogs.FILEPICKER_TYPE_CHOOSE,"",{allowDirectoryChooser:!0})}))},typeString:t("files_sharing","Link to a file"),typeIconClass:"icon-files-dark"})}}); !function(e){var n={};function t(r){if(n[r])return n[r].exports;var o=n[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}t.m=e,t.c=n,t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{enumerable:!0,get:r})},t.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},t.t=function(e,n){if(1&n&&(e=t(e)),8&n)return e;if(4&n&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(t.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&n&&"string"!=typeof e)for(var o in e)t.d(r,o,function(n){return e[n]}.bind(null,o));return r},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},t.p="/js/",t(t.s=153)}({153:function(e,n,r){r.p=OC.linkTo("files_sharing","js/dist/"),r.nc=btoa(OC.requestToken),window.OCP.Collaboration.registerType("file",{action:function(){return new Promise((function(e,n){OC.dialogs.filepicker(t("files_sharing","Link to a file"),(function(t){OC.Files.getClient().getFileInfo(t).then((function(n,t){e(t.id)})).fail((function(){n(new Error("Cannot get fileinfo"))}))}),!1,null,!1,OC.dialogs.FILEPICKER_TYPE_CHOOSE,"",{allowDirectoryChooser:!0})}))},typeString:t("files_sharing","Link to a file"),typeIconClass:"icon-files-dark"})}});
//# sourceMappingURL=collaboration.js.map //# sourceMappingURL=collaboration.js.map

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,2 +1,2 @@
!function(e){var t={};function r(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="/js/",r(r.s=277)}({277:function(e,t){Object.assign(OC,{Share:{SHARE_TYPE_USER:0,SHARE_TYPE_GROUP:1,SHARE_TYPE_LINK:3,SHARE_TYPE_EMAIL:4,SHARE_TYPE_REMOTE:6,SHARE_TYPE_CIRCLE:7,SHARE_TYPE_GUEST:8,SHARE_TYPE_REMOTE_GROUP:9,SHARE_TYPE_ROOM:10}})}}); !function(e){var t={};function r(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="/js/",r(r.s=278)}({278:function(e,t){Object.assign(OC,{Share:{SHARE_TYPE_USER:0,SHARE_TYPE_GROUP:1,SHARE_TYPE_LINK:3,SHARE_TYPE_EMAIL:4,SHARE_TYPE_REMOTE:6,SHARE_TYPE_CIRCLE:7,SHARE_TYPE_GUEST:8,SHARE_TYPE_REMOTE_GROUP:9,SHARE_TYPE_ROOM:10}})}});
//# sourceMappingURL=main.js.map //# sourceMappingURL=main.js.map

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -19,11 +19,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * 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 SharingTab from './views/SharingTab'
import ShareSearch from './services/ShareSearch' import ShareSearch from './services/ShareSearch'
import ExternalLinkActions from './services/ExternalLinkActions' import ExternalLinkActions from './services/ExternalLinkActions'
import TabSections from './services/TabSections' import TabSections from './services/TabSections'
// Init Sharing Tab Service // Init Sharing Tab Service
@ -34,8 +36,40 @@ Object.assign(window.OCA.Sharing, { ShareSearch: new ShareSearch() })
Object.assign(window.OCA.Sharing, { ExternalLinkActions: new ExternalLinkActions() }) Object.assign(window.OCA.Sharing, { ExternalLinkActions: new ExternalLinkActions() })
Object.assign(window.OCA.Sharing, { ShareTabSections: new TabSections() }) 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)
let TabInstance = null
window.addEventListener('DOMContentLoaded', function() { window.addEventListener('DOMContentLoaded', function() {
if (OCA.Files && OCA.Files.Sidebar) { 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',
async mount(el, fileInfo, context) {
if (TabInstance) {
TabInstance.$destroy()
}
TabInstance = new View({
// Better integration with vue parent component
parent: context,
})
// Only mount after we have all the info we need
await TabInstance.update(fileInfo)
TabInstance.$mount(el)
},
update(fileInfo) {
TabInstance.update(fileInfo)
},
destroy() {
TabInstance.$destroy()
TabInstance = null
},
}))
} }
}) })

View File

@ -21,10 +21,7 @@
--> -->
<template> <template>
<Tab :id="id" <div :class="{ 'icon-loading': loading }">
:icon="icon"
:name="name"
:class="{ 'icon-loading': loading }">
<!-- error message --> <!-- error message -->
<div v-if="error" class="emptycontent"> <div v-if="error" class="emptycontent">
<div class="icon icon-error" /> <div class="icon icon-error" />
@ -84,7 +81,7 @@
<component :is="section($refs['section-'+index], fileInfo)" :file-info="fileInfo" /> <component :is="section($refs['section-'+index], fileInfo)" :file-info="fileInfo" />
</div> </div>
</template> </template>
</Tab> </div>
</template> </template>
<script> <script>
@ -92,7 +89,6 @@ import { CollectionList } from 'nextcloud-vue-collections'
import { generateOcsUrl } from '@nextcloud/router' import { generateOcsUrl } from '@nextcloud/router'
import Avatar from '@nextcloud/vue/dist/Components/Avatar' import Avatar from '@nextcloud/vue/dist/Components/Avatar'
import axios from '@nextcloud/axios' import axios from '@nextcloud/axios'
import Tab from '@nextcloud/vue/dist/Components/AppSidebarTab'
import { shareWithTitle } from '../utils/SharedWithMe' import { shareWithTitle } from '../utils/SharedWithMe'
import Share from '../models/Share' import Share from '../models/Share'
@ -117,56 +113,29 @@ export default {
SharingInput, SharingInput,
SharingLinkList, SharingLinkList,
SharingList, SharingList,
Tab,
}, },
mixins: [ShareTypes], mixins: [ShareTypes],
props: {
fileInfo: {
type: Object,
default: () => {},
required: true,
},
},
data() { data() {
return { return {
error: '', error: '',
expirationInterval: null, expirationInterval: null,
icon: 'icon-share',
loading: true, loading: true,
name: t('files_sharing', 'Sharing'),
fileInfo: null,
// reshare Share object // reshare Share object
reshare: null, reshare: null,
sharedWithMe: {}, sharedWithMe: {},
shares: [], shares: [],
linkShares: [], linkShares: [],
sections: OCA.Sharing.ShareTabSections.getSections(), sections: OCA.Sharing.ShareTabSections.getSections(),
} }
}, },
computed: { 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? * Is this share shared with me?
* *
@ -182,20 +151,17 @@ export default {
}, },
}, },
watch: {
fileInfo(newFile, oldFile) {
if (newFile.id !== oldFile.id) {
this.resetState()
this.getShares()
}
},
},
beforeMount() {
this.getShares()
},
methods: { methods: {
/**
* Update current fileInfo and fetch new data
* @param {Object} fileInfo the current file FileInfo
*/
async update(fileInfo) {
this.fileInfo = fileInfo
this.resetState()
this.getShares()
},
/** /**
* Get the existing shares infos * Get the existing shares infos
*/ */
@ -248,6 +214,7 @@ export default {
this.error = '' this.error = ''
this.sharedWithMe = {} this.sharedWithMe = {}
this.shares = [] this.shares = []
this.linkShares = []
}, },
/** /**
@ -341,7 +308,3 @@ export default {
}, },
} }
</script> </script>
<style lang="scss" scoped>
</style>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

12
package-lock.json generated
View File

@ -1272,9 +1272,9 @@
} }
}, },
"@nextcloud/vue": { "@nextcloud/vue": {
"version": "2.6.8", "version": "2.6.9",
"resolved": "https://registry.npmjs.org/@nextcloud/vue/-/vue-2.6.8.tgz", "resolved": "https://registry.npmjs.org/@nextcloud/vue/-/vue-2.6.9.tgz",
"integrity": "sha512-9yi9V4gX4Y1uxh2hNxCAlTHaS9zolzAy7x1sowII/WZfxMysF/yIGmEsnYGyz6CZ5eYCzxNUgrU5p/HQ21/09Q==", "integrity": "sha512-Jx5h9WH+W9Tjz1mAhHq/QpqGMF9XbxpfQIK1DkEMPZ9N9ooLCpphaDN9qmPgOgt68ZGeUfGvJ+HrIfwD0r16Gw==",
"requires": { "requires": {
"@nextcloud/auth": "^1.2.3", "@nextcloud/auth": "^1.2.3",
"@nextcloud/axios": "^1.3.2", "@nextcloud/axios": "^1.3.2",
@ -3432,9 +3432,9 @@
} }
}, },
"emoji-mart-vue-fast": { "emoji-mart-vue-fast": {
"version": "7.0.5", "version": "7.0.6",
"resolved": "https://registry.npmjs.org/emoji-mart-vue-fast/-/emoji-mart-vue-fast-7.0.5.tgz", "resolved": "https://registry.npmjs.org/emoji-mart-vue-fast/-/emoji-mart-vue-fast-7.0.6.tgz",
"integrity": "sha512-+ayg30hhxqqM9oMtN9uUG470hT9gtOdFenByJJBm3XTfzI2QMVJ69euwk+xF55OphLfKZxQG7mnVz13lDOjb3g==", "integrity": "sha512-nvGoIRMhgVYHFBcHJMjjYKS71RopuBRGuO/51DqOcIFreRJAaTvAwmk9eUjI1mwXHY7b/cCarrGi3FBE7Kz37A==",
"requires": { "requires": {
"@babel/polyfill": "7.2.5", "@babel/polyfill": "7.2.5",
"@babel/runtime": "7.3.4", "@babel/runtime": "7.3.4",

View File

@ -39,7 +39,7 @@
"@nextcloud/password-confirmation": "^1.0.1", "@nextcloud/password-confirmation": "^1.0.1",
"@nextcloud/paths": "^1.1.2", "@nextcloud/paths": "^1.1.2",
"@nextcloud/router": "^1.1.0", "@nextcloud/router": "^1.1.0",
"@nextcloud/vue": "^2.6.8", "@nextcloud/vue": "^2.6.9",
"@nextcloud/vue-dashboard": "^1.0.1", "@nextcloud/vue-dashboard": "^1.0.1",
"autosize": "^4.0.2", "autosize": "^4.0.2",
"backbone": "^1.4.0", "backbone": "^1.4.0",