Skip to content

Commit

Permalink
feat(admin-ui): Asset names can be updated
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelbromley committed Feb 12, 2020
1 parent 7c114fd commit fcb4f3d
Show file tree
Hide file tree
Showing 12 changed files with 198 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@
</div>
<vdr-dropdown-menu vdrPosition="bottom-right">
<button type="button" vdrDropdownItem (click)="previewAsset(asset)">
{{ 'catalog.preview' | translate }}
{{ 'asset.preview' | translate }}
</button>
<button
type="button"
Expand Down
18 changes: 17 additions & 1 deletion packages/admin-ui/src/app/common/generated-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1709,6 +1709,7 @@ export type Mutation = {
assignRoleToAdministrator: Administrator,
/** Create a new Asset */
createAssets: Array<Asset>,
/** Update an existing Asset */
updateAsset: Asset,
login: LoginResult,
logout: Scalars['Boolean'],
Expand Down Expand Up @@ -2791,7 +2792,9 @@ export type Query = {
__typename?: 'Query',
administrators: AdministratorList,
administrator?: Maybe<Administrator>,
/** Get a list of Assets */
assets: AssetList,
/** Get a single Asset by id */
asset?: Maybe<Asset>,
me?: Maybe<CurrentUser>,
channels: Array<Channel>,
Expand Down Expand Up @@ -4027,7 +4030,7 @@ export type AddNoteToOrderMutationVariables = {

export type AddNoteToOrderMutation = ({ __typename?: 'Mutation' } & { addNoteToOrder: ({ __typename?: 'Order' } & Pick<Order, 'id'>) });

export type AssetFragment = ({ __typename?: 'Asset' } & Pick<Asset, 'id' | 'createdAt' | 'updatedAt' | 'name' | 'fileSize' | 'mimeType' | 'type' | 'preview' | 'source'>);
export type AssetFragment = ({ __typename?: 'Asset' } & Pick<Asset, 'id' | 'createdAt' | 'updatedAt' | 'name' | 'fileSize' | 'mimeType' | 'type' | 'preview' | 'source' | 'width' | 'height'>);

export type ProductVariantFragment = ({ __typename?: 'ProductVariant' } & Pick<ProductVariant, 'id' | 'createdAt' | 'updatedAt' | 'enabled' | 'languageCode' | 'name' | 'price' | 'currencyCode' | 'priceIncludesTax' | 'priceWithTax' | 'stockOnHand' | 'trackInventory' | 'sku'> & { taxRateApplied: ({ __typename?: 'TaxRate' } & Pick<TaxRate, 'id' | 'name' | 'value'>), taxCategory: ({ __typename?: 'TaxCategory' } & Pick<TaxCategory, 'id' | 'name'>), options: Array<({ __typename?: 'ProductOption' } & Pick<ProductOption, 'id' | 'code' | 'languageCode' | 'name' | 'groupId'> & { translations: Array<({ __typename?: 'ProductOptionTranslation' } & Pick<ProductOptionTranslation, 'id' | 'languageCode' | 'name'>)> })>, facetValues: Array<({ __typename?: 'FacetValue' } & Pick<FacetValue, 'id' | 'code' | 'name'> & { facet: ({ __typename?: 'Facet' } & Pick<Facet, 'id' | 'name'>) })>, featuredAsset: Maybe<({ __typename?: 'Asset' } & AssetFragment)>, assets: Array<({ __typename?: 'Asset' } & AssetFragment)>, translations: Array<({ __typename?: 'ProductVariantTranslation' } & Pick<ProductVariantTranslation, 'id' | 'languageCode' | 'name'>)> });

Expand Down Expand Up @@ -4142,6 +4145,13 @@ export type CreateAssetsMutationVariables = {

export type CreateAssetsMutation = ({ __typename?: 'Mutation' } & { createAssets: Array<({ __typename?: 'Asset' } & AssetFragment)> });

export type UpdateAssetMutationVariables = {
input: UpdateAssetInput
};


export type UpdateAssetMutation = ({ __typename?: 'Mutation' } & { updateAsset: ({ __typename?: 'Asset' } & AssetFragment) });

export type SearchProductsQueryVariables = {
input: SearchInput
};
Expand Down Expand Up @@ -5143,6 +5153,12 @@ export namespace CreateAssets {
export type CreateAssets = AssetFragment;
}

export namespace UpdateAsset {
export type Variables = UpdateAssetMutationVariables;
export type Mutation = UpdateAssetMutation;
export type UpdateAsset = AssetFragment;
}

export namespace SearchProducts {
export type Variables = SearchProductsQueryVariables;
export type Query = SearchProductsQuery;
Expand Down
11 changes: 11 additions & 0 deletions packages/admin-ui/src/app/data/definitions/product-definitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ export const ASSET_FRAGMENT = gql`
type
preview
source
width
height
}
`;

Expand Down Expand Up @@ -342,6 +344,15 @@ export const CREATE_ASSETS = gql`
${ASSET_FRAGMENT}
`;

export const UPDATE_ASSET = gql`
mutation UpdateAsset($input: UpdateAssetInput!) {
updateAsset(input: $input) {
...Asset
}
}
${ASSET_FRAGMENT}
`;

export const SEARCH_PRODUCTS = gql`
query SearchProducts($input: SearchInput!) {
search(input: $input) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ import {
RemoveProductsFromChannelInput,
SearchProducts,
SortOrder,
UpdateAsset,
UpdateAssetInput,
UpdateProduct,
UpdateProductInput,
UpdateProductOption,
Expand All @@ -53,6 +55,7 @@ import {
REMOVE_OPTION_GROUP_FROM_PRODUCT,
REMOVE_PRODUCTS_FROM_CHANNEL,
SEARCH_PRODUCTS,
UPDATE_ASSET,
UPDATE_PRODUCT,
UPDATE_PRODUCT_OPTION,
UPDATE_PRODUCT_VARIANTS,
Expand Down Expand Up @@ -265,6 +268,12 @@ export class ProductDataService {
});
}

updateAsset(input: UpdateAssetInput) {
return this.baseDataService.mutate<UpdateAsset.Mutation, UpdateAsset.Variables>(UPDATE_ASSET, {
input,
});
}

assignProductsToChannel(input: AssignProductsToChannelInput) {
return this.baseDataService.mutate<
AssignProductsToChannel.Mutation,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
</div>
<div>
<button (click)="previewAsset(lastSelected())" class="btn btn-link">
{{ 'catalog.preview' | translate }}
{{ 'asset.preview' | translate }}
</button>
</div>
<div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';
import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnChanges, Output } from '@angular/core';

import { Asset } from '../../../common/generated-types';
import { ModalService } from '../../providers/modal/modal.service';
Expand All @@ -10,7 +10,7 @@ import { AssetPreviewDialogComponent } from '../asset-preview-dialog/asset-previ
styleUrls: ['./asset-gallery.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AssetGalleryComponent {
export class AssetGalleryComponent implements OnChanges {
@Input() assets: Asset[];
/**
* If true, allows multiple assets to be selected by ctrl+clicking.
Expand All @@ -22,6 +22,18 @@ export class AssetGalleryComponent {

constructor(private modalService: ModalService) {}

ngOnChanges() {
if (this.assets) {
for (const asset of this.selection) {
// Update and selected assets with any changes
const match = this.assets.find(a => a.id === asset.id);
if (match) {
Object.assign(asset, match);
}
}
}
}

toggleSelection(event: MouseEvent, asset: Asset) {
const index = this.selection.findIndex(a => a.id === asset.id);
if (index === -1) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,8 @@
</div>
</ng-template>

<vdr-asset-preview [asset]="asset"></vdr-asset-preview>
<vdr-asset-preview [asset]="asset" (assetChange)="assetChanges = $event"></vdr-asset-preview>

<ng-template vdrDialogButtons>
<button class="btn btn-primary" [disabled]="!assetChanges" (click)="updateAsset()">{{ 'common.update' | translate }}</button>
</ng-template>
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
import { _ } from '@vendure/admin-ui/src/app/core/providers/i18n/mark-for-extraction';

import { Asset } from '../../../common/generated-types';
import { Asset, UpdateAssetInput } from '../../../common/generated-types';
import { NotificationService } from '../../../core/providers/notification/notification.service';
import { DataService } from '../../../data/providers/data.service';
import { Dialog } from '../../providers/modal/modal.service';

@Component({
Expand All @@ -11,5 +14,24 @@ import { Dialog } from '../../providers/modal/modal.service';
})
export class AssetPreviewDialogComponent implements Dialog<void> {
asset: Asset;
assetChanges?: UpdateAssetInput;
resolveWith: (result?: void) => void;

constructor(private dataService: DataService, private notificationService: NotificationService) {}

updateAsset() {
if (this.assetChanges) {
this.dataService.product.updateAsset(this.assetChanges).subscribe(
() => {
this.assetChanges = undefined;
this.notificationService.success(_('common.notify-update-success'), { entity: 'Asset' });
},
err => {
this.notificationService.error(_('common.notify-update-error'), {
entity: 'Asset',
});
},
);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,33 @@
</div>

<div class="controls">
<div>
<label>{{ 'catalog.preview-size' | translate }}:</label>
<vdr-form-field>
<form [formGroup]="form">
<clr-input-container>
<label>{{ 'common.name' | translate }}</label>
<input
clrInput
type="text"
formControlName="name"
[readonly]="!('UpdateCatalog' | hasPermission)"
/>
</clr-input-container>
<div class="asset-detail">
{{ 'asset.source-file' | translate }}:
<a [href]="asset.source" [title]="asset.source" target="_blank" class="source-link">{{
getSourceFileName()
}}</a>
</div>
<div class="asset-detail">
{{ 'asset.original-asset-size' | translate }}: {{ asset.fileSize | filesize }}
</div>
<div class="asset-detail">
{{ 'asset.dimensions' | translate }}: {{ asset.width }} x {{ asset.height }}
</div>
</form>
<div class="flex-spacer"></div>
<div class="preview-select">
<clr-select-container>
<label>{{ 'asset.preview' | translate }}</label>
<select clrSelect name="options" [(ngModel)]="size">
<option value="tiny">tiny</option>
<option value="thumb">thumb</option>
Expand All @@ -14,18 +38,8 @@
<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>
</clr-select-container>
<div class="asset-detail">{{ width }} x {{ height }}</div>
</div>
<div class="flex-spacer"></div>
<a [href]="asset.source" target="_blank" class="btn btn-link">
{{ 'asset.open-asset-source' | translate }}
</a>

</div>
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,36 @@
.controls {
display: flex;
flex-direction: column;
flex-wrap: wrap;
margin-left: 12px;
min-width: 15vw;

label {
color: $color-grey-500;
::ng-deep .clr-control-container {
width: 100%;
.clr-input {
width: 100%;
}
}
vdr-form-field {
height: 40px;
margin-left: 6px;
margin-right: 24px;
max-width: 112px;

.asset-detail {
font-size: 12px;
display: flex;
}

.source-link {
max-width: 191px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
flex: none;
direction: rtl;
}
.dimension {
margin: 0 6px;

.preview-select {
display: flex;
align-items: flex-end;
margin-bottom: 30px;
clr-select-container {
margin-right: 6px;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
import { ChangeDetectionStrategy, Component, ElementRef, Input, ViewChild } from '@angular/core';
import {
ChangeDetectionStrategy,
Component,
ElementRef,
EventEmitter,
Input,
OnDestroy,
OnInit,
Output,
ViewChild,
} from '@angular/core';
import { FormBuilder, FormControl, FormGroup } from '@angular/forms';
import { Subscription } from 'rxjs';

import { Asset } from '../../../common/generated-types';
import { Asset, UpdateAssetInput } from '../../../common/generated-types';
import { Dialog } from '../../providers/modal/modal.service';

@Component({
Expand All @@ -9,8 +21,11 @@ import { Dialog } from '../../providers/modal/modal.service';
styleUrls: ['./asset-preview.component.scss'],
changeDetection: ChangeDetectionStrategy.Default,
})
export class AssetPreviewComponent {
export class AssetPreviewComponent implements OnInit, OnDestroy {
@Input() asset: Asset;
@Output() assetChange = new EventEmitter<UpdateAssetInput>();

form: FormGroup;

size = 'medium';
resolveWith: (result?: void) => void;
Expand All @@ -19,6 +34,43 @@ export class AssetPreviewComponent {
centered = true;
@ViewChild('imageElement', { static: true }) private imageElementRef: ElementRef<HTMLImageElement>;
@ViewChild('previewDiv', { static: true }) private previewDivRef: ElementRef<HTMLDivElement>;
private subscription: Subscription;

constructor(private formBuilder: FormBuilder) {}

ngOnInit() {
const { focalPoint } = this.asset;
this.form = this.formBuilder.group({
name: [this.asset.name],
focalPointX: [focalPoint ? focalPoint.x : null],
focalPointY: [focalPoint ? focalPoint.y : null],
});
this.subscription = this.form.valueChanges.subscribe(value => {
const focalPointValue =
value.focalPointX != null && value.focalPointY != null
? {
x: value.focalPointX,
y: value.focalPointY,
}
: null;
this.assetChange.emit({
id: this.asset.id,
name: value.name,
focalPoint: focalPointValue,
});
});
}

ngOnDestroy(): void {
if (this.subscription) {
this.subscription.unsubscribe();
}
}

getSourceFileName(): string {
const parts = this.asset.source.split('/');
return parts[parts.length - 1];
}

getDimensions() {
const img = this.imageElementRef.nativeElement;
Expand Down
Loading

0 comments on commit fcb4f3d

Please sign in to comment.