Browse Source

feat(admin-ui): Improve multi-selection in Asset gallery component

Relates to #380. This commit introduces the ability to shift-click to select a range of assets
Michael Bromley 5 years ago
parent
commit
a4e132ac96

+ 19 - 25
packages/admin-ui/src/lib/core/src/shared/components/asset-gallery/asset-gallery.component.html

@@ -7,7 +7,7 @@
     >
         <div class="card-img">
             <div class="selected-checkbox"><clr-icon shape="check-circle" size="32"></clr-icon></div>
-            <img [src]="asset | assetPreview:'thumb'" />
+            <img [src]="asset | assetPreview: 'thumb'" />
         </div>
         <div class="detail">
             <vdr-entity-info
@@ -34,20 +34,20 @@
         </div>
         <div class="card-block details" *ngIf="selection.length >= 1">
             <div class="name">{{ lastSelected().name }}</div>
-            <div>
-                {{ 'asset.original-asset-size' | translate }}: {{ lastSelected().fileSize | filesize }}
-            </div>
-            <div>
-                <button (click)="previewAsset(lastSelected())" class="btn btn-link">
-                    <clr-icon shape="eye"></clr-icon> {{ 'asset.preview' | translate }}
-                </button>
-            </div>
-            <div>
-                <a [routerLink]="['./', lastSelected().id]" class="btn btn-link">
-                    <clr-icon shape="pencil"></clr-icon> {{ 'common.edit' | translate }}
-                </a>
-            </div>
-            <div *ngIf="selection.length === 1 && canDelete">
+            <div>{{ 'asset.original-asset-size' | translate }}: {{ lastSelected().fileSize | filesize }}</div>
+            <ng-container *ngIf="selection.length === 1">
+                <div>
+                    <button (click)="previewAsset(lastSelected())" class="btn btn-link">
+                        <clr-icon shape="eye"></clr-icon> {{ 'asset.preview' | translate }}
+                    </button>
+                </div>
+                <div>
+                    <a [routerLink]="['./', lastSelected().id]" class="btn btn-link">
+                        <clr-icon shape="pencil"></clr-icon> {{ 'common.edit' | translate }}
+                    </a>
+                </div>
+            </ng-container>
+            <div *ngIf="canDelete">
                 <button (click)="deleteAsset.emit(lastSelected())" class="btn btn-link">
                     <clr-icon shape="trash" class="is-danger"></clr-icon> {{ 'common.delete' | translate }}
                 </button>
@@ -56,15 +56,9 @@
     </div>
     <div class="card stack" [class.visible]="selection.length > 1"></div>
     <div class="selection-count" [class.visible]="selection.length > 1">
-        <clr-tooltip>
-            <div clrTooltipTrigger class="trigger">
-                {{ 'asset.assets-selected-count' | translate: { count: selection.length } }}
-            </div>
-            <clr-tooltip-content vdrPosition="top-left" clrSize="lg">
-                <ul>
-                    <li *ngFor="let asset of selection">{{ asset.name }}</li>
-                </ul>
-            </clr-tooltip-content>
-        </clr-tooltip>
+        {{ 'asset.assets-selected-count' | translate: { count: selection.length } }}
+        <ul>
+            <li *ngFor="let asset of selection">{{ asset.name }}</li>
+        </ul>
     </div>
 </div>

+ 11 - 7
packages/admin-ui/src/lib/core/src/shared/components/asset-gallery/asset-gallery.component.scss

@@ -1,4 +1,4 @@
-@import "variables";
+@import 'variables';
 
 :host {
     display: flex;
@@ -36,7 +36,7 @@
     border-radius: 50%;
     top: -12px;
     left: -12px;
-    box-shadow: 0px 5px 5px -4px rgba(0,0,0,0.75);
+    box-shadow: 0px 5px 5px -4px rgba(0, 0, 0, 0.75);
     transition: opacity 0.1s;
 }
 
@@ -87,19 +87,23 @@
 
     .selection-count {
         opacity: 0;
+        position: relative;
         text-align: center;
         visibility: hidden;
         transition: opacity 0.3s, visibility 0s 0.3s;
-        .trigger {
-            cursor: pointer;
-            color: $color-grey-400;
-            text-decoration: underline;
-        }
         &.visible {
             opacity: 1;
             visibility: visible;
             transition: opacity 0.3s, visibility 0s;
         }
+        ul {
+            text-align: left;
+            list-style-type: none;
+            margin-left: 12px;
+            li {
+                font-size: 12px;
+            }
+        }
     }
 
     .placeholder {

+ 11 - 2
packages/admin-ui/src/lib/core/src/shared/components/asset-gallery/asset-gallery.component.ts

@@ -38,8 +38,17 @@ export class AssetGalleryComponent implements OnChanges {
 
     toggleSelection(event: MouseEvent, asset: Asset) {
         const index = this.selection.findIndex((a) => a.id === asset.id);
-        if (index === -1) {
-            if (this.multiSelect && event.ctrlKey) {
+        if (this.multiSelect && event.shiftKey && 1 <= this.selection.length) {
+            const lastSelection = this.selection[this.selection.length - 1];
+            const lastSelectionIndex = this.assets.findIndex((a) => a.id === lastSelection.id);
+            const currentIndex = this.assets.findIndex((a) => a.id === asset.id);
+            const start = currentIndex < lastSelectionIndex ? currentIndex : lastSelectionIndex;
+            const end = currentIndex > lastSelectionIndex ? currentIndex + 1 : lastSelectionIndex;
+            this.selection.push(
+                ...this.assets.slice(start, end).filter((a) => !this.selection.find((s) => s.id === a.id)),
+            );
+        } else if (index === -1) {
+            if (this.multiSelect && (event.ctrlKey || event.shiftKey)) {
                 this.selection.push(asset);
             } else {
                 this.selection = [asset];