Make label filter editable for replication rule (#18357)

1. Fixes #15825
2. Now, you can input labels or select them from the candidates

Signed-off-by: AllForNothing <sshijun@vmware.com>
This commit is contained in:
Shijun Sun 2023-03-17 15:48:03 +08:00 committed by GitHub
parent e76aff6a0a
commit 339f5b106b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 92 additions and 129 deletions

View File

@ -272,69 +272,25 @@
</option>
</select>
</div>
<div
class="dropdown clr-select-wrapper"
formArrayName="value">
<clr-dropdown class="width-tag-label">
<div
class="width-100 label-text"
clrDropdownTrigger>
<div class="label-container">
<ng-template
ngFor
let-label
[ngForOf]="
filter.value.value
"
let-m="index">
<hbr-label-piece
class="label-piece"
*ngIf="m < 1 && label"
[hasIcon]="false"
[label]="
getLabel(label)
"
[labelWidth]="
84
"></hbr-label-piece>
</ng-template>
<span
class="ellipsis color-white-dark"
*ngIf="
filter.value.value
.length > 1
"
>···</span
>
</div>
<div
*ngFor="
let label1 of filter.value
.value;
let k = index
"
hidden="true">
<input
type="text"
[formControlName]="k"
#labelValue
id="{{
'label_' +
supportedFilters[i]
?.type +
'_' +
label1
}}"
name="{{
'label_' +
supportedFilters[i]
?.type +
'_' +
label1
}}"
placeholder="select labels" />
</div>
</div>
class="clr-input-wrapper position-relative width-tag-label">
<input
class="clr-input width-tag-label label-input"
autocomplete="off"
type="text"
id="labelFilter"
[(ngModel)]="stringForLabelFilter"
[ngModelOptions]="{
standalone: true
}" />
<clr-dropdown>
<clr-icon
class="down"
clrDropdownTrigger
shape="caret"
dir="down">
</clr-icon>
<clr-dropdown-menu
[ngStyle]="{ 'max-height.px': 230 }"
class="right-align"
@ -346,11 +302,13 @@
*ngFor="
let value of supportedFilterLabels
"
(click)="stickLabel(value, i)">
(click)="
stickLabel(value.name)
">
<clr-icon
shape="check"
[style.visibility]="
value.select
isSelect(value.name)
? 'visible'
: 'hidden'
"></clr-icon>

View File

@ -272,7 +272,7 @@ clr-modal {
.right-align {
min-width: 204px;
overflow-y: auto;
transform: translateX(-4.3rem) translateY(1.25rem)!important;
transform: translateX(-9rem) translateY(1.25rem)!important;
}
.dropdown-item {
@ -327,3 +327,19 @@ clr-modal {
.bandwidth {
margin-top: 0.25rem;
}
.down {
height: 25px;
width: 25px;
right: 0.2rem;
color: rgb(164 164 164) !important;
cursor: pointer;
}
.dropdown {
left: -1.2rem;
position: relative !important;
}
.label-input {
padding-right: 1.2rem;
}

View File

@ -95,7 +95,6 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy {
supportedFilterLabels: {
name: string;
color: string;
select: boolean;
scope: string;
}[] = [];
@ -118,6 +117,8 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy {
selectedUnit: string = BandwidthUnit.KB;
copySpeedUnit: string = BandwidthUnit.KB;
showChunkOption: boolean = false;
stringForLabelFilter: string = '';
copyStringForLabelFilter: string = '';
constructor(
private fb: UntypedFormBuilder,
private repService: ReplicationService,
@ -365,9 +366,23 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy {
});
this.isPushMode = true;
this.selectedUnit = BandwidthUnit.KB;
this.stringForLabelFilter = '';
}
updateRuleFormAndCopyUpdateForm(rule: ReplicationPolicy): void {
if (rule?.filters?.length) {
// set stringForLabelFilter
this.stringForLabelFilter = '';
this.copyStringForLabelFilter = '';
rule.filters.forEach(item => {
if (item.type === FilterType.LABEL) {
this.stringForLabelFilter = (item.value as string[]).join(
','
);
this.copyStringForLabelFilter = this.stringForLabelFilter;
}
});
}
this.isPushMode = rule.dest_registry.id !== 0;
this.checkChunkOption(rule.dest_registry.id || rule.src_registry.id);
setTimeout(() => {
@ -482,6 +497,10 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy {
// speed unit has been changed
return true;
}
if (this.copyStringForLabelFilter !== this.stringForLabelFilter) {
// label filter has been changed
return true;
}
return !isEmptyObject(this.hasChanges());
}
@ -511,6 +530,18 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy {
copyRuleForm.dest_registry = null;
}
let filters: any = copyRuleForm.filters;
// set label filter
if (this.stringForLabelFilter) {
// set stringForLabelFilter
copyRuleForm.filters.forEach(item => {
if (item.type === FilterType.LABEL) {
item.value = this.stringForLabelFilter
.split(',')
.filter(item => item);
}
});
}
// remove the filters which user not set.
for (let i = filters.length - 1; i >= 0; i--) {
if (
@ -575,30 +606,6 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy {
this.noEndpointInfo = 'REPLICATION.NO_ENDPOINT_INFO';
}
if (rule) {
if (
this.supportedFilterLabels &&
this.supportedFilterLabels.length
) {
this.supportedFilterLabels.forEach((label, index) => {
if (rule.filters && rule.filters.length) {
rule.filters.forEach(f => {
if (
f.type === FilterType.LABEL &&
f.value &&
(f.value as any).length
) {
(f.value as any).forEach(name => {
if (label.name === name) {
this.supportedFilterLabels[
index
].select = true;
}
});
}
});
}
});
}
this.onGoing = true;
this.policyId = +rule.id;
this.headerTitle = 'REPLICATION.EDIT_POLICY_TITLE';
@ -634,14 +641,6 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy {
adapter => {
this.setFilterAndTrigger(adapter);
this.copyUpdateForm = clone(this.ruleForm.value);
if (
this.supportedFilterLabels &&
this.supportedFilterLabels.length
) {
this.supportedFilterLabels.forEach((label, index) => {
label.select = false;
});
}
},
(error: any) => {
this.inlineAlert.showInlineError(error);
@ -746,24 +745,20 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy {
}
return false;
}
stickLabel(value, index) {
value.select = !value.select;
let filters = this.ruleForm.get('filters') as UntypedFormArray;
let fromIndex = filters.controls[index] as UntypedFormGroup;
let labelValue = this.supportedFilterLabels.reduce(
(cumulatedSelectedArrs, currentValue) => {
if (currentValue.select) {
if (!cumulatedSelectedArrs.length) {
return [currentValue.name];
}
return [...cumulatedSelectedArrs, currentValue.name];
}
return cumulatedSelectedArrs;
},
[]
);
fromIndex.setControl('value', this.fb.array(labelValue));
stickLabel(name: string) {
if (this.isSelect(name)) {
let arr: string[] = this.stringForLabelFilter.split(',');
arr = arr.filter(item => {
return item !== name;
});
this.stringForLabelFilter = arr.join(',');
} else {
if (this.stringForLabelFilter) {
this.stringForLabelFilter += `,${name}`;
} else {
this.stringForLabelFilter += `${name}`;
}
}
}
// set prefix '0 ', so user can not set item of 'seconds'
inputInvalid(e: any) {
@ -820,7 +815,6 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy {
this.supportedFilterLabels.push({
name: data.name,
color: data.color ? data.color : '#FFFFFF',
select: false,
scope: 'g',
});
});
@ -849,7 +843,6 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy {
color: data.color
? data.color
: '#FFFFFF',
select: false,
scope: 'g',
});
});
@ -880,17 +873,6 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy {
return realSpeed ? realSpeed : -1;
}
}
getLabel(labelName: string): Label {
if (this.supportedFilterLabels?.length) {
let label: Label;
this.supportedFilterLabels.forEach(item => {
if (item.name === labelName) {
label = item;
}
});
return label;
}
}
checkChunkOption(id: number, info?: RegistryInfo) {
this.showChunkOption = false;
this.ruleForm.get('copy_by_chunk').reset(false);
@ -906,4 +888,11 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy {
}
}
}
isSelect(v: string) {
if (v && this.stringForLabelFilter) {
return this.stringForLabelFilter.indexOf(v) !== -1;
}
return false;
}
}