+
drag_indicator
-
+
{{ i + 1 }}.
{{ item.getTitle() }}
-
+
+
+
0">
+ {{ multiSelectedIndex.length }} items selected
+
+
diff --git a/client/src/app/shared/components/sorting-list/sorting-list.component.ts b/client/src/app/shared/components/sorting-list/sorting-list.component.ts
index 7753d4036..8011cb1ae 100644
--- a/client/src/app/shared/components/sorting-list/sorting-list.component.ts
+++ b/client/src/app/shared/components/sorting-list/sorting-list.component.ts
@@ -36,6 +36,12 @@ export class SortingListComponent implements OnInit, OnDestroy {
*/
public array: Selectable[];
+ /**
+ * The index of multiple selected elements. Allows for multiple items to be
+ * selected and then moved
+ */
+ public multiSelectedIndex: number[] = [];
+
/**
* Declare the templateRef to coexist between parent in child
*/
@@ -143,12 +149,79 @@ export class SortingListComponent implements OnInit, OnDestroy {
}
}
+ /**
+ * Handles the start of a dragDrop event and clears multiSelect if the ittem dragged
+ * is not part of the selected items
+ */
+ public dragStarted(index: number): void {
+ if (this.multiSelectedIndex.length && !this.multiSelectedIndex.includes(index)) {
+ this.multiSelectedIndex = [];
+ }
+ }
+
/**
* drop event
* @param event the event
*/
public drop(event: CdkDragDrop
): void {
- moveItemInArray(this.array, event.previousIndex, event.currentIndex);
+ if (this.multiSelectedIndex.length < 2) {
+ moveItemInArray(this.array, event.previousIndex, event.currentIndex);
+ } else {
+ const before: Selectable[] = [];
+ const insertions: Selectable[] = [];
+ const behind: Selectable[] = [];
+ for (let i = 0; i < this.array.length; i++) {
+ if (!this.multiSelectedIndex.includes(i)) {
+ if (i < event.currentIndex) {
+ before.push(this.array[i]);
+ } else if (i > event.currentIndex) {
+ behind.push(this.array[i]);
+ } else {
+ event.currentIndex < 1 ? behind.push(this.array[i]) : before.push(this.array[i]);
+ }
+ } else {
+ insertions.push(this.array[i]);
+ }
+ }
+ this.array = [...before, ...insertions, ...behind];
+ }
this.sortEvent.emit(this.array);
+ this.multiSelectedIndex = [];
+ }
+
+ /**
+ * Handles a click on a row. If the control key is clicked, the element is
+ * added/removed from a multiselect list /(which will be handled on
+ * dropping)
+ *
+ * @param event MouseEvent.
+ * @param indx The index of the row clicked.
+ */
+ public onItemClick(event: MouseEvent, indx: number): void {
+ if (event.ctrlKey) {
+ const ind = this.multiSelectedIndex.findIndex(i => i === indx);
+ if (ind === -1) {
+ this.multiSelectedIndex.push(indx);
+ } else {
+ this.multiSelectedIndex = this.multiSelectedIndex
+ .slice(0, ind)
+ .concat(this.multiSelectedIndex.slice(ind + 1));
+ }
+ } else {
+ // deselect all when clicking on an non-selected item
+ if (this.multiSelectedIndex.length && !this.multiSelectedIndex.includes(indx)) {
+ this.multiSelectedIndex = [];
+ }
+ }
+ }
+
+ /**
+ * Checks if the row at the given index is currently selected
+ *
+ * @param index
+ * @returns true if the item is currently selected
+ */
+ public isSelectedRow(index: number): boolean {
+ return this.multiSelectedIndex.includes(index);
}
}
diff --git a/client/src/assets/styles/global-components-style.scss b/client/src/assets/styles/global-components-style.scss
index 5c06218a8..080d4c478 100644
--- a/client/src/assets/styles/global-components-style.scss
+++ b/client/src/assets/styles/global-components-style.scss
@@ -80,6 +80,11 @@
color: mat-color($accent, default-contrast) !important;
}
+ .backgroundColorSelected {
+ background-color: rgba(0, 0, 0, 0.155);
+ color: mat-color($foreground, text) !important;
+ }
+
.backgroundColorLight {
background-color: mat-color($background, hover);
color: mat-color($foreground, text) !important;