Browse Source

feat(admin-ui): Add asset preview dialog

Michael Bromley 6 years ago
parent
commit
34413ce569

+ 3 - 0
admin-ui/src/app/catalog/catalog.module.ts

@@ -10,6 +10,7 @@ import { AssetFileInputComponent } from './components/asset-file-input/asset-fil
 import { AssetGalleryComponent } from './components/asset-gallery/asset-gallery.component';
 import { AssetListComponent } from './components/asset-list/asset-list.component';
 import { AssetPickerDialogComponent } from './components/asset-picker-dialog/asset-picker-dialog.component';
+import { AssetPreviewComponent } from './components/asset-preview/asset-preview.component';
 import { CollectionContentsComponent } from './components/collection-contents/collection-contents.component';
 import { CollectionDetailComponent } from './components/collection-detail/collection-detail.component';
 import { CollectionListComponent } from './components/collection-list/collection-list.component';
@@ -61,12 +62,14 @@ import { ProductResolver } from './providers/routing/product-resolver';
         CollectionTreeNodeComponent,
         CollectionContentsComponent,
         ProductVariantsTableComponent,
+        AssetPreviewComponent,
     ],
     entryComponents: [
         AssetPickerDialogComponent,
         CreateOptionGroupDialogComponent,
         SelectOptionGroupDialogComponent,
         ApplyFacetDialogComponent,
+        AssetPreviewComponent,
     ],
     providers: [ProductResolver, FacetResolver, CollectionResolver],
 })

+ 6 - 1
admin-ui/src/app/catalog/components/asset-gallery/asset-gallery.component.html

@@ -31,7 +31,12 @@
                 {{ 'catalog.original-asset-size' | translate }}: {{ lastSelected().fileSize | filesize }}
             </div>
             <div>
-                <a [href]="lastSelected().source" target="_blank">
+                <button (click)="previewAsset(lastSelected())" class="btn btn-link">
+                    {{ 'catalog.preview' | translate }}
+                </button>
+            </div>
+            <div>
+                <a [href]="lastSelected().source" target="_blank" class="btn btn-link">
                     {{ 'catalog.open-asset-source' | translate }}
                 </a>
             </div>

+ 14 - 0
admin-ui/src/app/catalog/components/asset-gallery/asset-gallery.component.ts

@@ -1,6 +1,8 @@
 import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';
 
 import { Asset } from '../../../common/generated-types';
+import { ModalService } from '../../../shared/providers/modal/modal.service';
+import { AssetPreviewComponent } from '../asset-preview/asset-preview.component';
 
 @Component({
     selector: 'vdr-asset-gallery',
@@ -18,6 +20,8 @@ export class AssetGalleryComponent {
 
     selection: Asset[] = [];
 
+    constructor(private modalService: ModalService) {}
+
     toggleSelection(event: MouseEvent, asset: Asset) {
         const index = this.selection.findIndex(a => a.id === asset.id);
         if (index === -1) {
@@ -45,4 +49,14 @@ export class AssetGalleryComponent {
     lastSelected(): Asset {
         return this.selection[this.selection.length - 1];
     }
+
+    previewAsset(asset: Asset) {
+        this.modalService
+            .fromComponent(AssetPreviewComponent, {
+                size: 'xl',
+                closable: true,
+                locals: { asset },
+            })
+            .subscribe();
+    }
 }

+ 37 - 0
admin-ui/src/app/catalog/components/asset-preview/asset-preview.component.html

@@ -0,0 +1,37 @@
+<ng-template vdrDialogTitle>
+    <div class="title-row">
+        {{ asset.name }}
+    </div>
+</ng-template>
+
+<div class="preview-image" #previewDiv [class.centered]="centered">
+    <img class="" [src]="asset.preview + '?preset=' + size" #imageElement (load)="getDimensions()" />
+</div>
+
+<ng-template vdrDialogButtons>
+    <div class="controls">
+        <label>{{ 'catalog.preview-size' | translate }}:</label>
+        <vdr-form-field>
+            <select clrSelect name="options" [(ngModel)]="size">
+                <option value="tiny">tiny</option>
+                <option value="thumb">thumb</option>
+                <option value="small">small</option>
+                <option value="medium">medium</option>
+                <option value="large">large</option>
+                <option value="">full size</option>
+            </select>
+        </vdr-form-field>
+        <div class="dimension">
+            <label>{{ 'catalog.width' | translate }}:</label>
+            {{ width }}px
+        </div>
+        <div class="dimension">
+            <label>{{ 'catalog.height' | translate }}:</label>
+            {{ height }}px
+        </div>
+        <div class="flex-spacer"></div>
+        <a [href]="asset.source" target="_blank" class="btn btn-link">
+            {{ 'catalog.open-asset-source' | translate }}
+        </a>
+    </div>
+</ng-template>

+ 47 - 0
admin-ui/src/app/catalog/components/asset-preview/asset-preview.component.scss

@@ -0,0 +1,47 @@
+@import "variables";
+
+:host {
+    display: flex;
+    flex-direction: column;
+}
+
+.preview-image {
+    width: 100%;
+    height: 100%;
+    min-height: 60vh;
+    overflow: auto;
+    text-align: center;
+    box-shadow: inset 0 0 5px 0 rgba(0,0,0,0.1);
+    background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAACuoAAArqAVDM774AAAAZdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjAuMTZEaa/1AAAAK0lEQVQ4T2P4jwP8xgFGNSADqDwGIF0DlMYAUH0YYFQDMoDKYwASNfz/DwB/JvcficphowAAAABJRU5ErkJggg==");
+
+    &.centered {
+        display: flex;
+        align-items: center;
+        justify-content: center;
+    }
+
+    img {
+
+    }
+}
+
+.controls {
+    display: flex;
+    align-items: flex-end;
+    flex: 1;
+
+    label {
+        color: $color-grey-500;
+    }
+    vdr-form-field {
+        height: 40px;
+        margin-left: 6px;
+        margin-right: 24px;
+    }
+    .dimension {
+        margin: 0 6px;
+    }
+}
+.flex-spacer {
+    flex: 1;
+}

+ 29 - 0
admin-ui/src/app/catalog/components/asset-preview/asset-preview.component.ts

@@ -0,0 +1,29 @@
+import { ChangeDetectionStrategy, Component, ElementRef, ViewChild } from '@angular/core';
+
+import { Asset } from '../../../common/generated-types';
+import { Dialog } from '../../../shared/providers/modal/modal.service';
+
+@Component({
+    selector: 'vdr-asset-preview',
+    templateUrl: './asset-preview.component.html',
+    styleUrls: ['./asset-preview.component.scss'],
+    changeDetection: ChangeDetectionStrategy.Default,
+})
+export class AssetPreviewComponent implements Dialog<void> {
+    asset: Asset;
+    size = 'medium';
+    resolveWith: (result?: void) => void;
+    width = 0;
+    height = 0;
+    centered = true;
+    @ViewChild('imageElement') private imageElementRef: ElementRef<HTMLImageElement>;
+    @ViewChild('previewDiv') private previewDivRef: ElementRef<HTMLDivElement>;
+
+    getDimensions() {
+        const img = this.imageElementRef.nativeElement;
+        const container = this.previewDivRef.nativeElement;
+        this.width = img.width;
+        this.height = img.height;
+        this.centered = img.width <= container.offsetWidth && img.height <= container.offsetHeight;
+    }
+}

+ 13 - 2
admin-ui/src/app/catalog/components/product-assets/product-assets.component.html

@@ -1,7 +1,11 @@
 <div class="card" *ngIf="!compact; else compactView">
     <div class="card-img">
         <div class="featured-asset">
-            <img *ngIf="featuredAsset" [src]="featuredAsset!.preview + '?preset=small'" />
+            <img
+                *ngIf="featuredAsset"
+                [src]="featuredAsset!.preview + '?preset=small'"
+                (click)="previewAsset(featuredAsset)"
+            />
             <div class="placeholder" *ngIf="!featuredAsset">
                 <clr-icon shape="image" size="128"></clr-icon>
                 <div>{{ 'catalog.no-featured-asset' | translate }}</div>
@@ -19,7 +23,11 @@
 
 <ng-template #compactView>
     <div class="featured-asset compact">
-        <img *ngIf="featuredAsset" [src]="featuredAsset!.preview + '?preset=thumb'" />
+        <img
+            *ngIf="featuredAsset"
+            [src]="featuredAsset!.preview + '?preset=thumb'"
+            (click)="previewAsset(featuredAsset)"
+        />
 
         <div class="placeholder" *ngIf="!featuredAsset"><clr-icon shape="image" size="150"></clr-icon></div>
     </div>
@@ -48,6 +56,9 @@
                     <img [src]="asset.preview + '?preset=tiny'" />
                 </div>
                 <clr-dropdown-menu *clrIfOpen clrPosition="bottom-right">
+                    <button type="button" clrDropdownItem (click)="previewAsset(asset)">
+                        {{ 'catalog.preview' | translate }}
+                    </button>
                     <button
                         type="button"
                         [disabled]="isFeatured(asset)"

+ 1 - 0
admin-ui/src/app/catalog/components/product-assets/product-assets.component.scss

@@ -17,6 +17,7 @@
     text-align: center;
     background: $color-grey-200;
     padding: 6px;
+    cursor: pointer;
 
     &.compact {
         width: 100%;

+ 11 - 0
admin-ui/src/app/catalog/components/product-assets/product-assets.component.ts

@@ -12,6 +12,7 @@ import { unique } from 'shared/unique';
 import { Asset } from '../../../common/generated-types';
 import { ModalService } from '../../../shared/providers/modal/modal.service';
 import { AssetPickerDialogComponent } from '../asset-picker-dialog/asset-picker-dialog.component';
+import { AssetPreviewComponent } from '../asset-preview/asset-preview.component';
 
 export interface AssetChange {
     assetIds: string[];
@@ -64,6 +65,16 @@ export class ProductAssetsComponent {
         return !!this.featuredAsset && this.featuredAsset.id === asset.id;
     }
 
+    previewAsset(asset: Asset) {
+        this.modalService
+            .fromComponent(AssetPreviewComponent, {
+                size: 'xl',
+                closable: true,
+                locals: { asset },
+            })
+            .subscribe();
+    }
+
     removeAsset(asset: Asset) {
         this.assets = this.assets.filter(a => a.id !== asset.id);
         if (this.featuredAsset && this.featuredAsset.id === asset.id) {

+ 5 - 2
admin-ui/src/i18n-messages/en.json

@@ -49,6 +49,7 @@
     "generate-variants-default-only": "This product does not have options",
     "generate-variants-with-options": "This product has options",
     "group-by-product": "Group by product",
+    "height": "Height",
     "move-down": "Move down",
     "move-to": "Move to",
     "move-up": "Move up",
@@ -62,6 +63,8 @@
     "option-group-options-tooltip": "Enter each option on a new line in the default language ({ defaultLanguage })",
     "options": "Options",
     "original-asset-size": "Source size",
+    "preview": "Preview",
+    "preview-size": "Preview size",
     "price": "Price",
     "price-includes-tax-at": "Includes tax at { rate }%",
     "price-with-tax-in-default-zone": "Inc. { rate }% tax: { price }",
@@ -87,7 +90,8 @@
     "upload-assets": "Upload assets",
     "values": "Values",
     "view-contents": "View contents",
-    "visibility": "Visibility"
+    "visibility": "Visibility",
+    "width": "Width"
   },
   "common": {
     "ID": "ID",
@@ -439,7 +443,6 @@
     "read": "Read",
     "remove-countries-from-zone": "Remove countries from zone...",
     "remove-countries-from-zone-success": "Removed { countryCount } {countryCount, plural, one {country} other {countries}} from zone \"{ zoneName }\"",
-    "role": "Role",
     "roles": "Roles",
     "section": "Section",
     "select-zone": "Select zone",