diff --git a/contentcuration/contentcuration/frontend/channelEdit/components/move/MoveModal.vue b/contentcuration/contentcuration/frontend/channelEdit/components/move/MoveModal.vue index a68c50d51b..5865f28d30 100644 --- a/contentcuration/contentcuration/frontend/channelEdit/components/move/MoveModal.vue +++ b/contentcuration/contentcuration/frontend/channelEdit/components/move/MoveModal.vue @@ -98,6 +98,11 @@ +
+ + {{ showMoreLabel }} + +
{ + }).then(childrenResponse => { this.loading = false; + this.more = childrenResponse.more || null; }); } return Promise.resolve(); @@ -302,6 +321,15 @@ }); this.moveNodesInProgress = false; }, + loadMore() { + if (this.more && !this.moreLoading) { + this.moreLoading = true; + this.loadContentNodes(this.more).then(response => { + this.more = response.more || null; + this.moreLoading = false; + }); + } + }, }, $trs: { moveItems: @@ -350,4 +378,11 @@ } } + .show-more-button-container { + display: flex; + justify-content: center; + width: 100%; + margin-bottom: 10px; + } + diff --git a/contentcuration/contentcuration/frontend/channelEdit/views/ImportFromChannels/ContentTreeList.vue b/contentcuration/contentcuration/frontend/channelEdit/views/ImportFromChannels/ContentTreeList.vue index 72d046d3dd..8b2bf39ac6 100644 --- a/contentcuration/contentcuration/frontend/channelEdit/views/ImportFromChannels/ContentTreeList.vue +++ b/contentcuration/contentcuration/frontend/channelEdit/views/ImportFromChannels/ContentTreeList.vue @@ -43,6 +43,11 @@ /> +
+ + {{ showMoreLabel }} + +
@@ -55,6 +60,7 @@ import intersectionBy from 'lodash/intersectionBy'; import { mapActions, mapGetters } from 'vuex'; import find from 'lodash/find'; + import NodePanel from '../NodePanel'; import { RouteNames } from '../../constants'; import BrowsingCard from './BrowsingCard'; import Breadcrumbs from 'shared/views/Breadcrumbs'; @@ -62,6 +68,9 @@ import LoadingText from 'shared/views/LoadingText'; import { constantsTranslationMixin } from 'shared/mixins'; import { ChannelListTypes } from 'shared/constants'; + import { crossComponentTranslator } from 'shared/i18n'; + + const showMoreTranslator = crossComponentTranslator(NodePanel); export default { name: 'ContentTreeList', @@ -85,6 +94,8 @@ data() { return { loading: false, + more: null, + moreLoading: false, }; }, computed: { @@ -142,39 +153,44 @@ ...ancestorsLinks, ]; }, + showMoreLabel() { + // eslint-disable-next-line kolibri/vue-no-undefined-string-uses + return showMoreTranslator.$tr('showMore'); + }, }, watch: { - topicId(parent) { + topicId(newTopicId, oldTopicId) { + if (newTopicId !== oldTopicId && newTopicId) { + this.loadData(); + } + }, + }, + created() { + this.loadData(); + }, + methods: { + ...mapActions('contentNode', ['loadChildren', 'loadAncestors', 'loadContentNodes']), + loadData() { this.loading = true; - return this.loadChildren({ - parent, + const params = { complete: true, - }).then(() => { + }; + const channelListType = this.$route.query.channel_list || ChannelListTypes.PUBLIC; + if (channelListType === ChannelListTypes.PUBLIC) { + // TODO: load from public API instead + // TODO: challenging because of node_id->id and root_id->channel_id + params.published = true; + } + + return Promise.all([ + this.loadChildren({ parent: this.topicId, ...params }).then(childrenResponse => { + this.more = childrenResponse.more || null; + }), + this.loadAncestors({ id: this.topicId }), + ]).then(() => { this.loading = false; }); }, - }, - mounted() { - this.loading = true; - const params = { - complete: true, - }; - const channelListType = this.$route.query.channel_list || ChannelListTypes.PUBLIC; - if (channelListType === ChannelListTypes.PUBLIC) { - // TODO: load from public API instead - // TODO: challenging because of node_id->id and root_id->channel_id - params.published = true; - } - - return Promise.all([ - this.loadChildren({ parent: this.topicId, ...params }), - this.loadAncestors({ id: this.topicId }), - ]).then(() => { - this.loading = false; - }); - }, - methods: { - ...mapActions('contentNode', ['loadChildren', 'loadAncestors']), // @public scrollToNode(nodeId) { const ref = this.$refs[nodeId]; @@ -187,6 +203,15 @@ toggleSelected(node) { this.$emit('change_selected', { nodes: [node], isSelected: !this.isSelected(node) }); }, + loadMore() { + if (this.more && !this.moreLoading) { + this.moreLoading = true; + this.loadContentNodes(this.more).then(response => { + this.more = response.more || null; + this.moreLoading = false; + }); + } + }, }, $trs: { allChannelsLabel: 'Channels', diff --git a/contentcuration/contentcuration/frontend/channelEdit/views/trash/TrashModal.vue b/contentcuration/contentcuration/frontend/channelEdit/views/trash/TrashModal.vue index edbd7eea3e..a1098542b8 100644 --- a/contentcuration/contentcuration/frontend/channelEdit/views/trash/TrashModal.vue +++ b/contentcuration/contentcuration/frontend/channelEdit/views/trash/TrashModal.vue @@ -66,6 +66,11 @@ +
+ + {{ showMoreLabel }} + +
{ - this.loading = false; - }); }, methods: { ...mapActions('contentNode', [ @@ -234,6 +240,17 @@ 'loadContentNodes', 'loadAncestors', ]), + loadNodes() { + this.loading = true; + if (!this.trashId) { + this.loading = false; + return; + } + this.loadChildren({ parent: this.trashId }).then(childrenResponse => { + this.loading = false; + this.more = childrenResponse.more || null; + }); + }, moveNodes(target) { return this.moveContentNodes({ id__in: this.selected, @@ -242,6 +259,8 @@ }).then(() => { this.reset(); this.$refs.moveModal && this.$refs.moveModal.moveComplete(); + // Reload after this to ensure that anything over the pagination fold is loaded now + this.loadNodes(); }); }, reset() { @@ -254,6 +273,8 @@ this.showConfirmationDialog = false; this.reset(); this.$store.dispatch('showSnackbar', { text }); + // Reload after this to ensure that anything over the pagination fold is loaded now + this.loadNodes(); }); }, toggleSelectAll(selectAll) { @@ -262,6 +283,15 @@ getItemBackground(id) { return this.previewNodeId === id ? this.$vuetify.theme.greyBackground : 'transparent'; }, + loadMore() { + if (this.more && !this.moreLoading) { + this.moreLoading = true; + this.loadContentNodes(this.more).then(response => { + this.more = response.more || null; + this.moreLoading = false; + }); + } + }, }, $trs: { trashModalTitle: 'Trash', @@ -283,4 +313,10 @@ diff --git a/contentcuration/contentcuration/frontend/channelEdit/views/trash/__tests__/trashModal.spec.js b/contentcuration/contentcuration/frontend/channelEdit/views/trash/__tests__/trashModal.spec.js index fd75caa234..4d4db70575 100644 --- a/contentcuration/contentcuration/frontend/channelEdit/views/trash/__tests__/trashModal.spec.js +++ b/contentcuration/contentcuration/frontend/channelEdit/views/trash/__tests__/trashModal.spec.js @@ -55,7 +55,7 @@ function makeWrapper(items) { methods: { loadContentNodes: jest.fn(), loadAncestors: jest.fn(), - loadChildren: jest.fn(() => Promise.resolve()), + loadChildren: jest.fn(() => Promise.resolve({ more: null, results: [] })), }, stubs: { ResourceDrawer: true,