Skip to content

Commit

Permalink
fix(admin-ui): Styling improvements to custom field relation controls
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelbromley committed Jun 30, 2023
1 parent b590bdd commit fb8aca6
Show file tree
Hide file tree
Showing 21 changed files with 80 additions and 40 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { UntypedFormControl } from '@angular/forms';
import { FormControl } from '@angular/forms';

/**
* @description
Expand Down Expand Up @@ -30,7 +30,7 @@ export interface FormInputComponent<C = InputComponentConfig> {
*
* Full documentation can be found in the [Angular docs](https://angular.io/api/forms/FormControl).
*/
formControl: UntypedFormControl;
formControl: FormControl;
/**
* @description
* The `config` property contains the full configuration object of the custom field or configurable argument.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,12 @@ export class TabbedCustomFieldsComponent implements OnInit {
'password-form-input',
'select-form-input',
'text-form-input',
'relation-form-input',
];
return (
customField.type === 'text' ||
customField.type === 'localeText' ||
customField.type === 'relation' ||
(customField.ui?.component && !smallComponents.includes(customField.ui?.component))
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
[addTag]="false"
[multiple]="false"
bindValue="id"
[compareWith]="compareWith"
[clearable]="true"
[searchable]="false"
[ngModel]="formControl.value"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ChangeDetectionStrategy, Component, Input, OnInit } from '@angular/core';
import { UntypedFormControl } from '@angular/forms';
import { FormControl, UntypedFormControl } from '@angular/forms';
import { DefaultFormComponentConfig, DefaultFormComponentId } from '@vendure/common/lib/shared-types';
import { Observable } from 'rxjs';
import { startWith } from 'rxjs/operators';
Expand All @@ -26,7 +26,7 @@ import { DataService } from '../../../data/providers/data.service';
export class CustomerGroupFormInputComponent implements FormInputComponent, OnInit {
static readonly id: DefaultFormComponentId = 'customer-group-form-input';
@Input() readonly: boolean;
formControl: UntypedFormControl;
formControl: FormControl<string | { id: string }>;
customerGroups$: Observable<GetCustomerGroupsQuery['customerGroups']['items']>;
config: DefaultFormComponentConfig<'customer-group-form-input'>;

Expand All @@ -42,6 +42,13 @@ export class CustomerGroupFormInputComponent implements FormInputComponent, OnIn
}

selectGroup(group: ItemOf<GetCustomerGroupsQuery, 'customerGroups'>) {
this.formControl.setValue(group.id);
this.formControl.setValue(group ?? undefined);
}

compareWith(
o1: ItemOf<GetCustomerGroupsQuery, 'customerGroups'>,
o2: ItemOf<GetCustomerGroupsQuery, 'customerGroups'>,
) {
return o1.id === o2.id;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,19 @@
*ngFor="let item of listItems; trackBy: trackById"
cdkDrag
[cdkDragData]="item"
[cdkDragLockAxis]="'y'"
>
<ng-container #listItem></ng-container>
<div class="flex-spacer pr-2">
<ng-container #listItem></ng-container>
</div>
<button
class="btn btn-link btn-sm btn-warning"
class="button-small"
*ngIf="!readonly"
(click)="removeListItem(item)"
[title]="'common.remove-item-from-list' | translate"
>
<clr-icon shape="times"></clr-icon>
</button>
<div class="flex-spacer"></div>
<div class="drag-handle" cdkDragHandle [class.hidden]="readonly">
<clr-icon shape="drag-handle" size="24"></clr-icon>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@
0 3px 14px 2px rgba(0, 0, 0, 0.12);
}

.drag-handle {
cursor: move;
}

.drag-handle.hidden {
display: none;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,15 @@ import {
} from '@angular/core';
import {
ControlValueAccessor,
FormArray,
FormControl,
NG_VALUE_ACCESSOR,
UntypedFormArray,
UntypedFormControl,
} from '@angular/forms';
import { StringCustomFieldConfig } from '@vendure/common/lib/generated-types';
import { ConfigArgType, CustomFieldType, DefaultFormComponentId } from '@vendure/common/lib/shared-types';
import { assertNever } from '@vendure/common/lib/shared-utils';
import { assertNever, notNullOrUndefined } from '@vendure/common/lib/shared-utils';
import { simpleDeepClone } from '@vendure/common/lib/simple-deep-clone';
import { Subject, Subscription } from 'rxjs';
import { switchMap, take, takeUntil } from 'rxjs/operators';
Expand Down Expand Up @@ -71,7 +73,7 @@ export class DynamicFormInputComponent
listItems: InputListItem[] = [];
private singleComponentRef: ComponentRef<FormInputComponent>;
private listId = 1;
private listFormArray = new UntypedFormArray([]);
private listFormArray = new FormArray([] as Array<FormControl<any>>);
private componentType: Type<FormInputComponent>;
private onChange: (val: any) => void;
private onTouch: () => void;
Expand Down Expand Up @@ -151,8 +153,9 @@ export class DynamicFormInputComponent
.subscribe(val => {
this.control.markAsTouched();
this.control.markAsDirty();
this.onChange(val);
this.control.patchValue(val, { emitEvent: false });
const truthyValues = val.filter(notNullOrUndefined);
this.onChange(truthyValues);
this.control.patchValue(truthyValues, { emitEvent: false });
});
setTimeout(() => this.changeDetectorRef.markForCheck());
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnInit } from '@angular/core';
import { UntypedFormControl } from '@angular/forms';
import { FormControl, UntypedFormControl } from '@angular/forms';
import { DefaultFormComponentConfig, DefaultFormComponentId } from '@vendure/common/lib/shared-types';

import { FormInputComponent } from '../../../common/component-registry-types';
Expand All @@ -15,7 +15,7 @@ import { ProductMultiSelectorDialogComponent } from '../../components/product-mu
})
export class ProductMultiSelectorFormInputComponent implements OnInit, FormInputComponent {
@Input() config: DefaultFormComponentConfig<'product-multi-form-input'>;
@Input() formControl: UntypedFormControl;
@Input() formControl: FormControl<string[] | Array<{ id: string }>>;
@Input() readonly: boolean;
mode: 'product' | 'variant' = 'product';
readonly isListInput = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
</div>
<div class="flex-spacer"></div>
<button
class="btn btn-link btn-sm btn-warning"
class="button-small"
(click)="removeProductVariant(variant.id)"
[title]="'common.remove-item-from-list' | translate"
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
}
.thumb {
margin-right: 6px;
img {
border-radius: var(--border-radius);
}
}
.sku {
color: var(--color-grey-400);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
import { UntypedFormControl } from '@angular/forms';
import { DefaultFormComponentId } from '@vendure/common/lib/shared-types';
import { FormControl } from '@angular/forms';
import { DefaultFormComponentId, DefaultFormComponentUiConfig } from '@vendure/common/lib/shared-types';
import { notNullOrUndefined } from '@vendure/common/lib/shared-utils';
import { forkJoin, Observable, of } from 'rxjs';
import { map, startWith, switchMap } from 'rxjs/operators';

import { FormInputComponent, InputComponentConfig } from '../../../common/component-registry-types';
import { FormInputComponent } from '../../../common/component-registry-types';
import { GetProductVariantQuery, ProductSelectorSearchQuery } from '../../../common/generated-types';
import { DataService } from '../../../data/providers/data.service';

Expand All @@ -27,8 +27,8 @@ export class ProductSelectorFormInputComponent implements FormInputComponent, On
static readonly id: DefaultFormComponentId = 'product-selector-form-input';
readonly isListInput = true;
readonly: boolean;
formControl: UntypedFormControl;
config: InputComponentConfig;
formControl: FormControl<Array<string | { id: string }>>;
config: DefaultFormComponentUiConfig<'product-selector-form-input'>;
selection$: Observable<Array<GetProductVariantQuery['productVariant']>>;

constructor(private dataService: DataService) {}
Expand All @@ -52,7 +52,7 @@ export class ProductSelectorFormInputComponent implements FormInputComponent, On
return forkJoin(
value.map(id =>
this.dataService.product
.getProductVariant(id)
.getProductVariant(this.getId(id))
.mapSingle(data => data.productVariant),
),
);
Expand All @@ -66,10 +66,16 @@ export class ProductSelectorFormInputComponent implements FormInputComponent, On
addProductVariant(product: ProductSelectorSearchQuery['search']['items'][number]) {
const value = this.formControl.value as string[];
this.formControl.setValue([...new Set([...value, product.productVariantId])]);
this.formControl.markAsDirty();
}

removeProductVariant(id: string) {
const value = this.formControl.value as string[];
this.formControl.setValue(value.filter(_id => _id !== id));
const value = this.formControl.value;
this.formControl.setValue(value.map(this.getId).filter(_id => _id !== id));
this.formControl.markAsDirty();
}

private getId(value: (typeof this.formControl.value)[number]) {
return typeof value === 'string' ? value : value.id;
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
.preview {
cursor: pointer;
border-radius: var(--border-radius);
}

.detail {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
import { ChangeDetectionStrategy, Component, Input, OnInit } from '@angular/core';
import { UntypedFormControl } from '@angular/forms';
import { DefaultFormComponentId } from '@vendure/common/lib/shared-types';
import { gql } from 'apollo-angular';
import { Observable, of } from 'rxjs';
import { distinctUntilChanged, map, startWith, switchMap } from 'rxjs/operators';

import { FormInputComponent } from '../../../../common/component-registry-types';
import { GetAssetQuery, RelationCustomFieldConfig } from '../../../../common/generated-types';
import { ASSET_FRAGMENT, TAG_FRAGMENT } from '../../../../data/definitions/product-definitions';
import { DataService } from '../../../../data/providers/data.service';
Expand All @@ -32,8 +29,7 @@ export const RELATION_ASSET_INPUT_QUERY = gql`
styleUrls: ['./relation-asset-input.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class RelationAssetInputComponent implements FormInputComponent, OnInit {
static readonly id: DefaultFormComponentId = 'asset-form-input';
export class RelationAssetInputComponent implements OnInit {
@Input() readonly: boolean;
@Input('parentFormControl') formControl: UntypedFormControl;
@Input() config: RelationCustomFieldConfig;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ export class RelationCustomerInputComponent implements OnInit {
@Input() config: RelationCustomFieldConfig;

@ViewChild('selector') template: TemplateRef<any>;

searchControl = new UntypedFormControl('');
searchTerm$ = new Subject<string>();
results$: Observable<Codegen.GetCustomerListQuery['customers']['items']>;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,23 @@
[readonly]="readonly"
>
<ng-template vdrRelationCardPreview let-variant="entity">
<img
*ngIf="variant.featuredAsset || variant.product.featuredAsset as asset; else placeholder"
[src]="asset | assetPreview: 'tiny'"
/>
<div>
<img
class="thumb"
*ngIf="variant.featuredAsset || variant.product.featuredAsset as asset; else placeholder"
[src]="asset | assetPreview : 'tiny'"
/>
</div>
<ng-template #placeholder>
<div class="placeholder" *ngIf="!variant.featuredAsset">
<clr-icon shape="image" size="50"></clr-icon>
</div>
</ng-template>
</ng-template>
<ng-template vdrRelationCardDetail let-variant="entity">
<a [routerLink]="['/catalog/inventory', variant.product.id, { tab: 'variants' }]">{{ variant.name }}</a>
<a [routerLink]="['/catalog/inventory', variant.product.id, { tab: 'variants' }]">{{
variant.name
}}</a>
<div class="">{{ variant.sku }}</div>
</ng-template>
</vdr-relation-card>
Expand All @@ -29,7 +34,7 @@
<ng-template ng-option-tmp let-item="item">
<img
*ngIf="item.featuredAsset || item.product.featuredAsset as asset"
[src]="asset | assetPreview: 32"
[src]="asset | assetPreview : 32"
/>
{{ item.name }}
</ng-template>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
.placeholder {
color: var(--color-grey-300);
}
.thumb {
min-width: 50px;
object-fit: contain;
border-radius: var(--border-radius);
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
[readonly]="readonly"
>
<ng-template vdrRelationCardPreview let-product="entity">
<img *ngIf="product.featuredAsset" [src]="product.featuredAsset | assetPreview: 'tiny'" />
<div>
<img class="thumb" *ngIf="product.featuredAsset" [src]="product.featuredAsset | assetPreview: 'tiny'" />
</div>
<div class="placeholder" *ngIf="!product.featuredAsset">
<clr-icon shape="image" size="50"></clr-icon>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
.placeholder {
color: var(--color-grey-300);
}

.thumb {
min-width: 50px;
object-fit: contain;
border-radius: var(--border-radius);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<ng-container *ngTemplateOutlet="previewTemplate; context: { entity: entity }"></ng-container>
</div>
<div class="detail">
<div class="pl3">
<div class="pl-1">
<ng-container *ngTemplateOutlet="detailTemplate; context: { entity: entity }"></ng-container>
</div>
<button *ngIf="!readonly" class="button-small m-1" (click)="select.emit()">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@
display: block;
background-color: var(--color-component-bg-200);
padding: 3px;
border-radius: var(--border-radius);
}
2 changes: 0 additions & 2 deletions packages/common/src/shared-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,6 @@ export type DefaultFormComponentId =
| 'select-form-input'
| 'text-form-input'
| 'textarea-form-input'
| 'asset-form-input'
| 'product-multi-form-input'
| 'combination-mode-form-input';

Expand Down Expand Up @@ -177,7 +176,6 @@ type DefaultFormConfigHash = {
'textarea-form-input': {
spellcheck?: boolean;
};
'asset-form-input': Record<string, never>;
'product-multi-form-input': {
selectionMode?: 'product' | 'variant';
};
Expand Down

0 comments on commit fb8aca6

Please sign in to comment.