Skip to content

Commit

Permalink
Merge pull request #11397 from rtibbles/bo_select_all
Browse files Browse the repository at this point in the history
Fix selection behaviour on the My Downloads page
  • Loading branch information
marcellamaki authored Oct 17, 2023
2 parents 1166d08 + 98a8ca9 commit ad308de
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 158 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -147,11 +147,21 @@ export default function useDownloadRequests(store) {
return Promise.resolve();
}

function removeDownloadRequest(contentRequest) {
function removeDownloadRequest(contentNodeId) {
const contentRequest = downloadRequestMap[contentNodeId];
if (!contentRequest) {
return Promise.resolve();
}
ContentRequestResource.deleteModel({
id: contentRequest.id,
});
Vue.delete(downloadRequestMap, contentRequest.contentnode_id);
store.commit('CORE_CREATE_SNACKBAR', {
text: downloadRequestsTranslator.$tr('resourceRemoved'),
backdrop: false,
forceReuse: true,
autoDismiss: true,
});
return Promise.resolve();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,101 +8,28 @@
:totalPageNumber="totalPageNumber"
:numFilteredItems="downloadItemListLength"
>
<CoreTable v-if="windowIsLarge">
<CoreTable>
<template #headers>
<th>
<KCheckbox
showLabel
class="select-all"
:label="coreString('nameLabel')"
:checked="areAllSelected"
:indeterminate="areAnySelected && !areAllSelected"
:disabled="!areAnyAvailable"
:style="{ color: $themeTokens.annotation }"
@change="selectAll($event)"
/>
</th>
<th> {{ coreString('fileSize') }} </th>
<th> {{ coreString('dateAdded') }} </th>
<th> {{ coreString('statusLabel') }} </th>
</template>
<template #tbody>
<tbody v-if="!loading">
<tr
v-for="download in paginatedDownloads"
:key="download.contentnode_id"
:style="download.status !== 'COMPLETED' ? { color: $themeTokens.annotation } : {}"
>
<td>
<KCheckbox
:checked="resourceIsSelected(download)"
class="download-checkbox"
@change="handleCheckResource(download, $event)"
>
<KLabeledIcon
v-if="download.metadata"
:icon="getIcon(download.metadata.learning_activities)"
:label="download.metadata.title"
:style="nonCompleteStatus(download) ? { color: $themeTokens.annotation } : {}"
/>
</KCheckbox>
</td>
<td>
{{ formattedResourceSize(download) }}
</td>
<td>
{{ formatDownloadRequestedDate(download) }}
</td>
<td>
<KIcon
v-if="download.status !== 'IN_PROGRESS'"
:icon="downloadStatusIcon(download)"
:color="download.status === 'PENDING' ? $themeTokens.annotation : null"
class="icon"
/>
<KCircularLoader
v-if="download.status === 'IN_PROGRESS'"
class="icon"
/>
<span class="status-text">{{ formattedDownloadStatus(download) }} </span>
</td>
<td class="resource-action">
<KButton
v-if="nonCompleteStatus(download)"
:text="coreString('viewAction')"
appearance="flat-button"
:disabled="true"
/>
<KExternalLink
v-else
:text="coreString('viewAction')"
appearance="flat-button"
:href="genExternalContentURLBackLinkCurrentPage(download.contentnode_id)"
/>
</td>
<td class="resource-action">
<KButton
:text="coreString('removeAction')"
appearance="flat-button"
@click="markSingleResourceForRemoval(download)"
/>
</td>
</tr>
</tbody>
</template>
</CoreTable>
<!-- for small and medium screens, reorganize the table -->
<CoreTable v-else>
<template #headers>
<th>
<KCheckbox
showLabel
class="select-all"
:label="coreString('nameLabel')"
:checked="areAllSelected"
:disabled="!areAnyAvailable"
:style="{ color: $themeTokens.annotation }"
@change="selectAll($event)"
/>
<th v-if="windowIsLarge">
{{ coreString('fileSize') }}
</th>
<th v-if="windowIsLarge">
{{ coreString('dateAdded') }}
</th>
<th v-if="windowIsLarge">
{{ coreString('statusLabel') }}
</th>
</template>
<template #tbody>
Expand All @@ -112,11 +39,11 @@
:key="download.contentnode_id"
:style="download.status !== 'COMPLETED' ? { color: $themeTokens.annotation } : {}"
>
<td class="small-resource-details">
<td :class="{ 'small-resource-details': !windowIsLarge }">
<KCheckbox
:checked="resourceIsSelected(download)"
:checked="Boolean(selectedDownloadsMap[download.contentnode_id])"
class="download-checkbox"
@change="handleCheckResource(download, $event)"
@change="handleCheckResource(download.contentnode_id, $event)"
>
<KLabeledIcon
v-if="download.metadata"
Expand All @@ -125,9 +52,9 @@
:style="nonCompleteStatus(download) ? { color: $themeTokens.annotation } : {}"
/>
</KCheckbox>
<div class="small-screen-status">
<div v-if="!windowIsLarge" class="small-screen-status">
<p>
{{ formattedResourceSize(download) }} |
{{ formattedResourceSize(download) }} &nbsp;&nbsp;
{{ formatDownloadRequestedDate(download) }}
</p>
<KIcon
Expand All @@ -142,7 +69,25 @@
/>
<span class="status-text">{{ formattedDownloadStatus(download) }} </span>
</div>

</td>
<td v-if="windowIsLarge">
{{ formattedResourceSize(download) }}
</td>
<td v-if="windowIsLarge">
{{ formatDownloadRequestedDate(download) }}
</td>
<td v-if="windowIsLarge">
<KIcon
v-if="download.status !== 'IN_PROGRESS'"
:icon="downloadStatusIcon(download)"
:color="download.status === 'PENDING' ? $themeTokens.annotation : null"
class="icon"
/>
<KCircularLoader
v-if="download.status === 'IN_PROGRESS'"
class="icon"
/>
<span class="status-text">{{ formattedDownloadStatus(download) }} </span>
</td>
<td class="resource-action">
<KButton
Expand Down Expand Up @@ -172,9 +117,9 @@
</p>
</PaginatedListContainerWithBackend>
<SelectionBottomBar
:count="selectedDownloads.length"
:size="formattedSelectedSize()"
@click-remove="resourcesToDelete = selectedDownloads"
:count="Object.keys(selectedDownloadsMap).length"
:size="formattedSelectedSize"
@click-remove="removeSelectedResources"
/>
<ConfirmationDeleteModal
v-if="resourcesToDelete.length"
Expand Down Expand Up @@ -251,8 +196,7 @@
data() {
return {
now: now(),
selectedDownloadsSize: 0,
selectedDownloads: [],
selectedDownloadsMap: {},
resourcesToDelete: [],
};
},
Expand Down Expand Up @@ -295,42 +239,28 @@
}
return true;
});
if (sort) {
switch (sort) {
case 'newest':
downloadsToDisplay.sort(
(a, b) => new Date(b.requested_at) - new Date(a.requested_at)
);
break;
case 'oldest':
downloadsToDisplay.sort(
(a, b) => new Date(a.requested_at) - new Date(b.requested_at)
);
break;
case 'smallest':
downloadsToDisplay.sort((a, b) => a.metadata.file_size - b.metadata.file_size);
break;
case 'largest':
downloadsToDisplay.sort((a, b) => b.metadata.file_size - a.metadata.file_size);
break;
default:
break;
downloadsToDisplay.sort((a, b) => {
if (sort === 'oldest') {
return new Date(a.requested_at) - new Date(b.requested_at);
}
} else {
// if no sort value, default to newest downloads shown first in the UI
downloadsToDisplay.sort((a, b) => new Date(b.requested_at) - new Date(a.requested_at));
}
if (sort === 'smallest') {
return a.metadata.file_size - b.metadata.file_size;
}
if (sort === 'largest') {
return b.metadata.file_size - a.metadata.file_size;
}
// By default always sort by newest.
return new Date(b.requested_at) - new Date(a.requested_at);
});
return downloadsToDisplay;
},
paginatedDownloads() {
if (this.downloads && this.downloads.length > 0) {
const startIndex = (this.currentPage - 1) * this.itemsPerPage;
const endIndex = startIndex + this.itemsPerPage;
return this.downloads.slice(startIndex, endIndex);
} else {
return [];
}
return [];
},
downloadItemListLength() {
return this.downloads ? this.downloads.length : 0;
Expand All @@ -343,58 +273,56 @@
},
areAllSelected() {
return (
this.downloads &&
this.downloads.filter(id => this.selectedDownloads.includes(id)).length > 0
this.areAnySelected &&
this.paginatedDownloads.every(download =>
Boolean(this.selectedDownloadsMap[download.contentnode_id])
)
);
},
areAnySelected() {
return this.paginatedDownloads.some(download =>
Boolean(this.selectedDownloadsMap[download.contentnode_id])
);
},
areAnyAvailable() {
return this.downloads && this.downloads.length > 0;
return this.paginatedDownloads.length > 0;
},
},
watch: {
selectedDownloads(newVal) {
this.selectedDownloadsSize = newVal.reduce(
(acc, object) => acc + object.metadata.file_size,
0
formattedSelectedSize() {
return bytesForHumans(
Object.keys(this.selectedDownloadsMap).reduce((acc, contentnode_id) => {
return acc + (this.downloadRequestMap[contentnode_id]?.metadata?.file_size || 0);
}, 0)
);
},
},
mounted() {
this.areAnyAvailable;
},
methods: {
nonCompleteStatus(download) {
return download.status !== 'COMPLETED';
},
selectAll() {
if (this.areAllSelected) {
this.selectedDownloads = this.selectedDownloads.filter(
download => !this.paginatedDownloads.includes(download)
);
} else {
this.selectedDownloads = this.selectedDownloads.concat(
this.paginatedDownloads.filter(download => !this.selectedDownloads.includes(download))
);
const notAllSelected = !this.areAllSelected;
for (const download of this.paginatedDownloads) {
this.handleCheckResource(download.contentnode_id, notAllSelected);
}
},
handleCheckResource(id, checked) {
handleCheckResource(contentnode_id, checked) {
if (checked) {
this.selectedDownloads = this.selectedDownloads.concat(id);
return;
this.$set(this.selectedDownloadsMap, contentnode_id, checked);
} else {
this.$delete(this.selectedDownloadsMap, contentnode_id);
}
this.selectedDownloads = this.selectedDownloads.filter(resourceId => resourceId !== id);
},
resourceIsSelected(id) {
return this.selectedDownloads.indexOf(id) !== -1;
},
markSingleResourceForRemoval(download) {
this.resourcesToDelete.push(download);
this.resourcesToDelete.push(download.contentnode_id);
},
removeSelectedResources() {
this.resourcesToDelete = Object.keys(this.selectedDownloadsMap);
},
emitCurrentlySelectedResourcesForRemoval() {
this.$emit('removeResources', this.resourcesToDelete);
this.resourcesToDelete = [];
this.$nextTick(() => {
this.selectedDownloads = [];
this.selectedDownloadsMap = {};
if (this.paginatedDownloads.length == 0 && this.$route.query.page) {
const prevPage = this.currentPage - 1;
this.currentPage = prevPage;
Expand Down Expand Up @@ -463,9 +391,6 @@
return bytesForHumans(download.metadata.file_size);
}
},
formattedSelectedSize() {
return bytesForHumans(this.selectedDownloadsSize);
},
},
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,9 @@
return bytesForHumans(0);
}
},
removeResources(resources) {
for (const resource of resources) {
this.removeDownloadRequest(resource);
removeResources(contentNodeIds) {
for (const contentNodeId of contentNodeIds) {
this.removeDownloadRequest(contentNodeId);
}
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@
this.disableRequestButtons = false;
},
confirmRemoveRequest() {
this.removeDownloadRequest(this.contentNode).then(() => {
this.removeDownloadRequest(this.contentNode.id).then(() => {
this.removeConfirmationModalOpen = false;
});
},
Expand Down

0 comments on commit ad308de

Please sign in to comment.