From f74759667c52249b07dcf038323b75691a100b4a Mon Sep 17 00:00:00 2001 From: Will Sun <30999793+AllForNothing@users.noreply.github.com> Date: Fri, 2 Apr 2021 14:13:34 +0800 Subject: [PATCH] Improve replication page (#14566) Signed-off-by: AllForNothing --- .../create-edit-rule.component.ts | 24 ++---- .../replication/replication.component.ts | 14 ++-- src/portal/src/app/shared/units/utils.spec.ts | 25 ++++++ src/portal/src/app/shared/units/utils.ts | 77 +++++++++++++++++++ 4 files changed, 115 insertions(+), 25 deletions(-) create mode 100644 src/portal/src/app/shared/units/utils.spec.ts diff --git a/src/portal/src/app/base/left-side-nav/replication/replication/create-edit-rule/create-edit-rule.component.ts b/src/portal/src/app/base/left-side-nav/replication/replication/create-edit-rule/create-edit-rule.component.ts index f313e3882..1207fda60 100644 --- a/src/portal/src/app/base/left-side-nav/replication/replication/create-edit-rule/create-edit-rule.component.ts +++ b/src/portal/src/app/base/left-side-nav/replication/replication/create-edit-rule/create-edit-rule.component.ts @@ -21,10 +21,10 @@ import { Output } from "@angular/core"; import { Filter, ReplicationRule, Endpoint } from "../../../../../shared/services/interface"; -import { Subject, Subscription, Observable, zip } from "rxjs"; +import { Subject, Subscription } from "rxjs"; import { debounceTime, distinctUntilChanged, finalize } from "rxjs/operators"; import { FormArray, FormBuilder, FormGroup, Validators, FormControl } from "@angular/forms"; -import { clone, compareValue, isEmptyObject } from "../../../../../shared/units/utils"; +import { clone, isEmptyObject, isSameObject } from "../../../../../shared/units/utils"; import { InlineAlertComponent } from "../../../../../shared/components/inline-alert/inline-alert.component"; import { ReplicationService } from "../../../../../shared/services"; import { ErrorHandler } from "../../../../../shared/units/error-handler"; @@ -235,11 +235,7 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy { updateRuleFormAndCopyUpdateForm(rule: ReplicationRule): void { - if (rule.dest_registry.id === 0) { - this.isPushMode = false; - } else { - this.isPushMode = true; - } + this.isPushMode = rule.dest_registry.id !== 0; setTimeout(() => { // There is no trigger_setting type when the harbor is upgraded from the old version. rule.trigger.trigger_settings = rule.trigger.trigger_settings ? rule.trigger.trigger_settings : {cron: ''}; @@ -507,17 +503,9 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy { } hasChanges(): boolean { - let formValue = clone(this.ruleForm.value); - let initValue = clone(this.copyUpdateForm); - let initValueCopy: any = {}; - for (let key of Object.keys(formValue)) { - initValueCopy[key] = initValue[key]; - } - - if (!compareValue(formValue, initValueCopy)) { - return true; - } - return false; + const formValue = clone(this.ruleForm.value); + const initValue = clone(this.copyUpdateForm); + return !isSameObject(formValue, initValue); } diff --git a/src/portal/src/app/base/left-side-nav/replication/replication/replication.component.ts b/src/portal/src/app/base/left-side-nav/replication/replication/replication.component.ts index 56cb9ef78..76dfb6738 100644 --- a/src/portal/src/app/base/left-side-nav/replication/replication/replication.component.ts +++ b/src/portal/src/app/base/left-side-nav/replication/replication/replication.component.ts @@ -478,8 +478,12 @@ export class ReplicationComponent implements OnInit, OnDestroy { refreshRules() { this.search.ruleName = ""; - this.filterComponent.currentValue = ""; - this.listReplicationRule.refreshRule(); + if (this.filterComponent.currentValue) { + this.filterComponent.currentValue = ""; + this.filterComponent.filterTerms.next(''); // will trigger refreshing + } else { + this.listReplicationRule.refreshRule(); // manually refresh + } } refreshJobs() { @@ -497,11 +501,7 @@ export class ReplicationComponent implements OnInit, OnDestroy { } openFilter(isOpen: boolean): void { - if (isOpen) { - this.isOpenFilterTag = true; - } else { - this.isOpenFilterTag = false; - } + this.isOpenFilterTag = isOpen; } getDuration(j: ReplicationJobItem) { if (!j) { diff --git a/src/portal/src/app/shared/units/utils.spec.ts b/src/portal/src/app/shared/units/utils.spec.ts new file mode 100644 index 000000000..8cc3b3898 --- /dev/null +++ b/src/portal/src/app/shared/units/utils.spec.ts @@ -0,0 +1,25 @@ +import { isSameArrayValue, isSameObject } from "./utils"; + +describe('functions in utils.ts should work', () => { + it('function isSameArrayValue() should work', () => { + expect(isSameArrayValue).toBeTruthy(); + expect(isSameArrayValue(null, null)).toBeFalsy(); + expect(isSameArrayValue([], null)).toBeFalsy(); + expect(isSameArrayValue([1, 2, 3], [3 , 2, 1])).toBeTruthy(); + expect(isSameArrayValue([{a: 1, c: 2}, true], [true, {c: 2, a: 1, d: null}])).toBeTruthy(); + }); + + it('function isSameObject() should work', () => { + expect(isSameObject).toBeTruthy(); + expect(isSameObject(null, null)).toBeTruthy(); + expect(isSameObject({}, null)).toBeFalsy(); + expect(isSameObject(null, {})).toBeFalsy(); + expect(isSameObject([], null)).toBeFalsy(); + expect(isSameObject(null, [])).toBeFalsy(); + expect(isSameObject({a: 1, b: true}, {a: 1})).toBeFalsy(); + expect(isSameObject({a: 1, b: false}, {a: 1})).toBeFalsy(); + expect(isSameObject({a: [1, 2, 3], b: null}, {a: [3, 2, 1]})).toBeTruthy(); + expect(isSameObject({a: {a: 1 , b: 2}, b: null}, {a: {b: 2, a: 1}})).toBeTruthy(); + expect(isSameObject([1, 2, 3], [3 , 2, 1])).toBeFalsy(); + }); +}); diff --git a/src/portal/src/app/shared/units/utils.ts b/src/portal/src/app/shared/units/utils.ts index 0befb5b46..b37f0457f 100644 --- a/src/portal/src/app/shared/units/utils.ts +++ b/src/portal/src/app/shared/units/utils.ts @@ -646,3 +646,80 @@ export function getSortingString(state: ClrDatagridStateInterface): string { } return null; } + +/** + * if two object are the same + * @param a + * @param b + */ +export function isSameObject(a: any, b: any): boolean { + if (a && !b) { + return false; + } + if (b && !a) { + return false; + } + if (a && b) { + if (Array.isArray(a) || Array.isArray(b)) { + return false; + } + const c: any = Object.keys(a).length > Object.keys(b).length ? a : b; + for (const key in c) { + if (c.hasOwnProperty(key)) { + if (!c[key]) { + // should not use triple-equals here + // tslint:disable-next-line:triple-equals + if (a[key] != b[key]) { + return false; + } + } else { + if (Array.isArray(c[key])) { + if (!isSameArrayValue(a[key], b[key])) { + return false; + } + } else if (isObject(c[key])) { + if (!isSameObject(a[key], b[key])) { + return false; + } + } else { + // should not use triple-equals here + // tslint:disable-next-line:triple-equals + if (a[key] != b[key]) { + return false; + } + } + } + } + } + } + return true; +} + +/** + * if two arrays have the same length and contain the same items, they are regarded as the same + * @param a + * @param b + */ +export function isSameArrayValue(a: any, b: any): boolean { + if (a && b && Array.isArray(a) && Array.isArray(a)) { + if (a.length !== b.length) { + return false; + } + let isSame: boolean = true; + a.forEach(itemOfA => { + let hasItem: boolean = false; + b.forEach(itemOfB => { + if (isSameObject(itemOfA, itemOfB)) { + hasItem = true; + } + }); + if (!hasItem) { + isSame = false; + } + }); + if (isSame) { + return true; + } + } + return false; +}