From bd9899954d57deae374fceb0efc128b5680ab36f Mon Sep 17 00:00:00 2001 From: Alex Velez Date: Tue, 14 Mar 2023 03:54:48 -0500 Subject: [PATCH] View and remove downloads --- .../assets/src/composables/useContentLink.js | 40 ++++++++++++++++++- .../src/composables/useDownloadRequests.js | 26 +++++++----- kolibri/plugins/learn/assets/src/constants.js | 8 ++++ .../DownloadsList/ConfirmationDeleteModal.vue | 1 - .../views/DownloadsList/index.vue | 35 +++++++++++----- .../src/my_downloads/views/MyDownloads.vue | 12 ++++++ .../assets/src/views/TopicsContentPage.vue | 11 +++-- 7 files changed, 110 insertions(+), 23 deletions(-) diff --git a/kolibri/plugins/learn/assets/src/composables/useContentLink.js b/kolibri/plugins/learn/assets/src/composables/useContentLink.js index 6899ff94140..61b26a787d0 100644 --- a/kolibri/plugins/learn/assets/src/composables/useContentLink.js +++ b/kolibri/plugins/learn/assets/src/composables/useContentLink.js @@ -2,7 +2,7 @@ import { get } from '@vueuse/core'; import isEmpty from 'lodash/isEmpty'; import pick from 'lodash/pick'; import { computed, getCurrentInstance } from 'kolibri.lib.vueCompositionApi'; -import { PageNames } from '../constants'; +import { ExternalPagePaths, PageNames } from '../constants'; export default function useContentLink(store) { // Get store reference from the curent instance @@ -47,6 +47,29 @@ export default function useContentLink(store) { return _makeLink(id, isResource, query); } + function genExternalContentURLBackLinkCurrentPage(id) { + const pathname = window.location.pathname; + const learnIndex = pathname.indexOf('/learn'); + const base = pathname.slice(0, learnIndex) + '/learn/#'; + if (!route) { + return base; + } + const oldQuery = get(route).query || {}; + const query = { + prevName: get(route).name, + }; + if (!isEmpty(oldQuery)) { + query.prevQuery = encodeURI(JSON.stringify(oldQuery)); + } + const params = get(route).params; + if (!isEmpty(params)) { + query.prevParams = encodeURI(JSON.stringify(params)); + } + const path = `/topics/c/${id}`; + + return `${base}${path}?${new URLSearchParams(query)}`; + } + /** * A function to generate a VueRouter link object that links to * either a resource or a topic, and copies current query parameters @@ -90,9 +113,24 @@ export default function useContentLink(store) { }; }); + function genExternalBackURL() { + const pathname = window.location.pathname; + const learnIndex = pathname.indexOf('/learn'); + const base = pathname.slice(0, learnIndex) + '/learn'; + const backValue = get(back); + if (!backValue) { + return base; + } + const query = backValue.query ? `#/?${new URLSearchParams(backValue.query)}` : ''; + const path = ExternalPagePaths[backValue.name]; + return `${base}${path}${query}`; + } + return { genContentLinkBackLinkCurrentPage, genContentLinkKeepCurrentBackLink, + genExternalContentURLBackLinkCurrentPage, + genExternalBackURL, back, }; } diff --git a/kolibri/plugins/learn/assets/src/composables/useDownloadRequests.js b/kolibri/plugins/learn/assets/src/composables/useDownloadRequests.js index 65394e86d60..6968695cf4e 100644 --- a/kolibri/plugins/learn/assets/src/composables/useDownloadRequests.js +++ b/kolibri/plugins/learn/assets/src/composables/useDownloadRequests.js @@ -32,12 +32,11 @@ const downloadRequestMap = reactive({ export default function useDownloadRequests(store) { store = store || getCurrentInstance().proxy.$store; function fetchUserDownloadRequests(params) { - console.log('Executing fetchUserDownloadRequests', params); const { page, pageSize } = params; const loading = ref(true); const dummyDownloadRequests = [ { - id: '2ea9bda8703241be89b5b9fd87f88113', + id: '2ea9bda8703241be89b5b9fd87f88815', user_id: store.getters.currentUserId, reason: 'USER_INITIATED', facility_id: store.getters.currentFacilityId, @@ -51,18 +50,18 @@ export default function useDownloadRequests(store) { node_id: '2ea9bda8703241be89b5b9fd87f88815', }, { - id: '2ea9bda8703241be89b5b9fd87f88111', + id: '9e53d545aaf44c3787a29a34b189c56a', user_id: store.getters.currentUserId, reason: 'USER_INITIATED', facility_id: store.getters.currentFacilityId, status: 'QUEUED', date_added: new Date(), resource_metadata: { - title: 'Intro to addition 2', - file_size: 1113580, - learning_activities: ['UD5UGM0z'], + title: 'PDF 1 page', + file_size: 3113580, + learning_activities: ['wA01urpi'], }, - node_id: '2ea9bda8703241be89b5b9fd87f88817', + node_id: '9e53d545aaf44c3787a29a34b189c56a', }, ]; setTimeout(() => { @@ -90,7 +89,6 @@ export default function useDownloadRequests(store) { } function fetchDownloadsStorageInfo() { - console.log('Executing fetchDownloadsStorageInfo'); const loading = ref(true); const storageInfo = ref(null); const dummyStorageInfo = { @@ -137,7 +135,16 @@ export default function useDownloadRequests(store) { function removeDownloadRequest(content) { console.log(`requested removal of ${content.id}`); - Vue.delete(downloadRequestMap, content.id); + Vue.delete(downloadRequestMap.downloads, content.id); + return Promise.resolve(); + } + + function removeDownloadsRequest(contentList) { + console.log(`requested removal of ${contentList.length} items`); + contentList.forEach(content => { + Vue.delete(downloadRequestMap.downloads, content.id); + }); + console.log('downloadRequestMap', downloadRequestMap); return Promise.resolve(); } @@ -147,5 +154,6 @@ export default function useDownloadRequests(store) { downloadRequestMap, addDownloadRequest, removeDownloadRequest, + removeDownloadsRequest, }; } diff --git a/kolibri/plugins/learn/assets/src/constants.js b/kolibri/plugins/learn/assets/src/constants.js index 71cfea390d2..489e3fca21f 100644 --- a/kolibri/plugins/learn/assets/src/constants.js +++ b/kolibri/plugins/learn/assets/src/constants.js @@ -17,6 +17,14 @@ export const PageNames = { EXPLORE_LIBRARIES: 'EXPLORE_LIBRARIES', }; +export const ExternalPageNames = { + MY_DOWNLOADS: 'MY_DOWNLOADS', +}; + +export const ExternalPagePaths = { + [ExternalPageNames.MY_DOWNLOADS]: '/my-downloads', +}; + // switch between modes export const PageModes = { TOPICS: 'TOPICS', diff --git a/kolibri/plugins/learn/assets/src/my_downloads/views/DownloadsList/ConfirmationDeleteModal.vue b/kolibri/plugins/learn/assets/src/my_downloads/views/DownloadsList/ConfirmationDeleteModal.vue index e53652cf18e..85a2830c1e0 100644 --- a/kolibri/plugins/learn/assets/src/my_downloads/views/DownloadsList/ConfirmationDeleteModal.vue +++ b/kolibri/plugins/learn/assets/src/my_downloads/views/DownloadsList/ConfirmationDeleteModal.vue @@ -36,7 +36,6 @@ }, methods: { removeResources() { - console.log('Removing', this.resourcesToDelete); this.$emit('success'); }, }, diff --git a/kolibri/plugins/learn/assets/src/my_downloads/views/DownloadsList/index.vue b/kolibri/plugins/learn/assets/src/my_downloads/views/DownloadsList/index.vue index 77d55866a8b..e54cae72489 100644 --- a/kolibri/plugins/learn/assets/src/my_downloads/views/DownloadsList/index.vue +++ b/kolibri/plugins/learn/assets/src/my_downloads/views/DownloadsList/index.vue @@ -49,10 +49,10 @@ {{ formattedTime(download) }} - @@ -76,7 +76,7 @@ v-if="resourcesToDelete.length" :resourcesToDelete="resourcesToDelete" @cancel="resourcesToDelete = []" - @success="resourcesToDelete = []" + @success="removeResources" /> @@ -92,6 +92,7 @@ import commonCoreStrings from 'kolibri.coreVue.mixins.commonCoreStrings'; import PaginatedListContainerWithBackend from 'kolibri-common/components/PaginatedListContainerWithBackend'; import { LearningActivityToIconMap } from '../../../constants'; + import useContentLink from '../../../composables/useContentLink'; import SelectionBottomBar from './SelectionBottomBar.vue'; import ConfirmationDeleteModal from './ConfirmationDeleteModal.vue'; @@ -104,6 +105,13 @@ PaginatedListContainerWithBackend, }, mixins: [commonCoreStrings], + setup() { + const { genExternalContentURLBackLinkCurrentPage } = useContentLink(); + + return { + genExternalContentURLBackLinkCurrentPage, + }; + }, props: { downloads: { type: Object, @@ -162,14 +170,20 @@ }, watch: { selectedDownloads(newVal, oldVal) { + if (newVal.length === 0) { + this.selectedDownloadsSize = 0; + return; + } const addedDownloads = newVal.filter(id => !oldVal.includes(id)); const removedDownloads = oldVal.filter(id => !newVal.includes(id)); const addedDownloadsSize = addedDownloads.reduce( - (acc, id) => acc + this.downloads[id].resource_metadata.file_size, + (acc, id) => + acc + (this.downloads[id] ? this.downloads[id].resource_metadata.file_size : 0), 0 ); const removedDownloadsSize = removedDownloads.reduce( - (acc, id) => acc + this.downloads[id].resource_metadata.file_size, + (acc, id) => + acc + (this.downloads[id] ? this.downloads[id].resource_metadata.file_size : 0), 0 ); this.selectedDownloadsSize += addedDownloadsSize - removedDownloadsSize; @@ -197,13 +211,16 @@ resourceIsSelected(id) { return this.selectedDownloads.indexOf(id) !== -1; }, - viewResource(id) { - window.location.replace('/en/learn/#/topics/c/1c5a63eb626f4aa883eaef0cfe37634f'); - console.log('view resource', id); - }, removeResource(id) { this.resourcesToDelete = [id]; }, + removeResources() { + this.$emit('removeResources', this.resourcesToDelete); + this.selectedDownloads = this.selectedDownloads.filter( + resourceId => !this.resourcesToDelete.includes(resourceId) + ); + this.resourcesToDelete = []; + }, getIcon(download) { return LearningActivityToIconMap[download.resource_metadata.learning_activities[0]]; }, diff --git a/kolibri/plugins/learn/assets/src/my_downloads/views/MyDownloads.vue b/kolibri/plugins/learn/assets/src/my_downloads/views/MyDownloads.vue index d6fa57c5536..1806d9c2ea5 100644 --- a/kolibri/plugins/learn/assets/src/my_downloads/views/MyDownloads.vue +++ b/kolibri/plugins/learn/assets/src/my_downloads/views/MyDownloads.vue @@ -50,6 +50,7 @@ :downloads="downloads || {}" :totalDownloads="totalDownloads" :totalPageNumber="totalPageNumber" + @removeResources="removeResources" /> @@ -84,6 +85,8 @@ downloadRequestMap, fetchUserDownloadRequests, fetchDownloadsStorageInfo, + removeDownloadRequest, + removeDownloadsRequest, } = useDownloadRequests(); const store = getCurrentInstance().proxy.$store; @@ -134,12 +137,21 @@ totalPageNumber, storage, storageLoading, + removeDownloadRequest, + removeDownloadsRequest, }; }, methods: { formattedSize(size) { return bytesForHumans(size); }, + removeResources(resources) { + if (resources.length === 1) { + this.removeDownloadRequest({ id: resources[0] }); + } else { + this.removeDownloadsRequest(resources.map(resource => ({ id: resource }))); + } + }, }, }; diff --git a/kolibri/plugins/learn/assets/src/views/TopicsContentPage.vue b/kolibri/plugins/learn/assets/src/views/TopicsContentPage.vue index 1c87dfc2317..aff32481847 100644 --- a/kolibri/plugins/learn/assets/src/views/TopicsContentPage.vue +++ b/kolibri/plugins/learn/assets/src/views/TopicsContentPage.vue @@ -151,6 +151,7 @@ import urls from 'kolibri.urls'; import AppError from 'kolibri-common/components/AppError'; import GlobalSnackbar from 'kolibri-common/components/GlobalSnackbar'; + import { PageNames } from '../constants'; import SkipNavigationLink from '../../../../../../kolibri/core/assets/src/views/SkipNavigationLink'; import useContentLink from '../composables/useContentLink'; import useCoreLearn from '../composables/useCoreLearn'; @@ -204,7 +205,7 @@ contentNodeProgressMap, } = useContentNodeProgress(); const { fetchLesson } = useLearnerResources(); - const { back } = useContentLink(); + const { back, genExternalBackURL } = useContentLink(); const { baseurl } = useDevices(); return { baseurl, @@ -214,6 +215,7 @@ fetchContentNodeTreeProgress, fetchLesson, back, + genExternalBackURL, }; }, props: { @@ -432,8 +434,11 @@ }); }, navigateBack() { - window.location.replace('/en/learn/my-downloads'); - // this.$router.push(this.back); + if (PageNames[this.back.name]) { + this.$router.push(this.back); + } else { + window.location.replace(this.genExternalBackURL()); + } }, openSidePanel() { this.sidePanelContent = this.content;