Browse Source

feat(admin-ui): Make new product option names editable

Michael Bromley 3 years ago
parent
commit
600990f38f

+ 1 - 0
packages/admin-ui/src/lib/catalog/src/components/generate-product-variants/generate-product-variants.component.html

@@ -16,6 +16,7 @@
             #optionValueInputComponent
             [(ngModel)]="group.values"
             (ngModelChange)="generateVariants()"
+            (edit)="generateVariants()"
             [groupName]="group.name"
             [disabled]="group.name === ''"
         ></vdr-option-value-input>

+ 1 - 2
packages/admin-ui/src/lib/catalog/src/components/generate-product-variants/generate-product-variants.component.ts

@@ -1,8 +1,7 @@
 import { Component, EventEmitter, OnInit, Output } from '@angular/core';
+import { CurrencyCode, DataService } from '@vendure/admin-ui/core';
 import { generateAllCombinations } from '@vendure/common/lib/shared-utils';
 
-import { CurrencyCode } from '@vendure/admin-ui/core';
-import { DataService } from '@vendure/admin-ui/core';
 import { OptionValueInputComponent } from '../option-value-input/option-value-input.component';
 
 const DEFAULT_VARIANT_CODE = '__DEFAULT_VARIANT__';

+ 14 - 2
packages/admin-ui/src/lib/catalog/src/components/option-value-input/option-value-input.component.html

@@ -1,14 +1,26 @@
 <div class="input-wrapper" [class.focus]="isFocussed" (click)="textArea.focus()">
     <div class="chips" *ngIf="0 < optionValues.length">
         <vdr-chip
-            *ngFor="let option of optionValues; last as isLast"
+            *ngFor="let option of optionValues; last as isLast; index as i"
             [icon]="option.locked ? 'lock' : 'times'"
             [class.selected]="isLast && lastSelected"
             [class.locked]="option.locked"
             [colorFrom]="groupName"
             (iconClick)="removeOption(option)"
         >
-            {{ option.name }}
+            <span [hidden]="editingIndex !== i">
+                <input
+                    #editNameInput
+                    type="text"
+                    [ngModel]="option.name"
+                    (blur)="updateOption(i, $event)"
+                    (click)="$event.cancelBubble = true"
+                />
+            </span>
+            <span
+                class="option-name"
+                [class.editable]="!option.locked && !option.id"
+                (click)="editName(i, $event)" [hidden]="editingIndex === i">{{ option.name }}</span>
         </vdr-chip>
     </div>
     <textarea

+ 14 - 0
packages/admin-ui/src/lib/catalog/src/components/option-value-input/option-value-input.component.scss

@@ -43,4 +43,18 @@ vdr-chip {
             opacity: 0.6;
         }
     }
+    .option-name {
+        &.editable {
+            &:hover {
+                outline: 1px solid var(--color-component-bg-300);
+                outline-offset: 1px;
+                border-radius: 1px;
+            }
+        }
+    }
+    input {
+        padding: 0px !important;
+        margin-top: -2px;
+        margin-bottom: -2px;
+    }
 }

+ 27 - 0
packages/admin-ui/src/lib/catalog/src/components/option-value-input/option-value-input.component.ts

@@ -10,8 +10,10 @@ import {
     OnInit,
     Output,
     Provider,
+    QueryList,
     SimpleChanges,
     ViewChild,
+    ViewChildren,
 } from '@angular/core';
 import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
 import { unique } from '@vendure/common/lib/unique';
@@ -38,14 +40,17 @@ interface Option {
 export class OptionValueInputComponent implements ControlValueAccessor {
     @Input() groupName = '';
     @ViewChild('textArea', { static: true }) textArea: ElementRef<HTMLTextAreaElement>;
+    @ViewChildren('editNameInput', { read: ElementRef }) nameInputs: QueryList<ElementRef>;
     @Input() options: Option[];
     @Output() add = new EventEmitter<Option>();
     @Output() remove = new EventEmitter<Option>();
+    @Output() edit = new EventEmitter<{ index: number; option: Option }>();
     @Input() disabled = false;
     input = '';
     isFocussed = false;
     lastSelected = false;
     formValue: Option[];
+    editingIndex = -1;
     onChangeFn: (value: any) => void;
     onTouchFn: (value: any) => void;
 
@@ -76,6 +81,28 @@ export class OptionValueInputComponent implements ControlValueAccessor {
         this.textArea.nativeElement.focus();
     }
 
+    editName(index: number, event: MouseEvent) {
+        const optionValue = this.optionValues[index];
+        if (!optionValue.locked && !optionValue.id) {
+            event.cancelBubble = true;
+            this.editingIndex = index;
+            const input = this.nameInputs.get(index)?.nativeElement;
+            setTimeout(() => input?.focus());
+        }
+    }
+
+    updateOption(index: number, event: InputEvent) {
+        const optionValue = this.optionValues[index];
+        const newName = (event.target as HTMLInputElement).value;
+        if (optionValue) {
+            if (newName) {
+                optionValue.name = newName;
+                this.edit.emit({ index, option: optionValue });
+            }
+            this.editingIndex = -1;
+        }
+    }
+
     removeOption(option: Option) {
         if (!option.locked) {
             if (this.formValue) {