diff --git a/contentcuration/contentcuration/frontend/channelEdit/views/TreeView/TreeViewBase.vue b/contentcuration/contentcuration/frontend/channelEdit/views/TreeView/TreeViewBase.vue index 4a364278c2..76805f645b 100644 --- a/contentcuration/contentcuration/frontend/channelEdit/views/TreeView/TreeViewBase.vue +++ b/contentcuration/contentcuration/frontend/channelEdit/views/TreeView/TreeViewBase.vue @@ -60,22 +60,21 @@ v-if="errorsInChannel && canEdit" class="mx-1" > - + {{ $formatNumber(errorsInChannel) }} + + + - - - {{ $formatNumber(errorsInChannel) }} - - - {{ $tr('incompleteDescendantsText', { count: errorsInChannel }) }} - + {{ $tr('apiGenerated') }} - - - - {{ $tr('shareMenuButton') }} - + + + - - - {{ $tr('submitToCommunityLibrary') }} - - - {{ $tr('inviteCollaborators') }} - - - {{ $tr('shareToken') }} - - - - + + + + + - - - - - {{ $tr('publishButton') }} - - - {{ publishButtonTooltip }} - + - - - - - + + + - - - - {{ $tr('publishButton') }} - - - {{ $tr('channelDetails') }} - - - - {{ $tr('editChannel') }} - - - - - - {{ $tr('getToken') }} - - - {{ $tr('shareChannel') }} - - - {{ $tr('syncChannel') }} - - - {{ $tr('openTrash') }} - - - - {{ $tr('deleteChannel') }} - - - - + @@ -521,6 +435,104 @@ dropEffect() { return DropEffect.COPY; }, + shareMenuOptions() { + const options = []; + if (this.canSubmitToCommunityLibrary) { + options.push({ + label: this.$tr('submitToCommunityLibrary'), + value: 'submit-to-library', + }); + } + if (this.canManage) { + options.push({ + label: this.$tr('inviteCollaborators'), + value: 'invite-collaborators', + }); + } + if (this.isPublished) { + options.push({ + label: this.$tr('shareToken'), + value: 'share-token', + }); + } + return options; + }, + channelMenuOptions() { + const options = []; + + if (this.$vuetify.breakpoint.xsOnly) { + if (this.canManage) { + options.push({ + label: this.$tr('publishButton'), + value: 'publish', + disabled: this.disablePublish, + }); + } + options.push({ + label: this.$tr('channelDetails'), + value: 'view-details', + }); + if (this.canEdit) { + let label = this.$tr('editChannel'); + if (!this.currentChannel.language) { + label = `${label}`; + } + options.push({ + label, + value: 'edit-channel', + }); + } + + if (this.canSubmitToCommunityLibrary) { + options.push({ + label: this.$tr('submitToCommunityLibrary'), + value: 'submit-to-library', + }); + } + if (this.canManage) { + options.push({ + label: this.$tr('inviteCollaborators'), + value: 'invite-collaborators', + }); + } + if (this.isPublished) { + options.push({ + label: this.$tr('shareToken'), + value: 'share-token', + }); + } + } else { + if (this.isPublished) { + options.push({ + label: this.$tr('getToken'), + value: 'get-token', + }); + } + if (this.canManage) { + options.push({ + label: this.$tr('shareChannel'), + value: 'share-channel', + }); + } + } + + if (this.canEdit) { + options.push({ + label: this.$tr('syncChannel'), + value: 'sync', + }); + options.push({ + label: this.$tr('openTrash'), + value: 'trash', + }); + options.push({ + label: this.$tr('deleteChannel'), + value: 'delete', + }); + } + + return options; + }, }, watch: { rootId: { @@ -573,6 +585,56 @@ trackClickEvent(eventLabel) { this.$analytics.trackClick('channel_editor_toolbar', eventLabel); }, + handleShareMenuSelect(option) { + if (option.value === 'submit-to-library') { + this.showSubmitToCommunityLibrarySidePanel = true; + } else if (option.value === 'invite-collaborators') { + this.trackClickEvent('Share channel'); + this.$router.push(this.shareChannelLink); + } else if (option.value === 'share-token') { + this.showTokenModal = true; + } + }, + handleChannelMenuSelect(option) { + switch (option.value) { + case 'publish': + this.showPublishSidePanel = true; + break; + case 'view-details': + this.$router.push(this.viewChannelDetailsLink); + break; + case 'edit-channel': + this.$router.push(this.editChannelLink); + break; + case 'submit-to-library': + this.showSubmitToCommunityLibrarySidePanel = true; + break; + case 'invite-collaborators': + this.trackClickEvent('Share channel'); + this.$router.push(this.shareChannelLink); + break; + case 'share-token': + this.showTokenModal = true; + break; + case 'get-token': + this.showTokenModal = true; + break; + case 'share-channel': + this.trackClickEvent('Share channel'); + this.$router.push(this.shareChannelLink); + break; + case 'sync': + this.syncChannel(); + break; + case 'trash': + this.trackClickEvent('Trash'); + this.$router.push(this.trashLink); + break; + case 'delete': + this.deleteChannelModal(); + break; + } + }, }, $trs: { channelDetails: 'View channel details', @@ -598,6 +660,9 @@ inviteCollaborators: 'Invite collaborators', shareToken: 'Share token', + // More options menu + moreOptions: 'More options', + channelDeletedSnackbar: 'Channel deleted', }, }; diff --git a/contentcuration/contentcuration/frontend/channelEdit/views/TreeView/__tests__/TreeViewBase.spec.js b/contentcuration/contentcuration/frontend/channelEdit/views/TreeView/__tests__/TreeViewBase.spec.js index 5987cb99d0..4c0ce7dab7 100644 --- a/contentcuration/contentcuration/frontend/channelEdit/views/TreeView/__tests__/TreeViewBase.spec.js +++ b/contentcuration/contentcuration/frontend/channelEdit/views/TreeView/__tests__/TreeViewBase.spec.js @@ -127,46 +127,23 @@ const initWrapper = ({ MainNavigationDrawer: true, PublishSidePanel: true, SubmitToCommunityLibrarySidePanel: true, + ResubmitToCommunityLibraryModal: true, ProgressModal: true, ChannelTokenModal: true, + RemoveChannelModal: true, SyncResourcesModal: true, Clipboard: true, OfflineText: true, ContentNodeIcon: true, DraggablePlaceholder: true, - MessageDialog: true, SavingIndicator: true, QuickEditModal: true, - BaseMenu: { - name: 'BaseMenu', - template: - '', - }, }, }); }; const getShareButton = wrapper => { - const allBaseMenus = wrapper.findAllComponents({ name: 'BaseMenu' }); - for (let i = 0; i < allBaseMenus.length; i++) { - const baseMenu = allBaseMenus.at(i); - const shareButton = baseMenu.find('.share-button'); - if (shareButton.exists()) { - return shareButton; - } - } - return { exists: () => false }; -}; -const getShareMenuItems = wrapper => { - const allBaseMenus = wrapper.findAllComponents({ name: 'BaseMenu' }); - for (let i = 0; i < allBaseMenus.length; i++) { - const baseMenu = allBaseMenus.at(i); - const shareButton = baseMenu.find('.share-button'); - if (shareButton.exists()) { - return baseMenu.findAll('.v-list__tile'); - } - } - return { length: 0, wrappers: [] }; + return wrapper.find('.share-button'); }; describe('TreeViewBase', () => { @@ -305,11 +282,10 @@ describe('TreeViewBase', () => { createChannel({ published: true, public: false }); const wrapper = initWrapper({ getters }); - const menuItems = getShareMenuItems(wrapper); - const submitItem = menuItems.wrappers.find(item => - item.text().includes('Submit to community library'), - ); + const menuOptions = wrapper.vm.shareMenuOptions; + const submitItem = menuOptions.find(item => item.value === 'submit-to-library'); expect(submitItem).toBeDefined(); + expect(submitItem.label).toContain('Submit to community library'); }); it('hides submit to community library when user cannot submit', () => { @@ -319,10 +295,8 @@ describe('TreeViewBase', () => { createChannel({ published: true, public: false }); const wrapper = initWrapper({ getters }); - const menuItems = getShareMenuItems(wrapper); - const submitItem = menuItems.wrappers.find(item => - item.text().includes('Submit to community library'), - ); + const menuOptions = wrapper.vm.shareMenuOptions; + const submitItem = menuOptions.find(item => item.value === 'submit-to-library'); expect(submitItem).toBeUndefined(); }); @@ -333,10 +307,8 @@ describe('TreeViewBase', () => { createChannel({ published: true, public: true }); const wrapper = initWrapper({ getters }); - const menuItems = getShareMenuItems(wrapper); - const submitItem = menuItems.wrappers.find(item => - item.text().includes('Submit to community library'), - ); + const menuOptions = wrapper.vm.shareMenuOptions; + const submitItem = menuOptions.find(item => item.value === 'submit-to-library'); expect(submitItem).toBeUndefined(); }); @@ -346,11 +318,10 @@ describe('TreeViewBase', () => { getters.currentChannel.currentChannel = () => createChannel({ published: false }); const wrapper = initWrapper({ getters }); - const menuItems = getShareMenuItems(wrapper); - const inviteItem = menuItems.wrappers.find(item => - item.text().includes('Invite collaborators'), - ); + const menuOptions = wrapper.vm.shareMenuOptions; + const inviteItem = menuOptions.find(item => item.value === 'invite-collaborators'); expect(inviteItem).toBeDefined(); + expect(inviteItem.label).toContain('Invite collaborators'); }); it('hides invite collaborators when user cannot manage', () => { @@ -359,10 +330,8 @@ describe('TreeViewBase', () => { getters.currentChannel.currentChannel = () => createChannel({ published: true }); const wrapper = initWrapper({ getters }); - const menuItems = getShareMenuItems(wrapper); - const inviteItem = menuItems.wrappers.find(item => - item.text().includes('Invite collaborators'), - ); + const menuOptions = wrapper.vm.shareMenuOptions; + const inviteItem = menuOptions.find(item => item.value === 'invite-collaborators'); expect(inviteItem).toBeUndefined(); }); @@ -372,9 +341,10 @@ describe('TreeViewBase', () => { getters.currentChannel.currentChannel = () => createChannel({ published: true }); const wrapper = initWrapper({ getters }); - const menuItems = getShareMenuItems(wrapper); - const tokenItem = menuItems.wrappers.find(item => item.text().includes('Share token')); + const menuOptions = wrapper.vm.shareMenuOptions; + const tokenItem = menuOptions.find(item => item.value === 'share-token'); expect(tokenItem).toBeDefined(); + expect(tokenItem.label).toContain('Share token'); }); it('hides share token when channel is not published', () => { @@ -383,8 +353,8 @@ describe('TreeViewBase', () => { getters.currentChannel.currentChannel = () => createChannel({ published: false }); const wrapper = initWrapper({ getters }); - const menuItems = getShareMenuItems(wrapper); - const tokenItem = menuItems.wrappers.find(item => item.text().includes('Share token')); + const menuOptions = wrapper.vm.shareMenuOptions; + const tokenItem = menuOptions.find(item => item.value === 'share-token'); expect(tokenItem).toBeUndefined(); }); @@ -395,15 +365,11 @@ describe('TreeViewBase', () => { createChannel({ published: true, public: false }); const wrapper = initWrapper({ getters }); - const menuItems = getShareMenuItems(wrapper); - expect(menuItems.length).toBe(3); - expect( - menuItems.wrappers.some(item => item.text().includes('Submit to community library')), - ).toBe(true); - expect(menuItems.wrappers.some(item => item.text().includes('Invite collaborators'))).toBe( - true, - ); - expect(menuItems.wrappers.some(item => item.text().includes('Share token'))).toBe(true); + const menuOptions = wrapper.vm.shareMenuOptions; + expect(menuOptions.length).toBe(3); + expect(menuOptions.some(item => item.value === 'submit-to-library')).toBe(true); + expect(menuOptions.some(item => item.value === 'invite-collaborators')).toBe(true); + expect(menuOptions.some(item => item.value === 'share-token')).toBe(true); }); }); });