mirror of https://github.com/goharbor/harbor.git
825 lines
40 KiB
HTML
825 lines
40 KiB
HTML
<clr-modal
|
|
[(clrModalOpen)]="createEditRuleOpened"
|
|
[clrModalStaticBackdrop]="true"
|
|
[clrModalClosable]="false">
|
|
<h3 class="modal-title">{{ headerTitle | translate }}</h3>
|
|
<div class="modal-body modal-body-height">
|
|
<inline-alert (confirmEvt)="confirmCancel($event)"></inline-alert>
|
|
<form
|
|
[formGroup]="ruleForm"
|
|
novalidate
|
|
class="clr-form clr-form-horizontal">
|
|
<div
|
|
class="clr-form-control"
|
|
[class.clr-error]="
|
|
(ruleForm.controls.name.touched &&
|
|
ruleForm.controls.name.invalid) ||
|
|
!isRuleNameValid
|
|
">
|
|
<label class="clr-control-label required">{{
|
|
'REPLICATION.NAME' | translate
|
|
}}</label>
|
|
<div class="clr-control-container">
|
|
<div class="clr-input-wrapper">
|
|
<input
|
|
class="clr-input width-input"
|
|
type="text"
|
|
id="ruleName"
|
|
size="35"
|
|
pattern="^[a-z0-9]+(?:[._-][a-z0-9]+)*$"
|
|
required
|
|
maxlength="255"
|
|
formControlName="name"
|
|
#ruleName
|
|
(keyup)="checkRuleName()"
|
|
autocomplete="off" />
|
|
<clr-icon
|
|
class="clr-validate-icon"
|
|
shape="exclamation-circle"></clr-icon>
|
|
<span
|
|
class="spinner spinner-inline spinner-pos"
|
|
[hidden]="!inNameChecking"></span>
|
|
</div>
|
|
<clr-control-error
|
|
*ngIf="
|
|
(ruleForm.controls.name.touched &&
|
|
ruleForm.controls.name.invalid) ||
|
|
!isRuleNameValid
|
|
"
|
|
>{{ ruleNameTooltip | translate }}</clr-control-error
|
|
>
|
|
</div>
|
|
</div>
|
|
<!--Description-->
|
|
<clr-textarea-container>
|
|
<label>{{ 'REPLICATION.DESCRIPTION' | translate }}</label>
|
|
<textarea
|
|
clrTextarea
|
|
type="text"
|
|
id="ruleDescription"
|
|
class="width-input"
|
|
row="3"
|
|
formControlName="description"></textarea>
|
|
</clr-textarea-container>
|
|
<!-- replication mode -->
|
|
<clr-radio-container clrInline>
|
|
<label>{{ 'REPLICATION.REPLI_MODE' | translate }}</label>
|
|
<clr-radio-wrapper>
|
|
<input
|
|
clrRadio
|
|
type="radio"
|
|
id="push_base"
|
|
name="replicationMode"
|
|
[value]="true"
|
|
[disabled]="policyId >= 0 || onGoing"
|
|
[(ngModel)]="isPushMode"
|
|
(change)="pushModeChange()"
|
|
[ngModelOptions]="{ standalone: true }" />
|
|
<label for="push_base"
|
|
>Push-based
|
|
<clr-tooltip class="mode-tooltip">
|
|
<clr-icon
|
|
clrTooltipTrigger
|
|
shape="info-circle"
|
|
size="24"></clr-icon>
|
|
<clr-tooltip-content
|
|
clrPosition="top-left"
|
|
clrSize="md"
|
|
*clrIfOpen>
|
|
<span>{{
|
|
'TOOLTIP.PUSH_BASED' | translate
|
|
}}</span>
|
|
</clr-tooltip-content>
|
|
</clr-tooltip>
|
|
</label>
|
|
</clr-radio-wrapper>
|
|
<clr-radio-wrapper>
|
|
<input
|
|
clrRadio
|
|
type="radio"
|
|
id="pull_base"
|
|
name="replicationMode"
|
|
[value]="false"
|
|
[disabled]="policyId >= 0 || onGoing"
|
|
[(ngModel)]="isPushMode"
|
|
(change)="pullModeChange()"
|
|
[ngModelOptions]="{ standalone: true }" />
|
|
<label for="pull_base"
|
|
>Pull-based
|
|
<clr-tooltip class="mode-tooltip">
|
|
<clr-icon
|
|
clrTooltipTrigger
|
|
shape="info-circle"
|
|
size="24"></clr-icon>
|
|
<clr-tooltip-content
|
|
clrPosition="top-left"
|
|
clrSize="md"
|
|
*clrIfOpen>
|
|
<span>{{
|
|
'TOOLTIP.PULL_BASED' | translate
|
|
}}</span>
|
|
</clr-tooltip-content>
|
|
</clr-tooltip>
|
|
</label>
|
|
</clr-radio-wrapper>
|
|
</clr-radio-container>
|
|
<!--source registry-->
|
|
<div class="clr-form-control" *ngIf="!isPushMode">
|
|
<label class="required clr-control-label">{{
|
|
'REPLICATION.SOURCE_REGISTRY' | translate
|
|
}}</label>
|
|
<div class="clr-control-container">
|
|
<div class="clr-select-wrapper">
|
|
<select
|
|
class="clr-select width-input"
|
|
id="src_registry_id"
|
|
(change)="sourceChange($event)"
|
|
formControlName="src_registry"
|
|
[compareWith]="equals">
|
|
<option class="display-none"></option>
|
|
<option
|
|
*ngFor="let source of sourceList"
|
|
[ngValue]="source">
|
|
{{ source.name }}-{{ source.url }}
|
|
</option>
|
|
</select>
|
|
</div>
|
|
<div class="space-between">
|
|
<span
|
|
*ngIf="noEndpointInfo.length !== 0"
|
|
class="alert-label"
|
|
>{{ noEndpointInfo | translate }}</span
|
|
>
|
|
<span
|
|
class="alert-label go-link"
|
|
*ngIf="noEndpointInfo.length !== 0"
|
|
(click)="goRegistry()"
|
|
>{{ 'REPLICATION.ENDPOINTS' | translate }}</span
|
|
>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!--images/Filter-->
|
|
<div class="clr-form-control">
|
|
<label class="clr-control-label">{{
|
|
'REPLICATION.SOURCE_RESOURCE_FILTER' | translate
|
|
}}</label>
|
|
<span
|
|
class="spinner spinner-inline spinner-position"
|
|
[hidden]="onGoing === false"></span>
|
|
<div formArrayName="filters" class="clr-control-container">
|
|
<div
|
|
class="filterSelect"
|
|
*ngFor="let filter of filters.controls; let i = index">
|
|
<div [formGroupName]="i" class="flex">
|
|
<label class="sub-label"
|
|
>{{
|
|
'REPLICATION.' +
|
|
supportedFilters[i]?.type.toUpperCase()
|
|
| translate
|
|
}}:</label
|
|
>
|
|
<div
|
|
*ngIf="supportedFilters[i]?.style === 'input'"
|
|
class="flex">
|
|
<div
|
|
class="clr-select-wrapper mr-1"
|
|
*ngIf="supportedFilters[i]?.type === 'tag'">
|
|
<select
|
|
class="clr-select width-match-exclude"
|
|
formControlName="decoration">
|
|
<option value="matches">
|
|
{{
|
|
'TAG_RETENTION.MAT' | translate
|
|
}}
|
|
</option>
|
|
<option value="excludes">
|
|
{{
|
|
'TAG_RETENTION.EXC' | translate
|
|
}}
|
|
</option>
|
|
</select>
|
|
</div>
|
|
<div class="clr-input-wrapper">
|
|
<input
|
|
class="clr-input"
|
|
autocomplete="off"
|
|
[ngClass]="{
|
|
'width-name-resource':
|
|
supportedFilters[i]?.type !==
|
|
'tag',
|
|
'width-tag-label':
|
|
supportedFilters[i]?.type ===
|
|
'tag'
|
|
}"
|
|
(input)="trimText($event)"
|
|
type="text"
|
|
#filterValue
|
|
size="14"
|
|
formControlName="value"
|
|
id="{{
|
|
'filter_' +
|
|
supportedFilters[i]?.type
|
|
}}" />
|
|
</div>
|
|
</div>
|
|
<div
|
|
class="select resource-box clr-select-wrapper"
|
|
*ngIf="
|
|
supportedFilters[i]?.style === 'radio' &&
|
|
supportedFilters[i]?.values.length > 1
|
|
">
|
|
<select
|
|
class="clr-select width-name-resource"
|
|
formControlName="value"
|
|
#selectedValue
|
|
id="{{
|
|
'select_' + supportedFilters[i]?.type
|
|
}}"
|
|
name="{{ supportedFilters[i]?.type }}">
|
|
<option value="">
|
|
{{ 'REPLICATION.ALL' | translate }}
|
|
</option>
|
|
<option
|
|
*ngFor="
|
|
let value of supportedFilters[i]
|
|
?.values
|
|
"
|
|
value="{{ value }}">
|
|
{{ value }}
|
|
</option>
|
|
</select>
|
|
</div>
|
|
<div
|
|
class="select flex"
|
|
*ngIf="
|
|
supportedFilters[i]?.type === 'label' &&
|
|
supportedFilters[i]?.style === 'list'
|
|
">
|
|
<div class="clr-select-wrapper mr-1">
|
|
<select
|
|
class="clr-select width-match-exclude"
|
|
formControlName="decoration">
|
|
<option value="matches">
|
|
{{
|
|
'TAG_RETENTION.MAT' | translate
|
|
}}
|
|
</option>
|
|
<option value="excludes">
|
|
{{
|
|
'TAG_RETENTION.EXC' | translate
|
|
}}
|
|
</option>
|
|
</select>
|
|
</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"
|
|
clrPosition="bottom-left"
|
|
*clrIfOpen>
|
|
<button
|
|
type="button"
|
|
class="dropdown-item flex"
|
|
*ngFor="
|
|
let value of supportedFilterLabels
|
|
"
|
|
(click)="
|
|
stickLabel(value.name)
|
|
">
|
|
<clr-icon
|
|
shape="check"
|
|
[style.visibility]="
|
|
isSelect(value.name)
|
|
? 'visible'
|
|
: 'hidden'
|
|
"></clr-icon>
|
|
<hbr-label-piece
|
|
[label]="value"
|
|
[labelWidth]="
|
|
130
|
|
"></hbr-label-piece>
|
|
</button>
|
|
<button
|
|
type="button"
|
|
class="dropdown-item space-between no-labels"
|
|
*ngIf="
|
|
!supportedFilterLabels?.length
|
|
">
|
|
<span class="alert-label">{{
|
|
'REPLICATION.NO_LABEL_INFO'
|
|
| translate
|
|
}}</span>
|
|
<span
|
|
class="alert-label go-link"
|
|
routerLink="/harbor/labels"
|
|
>{{
|
|
'CONFIG.LABEL'
|
|
| translate
|
|
}}</span
|
|
>
|
|
</button>
|
|
</clr-dropdown-menu>
|
|
</clr-dropdown>
|
|
</div>
|
|
</div>
|
|
<div
|
|
class="resource-box"
|
|
*ngIf="
|
|
supportedFilters[i]?.style === 'radio' &&
|
|
supportedFilters[i]?.values.length <= 1
|
|
">
|
|
<span>{{ supportedFilters[i]?.values }}</span>
|
|
</div>
|
|
<clr-tooltip>
|
|
<clr-icon
|
|
clrTooltipTrigger
|
|
shape="info-circle"
|
|
size="24"></clr-icon>
|
|
<clr-tooltip-content
|
|
clrPosition="top-left"
|
|
clrSize="md"
|
|
*clrIfOpen>
|
|
<span
|
|
class="tooltip-content"
|
|
*ngIf="
|
|
supportedFilters[i]?.type === 'name'
|
|
"
|
|
>{{
|
|
'TOOLTIP.NAME_FILTER' | translate
|
|
}}</span
|
|
>
|
|
<span
|
|
class="tooltip-content"
|
|
*ngIf="
|
|
supportedFilters[i]?.type === 'tag'
|
|
"
|
|
>{{
|
|
'TOOLTIP.TAG_FILTER' | translate
|
|
}}</span
|
|
>
|
|
<span
|
|
class="tooltip-content"
|
|
*ngIf="
|
|
supportedFilters[i]?.type ===
|
|
'label'
|
|
"
|
|
>{{
|
|
'TOOLTIP.LABEL_FILTER' | translate
|
|
}}</span
|
|
>
|
|
<span
|
|
class="tooltip-content"
|
|
*ngIf="
|
|
supportedFilters[i]?.type ===
|
|
'resource'
|
|
"
|
|
>{{
|
|
'TOOLTIP.RESOURCE_FILTER'
|
|
| translate
|
|
}}</span
|
|
>
|
|
</clr-tooltip-content>
|
|
</clr-tooltip>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!--destination registry-->
|
|
<div *ngIf="isPushMode" class="clr-form-control">
|
|
<label class="clr-control-label required">{{
|
|
'REPLICATION.DEST_REGISTRY' | translate
|
|
}}</label>
|
|
<div class="form-select clr-control-container">
|
|
<div class="clr-select-wrapper">
|
|
<select
|
|
class="clr-select width-input"
|
|
id="dest_registry"
|
|
(change)="targetChange($event)"
|
|
formControlName="dest_registry"
|
|
[compareWith]="equals">
|
|
<option class="display-none"></option>
|
|
<option
|
|
*ngFor="let target of targetList"
|
|
[ngValue]="target">
|
|
{{ target.name }}-{{ target.url }}
|
|
</option>
|
|
</select>
|
|
</div>
|
|
<div class="space-between">
|
|
<label
|
|
*ngIf="noEndpointInfo.length !== 0"
|
|
class="alert-label"
|
|
>{{ noEndpointInfo | translate }}</label
|
|
>
|
|
<span
|
|
class="alert-label go-link"
|
|
*ngIf="noEndpointInfo.length !== 0"
|
|
(click)="goRegistry()"
|
|
>{{ 'REPLICATION.ENDPOINTS' | translate }}</span
|
|
>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!--destination namespaces -->
|
|
<div class="clr-form-control">
|
|
<label for="dest_namespace" class="clr-control-label">{{
|
|
'REPLICATION.DESTINATION' | translate
|
|
}}</label>
|
|
<div
|
|
class="clr-control-container"
|
|
[class.clr-error]="
|
|
(ruleForm.controls.dest_namespace.dirty ||
|
|
ruleForm.controls.dest_namespace.touched) &&
|
|
ruleForm.controls.dest_namespace.invalid
|
|
">
|
|
<div class="clr-input-wrapper flex">
|
|
<label class="sub-label"
|
|
>{{ 'REPLICATION.NAMESPACE' | translate }}:</label
|
|
>
|
|
<input
|
|
autocomplete="off"
|
|
class="clr-input width-name-resource"
|
|
formControlName="dest_namespace"
|
|
type="text"
|
|
id="dest_namespace"
|
|
pattern="^[a-z0-9]+(?:[/._-][a-z0-9]+)*$"
|
|
maxlength="255" />
|
|
<clr-tooltip class="des-tooltip">
|
|
<clr-icon
|
|
clrTooltipTrigger
|
|
shape="info-circle"
|
|
size="24"></clr-icon>
|
|
<clr-tooltip-content
|
|
clrPosition="top-left"
|
|
clrSize="lg"
|
|
*clrIfOpen>
|
|
<span>{{
|
|
'TOOLTIP.DESTINATION_NAMESPACE' | translate
|
|
}}</span>
|
|
</clr-tooltip-content>
|
|
</clr-tooltip>
|
|
</div>
|
|
<clr-control-error
|
|
class="margin-left-90px"
|
|
*ngIf="
|
|
(ruleForm.controls.dest_namespace.dirty ||
|
|
ruleForm.controls.dest_namespace.touched) &&
|
|
ruleForm.controls.dest_namespace.invalid
|
|
">
|
|
{{ 'REPLICATION.NAMESPACE_TOOLTIP' | translate }}
|
|
</clr-control-error>
|
|
</div>
|
|
</div>
|
|
<!--destination namespaces -->
|
|
<div class="clr-form-control flattening">
|
|
<label
|
|
for="dest_namespace_replace_count"
|
|
class="clr-control-label"></label>
|
|
<div class="clr-control-container">
|
|
<div class="clr-select-wrapper flex">
|
|
<label class="sub-label"
|
|
>{{
|
|
'REPLICATION.REPO_FLATTENING' | translate
|
|
}}:</label
|
|
>
|
|
<select
|
|
[attr.disabled]="
|
|
ruleForm.controls.dest_namespace.invalid ||
|
|
!ruleForm.controls.dest_namespace.value
|
|
? 'disabled'
|
|
: null
|
|
"
|
|
id="dest_namespace_replace_count"
|
|
formControlName="dest_namespace_replace_count"
|
|
class="clr-select width-name-resource">
|
|
<option
|
|
*ngFor="let item of flattenLevelMap | keyvalue"
|
|
[value]="item.key">
|
|
{{ item.value | translate }}
|
|
</option>
|
|
</select>
|
|
<clr-tooltip class="des-tooltip">
|
|
<clr-icon
|
|
clrTooltipTrigger
|
|
shape="info-circle"
|
|
size="24"></clr-icon>
|
|
<clr-tooltip-content
|
|
class="flatten"
|
|
clrPosition="top-left"
|
|
clrSize="lg"
|
|
*clrIfOpen>
|
|
<div>
|
|
{{
|
|
'REPLICATION.FLATTEN_LEVEL_TIP'
|
|
| translate
|
|
}}
|
|
</div>
|
|
<div>
|
|
{{
|
|
'REPLICATION.FLATTEN_LEVEL_TIP_ALL'
|
|
| translate
|
|
}}
|
|
</div>
|
|
<div>
|
|
{{
|
|
'REPLICATION.FLATTEN_LEVEL_TIP_NO'
|
|
| translate
|
|
}}
|
|
</div>
|
|
<div>
|
|
{{
|
|
'REPLICATION.FLATTEN_LEVEL_TIP_1'
|
|
| translate
|
|
}}
|
|
</div>
|
|
<div>
|
|
{{
|
|
'REPLICATION.FLATTEN_LEVEL_TIP_2'
|
|
| translate
|
|
}}
|
|
</div>
|
|
<div>
|
|
{{
|
|
'REPLICATION.FLATTEN_LEVEL_TIP_3'
|
|
| translate
|
|
}}
|
|
</div>
|
|
</clr-tooltip-content>
|
|
</clr-tooltip>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!--Trigger-->
|
|
<div class="clr-form-control">
|
|
<label class="clr-control-label required">{{
|
|
'REPLICATION.TRIGGER_MODE' | translate
|
|
}}</label>
|
|
<div class="clr-control-container">
|
|
<div formGroupName="trigger">
|
|
<!--on trigger-->
|
|
<div class="select clr-select-wrapper">
|
|
<select
|
|
(change)="changeTrigger($event)"
|
|
id="ruleTrigger"
|
|
formControlName="type"
|
|
class="clr-select width-input">
|
|
<option
|
|
*ngFor="let trigger of supportedTriggers"
|
|
[value]="trigger">
|
|
{{
|
|
'REPLICATION.' + trigger.toUpperCase()
|
|
| translate
|
|
}}
|
|
</option>
|
|
</select>
|
|
</div>
|
|
<div
|
|
formGroupName="trigger_settings"
|
|
class="clr-form-control">
|
|
<div class="flex" [hidden]="isNotSchedule()">
|
|
<label for="targetCron" class="required"
|
|
>Cron String</label
|
|
>
|
|
<div
|
|
class="clr-control-container"
|
|
[class.clr-error]="
|
|
cronInputShouldShowError()
|
|
">
|
|
<div class="clr-input-wrapper">
|
|
<input
|
|
autocomplete="off"
|
|
(input)="inputInvalid($event)"
|
|
type="text"
|
|
name="targetCron"
|
|
id="targetCron"
|
|
required
|
|
pattern="^0\s(?!(\*\s)).+$"
|
|
class="form-control cron-input clr-input"
|
|
formControlName="cron" />
|
|
</div>
|
|
<clr-control-error
|
|
*ngIf="cronInputShouldShowError()">
|
|
{{
|
|
'REPLICATION.CRON_ERROR_TIP'
|
|
| translate
|
|
}}
|
|
</clr-control-error>
|
|
</div>
|
|
<a
|
|
href="javascript:void(0)"
|
|
role="tooltip"
|
|
aria-haspopup="true"
|
|
class="tooltip tooltip-lg tooltip-top-left top-7 cron-tooltip">
|
|
<clr-icon
|
|
shape="info-circle"
|
|
class="info-tips-icon"
|
|
size="24"></clr-icon>
|
|
<div class="tooltip-content table-box">
|
|
<cron-tooltip></cron-tooltip>
|
|
</div>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div
|
|
class="clr-checkbox-wrapper clr-form-control mt-0"
|
|
[hidden]="isNotEventBased()">
|
|
<input
|
|
type="checkbox"
|
|
class="clr-checkbox"
|
|
[checked]="false"
|
|
id="ruleDeletion"
|
|
formControlName="deletion" />
|
|
<label for="ruleDeletion">{{
|
|
'REPLICATION.DELETE_REMOTE_IMAGES' | translate
|
|
}}</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!--speed-->
|
|
<div class="clr-form-control bandwidth">
|
|
<label for="speed" class="required clr-control-label"
|
|
>{{ 'REPLICATION.BANDWIDTH' | translate }}
|
|
</label>
|
|
<div
|
|
class="clr-control-container"
|
|
[class.clr-error]="
|
|
ruleForm.controls.speed.invalid &&
|
|
(ruleForm.controls.speed.dirty ||
|
|
ruleForm.controls.speed.touched)
|
|
">
|
|
<div class="clr-checkbox-wrapper speed">
|
|
<input
|
|
type="text"
|
|
id="speed"
|
|
name="speed"
|
|
class="clr-input"
|
|
formControlName="speed"
|
|
autocomplete="off"
|
|
required
|
|
pattern="(^-1$)|(^([1-9]+)([0-9]+)*$)"
|
|
maxlength="5" />
|
|
<clr-icon
|
|
class="clr-validate-icon"
|
|
shape="exclamation-circle"></clr-icon>
|
|
</div>
|
|
<div
|
|
class="clr-select-wrapper unit-select"
|
|
[class.unit]="
|
|
ruleForm.controls.speed.invalid &&
|
|
(ruleForm.controls.speed.dirty ||
|
|
ruleForm.controls.speed.touched)
|
|
">
|
|
<select
|
|
class="clr-select unit-select"
|
|
[ngModelOptions]="{ standalone: true }"
|
|
id="speed_unit"
|
|
name="speed_unit"
|
|
[(ngModel)]="selectedUnit">
|
|
<option
|
|
*ngFor="let unit of speedUnits"
|
|
[value]="unit.UNIT">
|
|
{{ unit.UNIT }}
|
|
</option>
|
|
</select>
|
|
<clr-tooltip class="ml-10px">
|
|
<clr-icon
|
|
clrTooltipTrigger
|
|
shape="info-circle"
|
|
size="24"></clr-icon>
|
|
<clr-tooltip-content
|
|
clrPosition="top-left"
|
|
clrSize="lg"
|
|
*clrIfOpen>
|
|
<span>{{
|
|
'REPLICATION.BANDWIDTH_TOOLTIP' | translate
|
|
}}</span>
|
|
</clr-tooltip-content>
|
|
</clr-tooltip>
|
|
</div>
|
|
<clr-control-error
|
|
*ngIf="
|
|
ruleForm.controls.speed.invalid &&
|
|
(ruleForm.controls.speed.dirty ||
|
|
ruleForm.controls.speed.touched)
|
|
"
|
|
class="tooltip-content">
|
|
{{ 'REPLICATION.BANDWIDTH_ERROR_TIP' | translate }}
|
|
</clr-control-error>
|
|
</div>
|
|
</div>
|
|
|
|
<!--override and enable and chunk-->
|
|
<div class="clr-form-control">
|
|
<label class="clr-control-label">{{
|
|
'SCANNER.OPTIONS' | translate
|
|
}}</label>
|
|
|
|
<div class="clr-control-container clr-control-inline">
|
|
<div class="clr-checkbox-wrapper">
|
|
<input
|
|
type="checkbox"
|
|
class="clr-checkbox"
|
|
[checked]="true"
|
|
id="overridePolicy"
|
|
formControlName="override" />
|
|
<label for="overridePolicy" class="clr-control-label"
|
|
>{{ 'REPLICATION.OVERRIDE_INFO' | translate }}
|
|
<clr-tooltip class="override-tooltip">
|
|
<clr-icon
|
|
clrTooltipTrigger
|
|
shape="info-circle"
|
|
size="24"></clr-icon>
|
|
<clr-tooltip-content
|
|
clrPosition="top-left"
|
|
clrSize="md"
|
|
*clrIfOpen>
|
|
<span>{{
|
|
'TOOLTIP.OVERRIDE' | translate
|
|
}}</span>
|
|
</clr-tooltip-content>
|
|
</clr-tooltip>
|
|
</label>
|
|
</div>
|
|
<div
|
|
class="clr-checkbox-wrapper"
|
|
[hidden]="!showChunkOption">
|
|
<input
|
|
type="checkbox"
|
|
id="by-chunk"
|
|
formControlName="copy_by_chunk"
|
|
class="clr-checkbox" />
|
|
<label for="by-chunk" class="clr-control-label"
|
|
>{{ 'REPLICATION.COPY_BY_CHUNK' | translate }}
|
|
<clr-tooltip class="override-tooltip">
|
|
<clr-icon
|
|
clrTooltipTrigger
|
|
shape="info-circle"
|
|
size="24"></clr-icon>
|
|
<clr-tooltip-content
|
|
clrPosition="top-left"
|
|
clrSize="md"
|
|
*clrIfOpen>
|
|
<span>{{
|
|
'REPLICATION.COPY_BY_CHUNK_TIP'
|
|
| translate
|
|
}}</span>
|
|
</clr-tooltip-content>
|
|
</clr-tooltip>
|
|
</label>
|
|
</div>
|
|
<div class="clr-checkbox-wrapper" [hidden]="policyId < 0">
|
|
<input
|
|
type="checkbox"
|
|
[checked]="true"
|
|
id="enablePolicy"
|
|
formControlName="enabled"
|
|
class="clr-checkbox" />
|
|
<label for="enablePolicy" class="clr-control-label">{{
|
|
'REPLICATION.ENABLED_RULE' | translate
|
|
}}</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button
|
|
type="button"
|
|
id="ruleBtnCancel"
|
|
class="btn btn-outline"
|
|
[disabled]="inProgress"
|
|
(click)="onCancel()">
|
|
{{ 'BUTTON.CANCEL' | translate }}
|
|
</button>
|
|
<button
|
|
type="submit"
|
|
id="ruleBtnOk"
|
|
class="btn btn-primary"
|
|
[clrLoading]="inProgress"
|
|
(click)="onSubmit()"
|
|
[disabled]="inProgress || !isValid || !hasFormChange()">
|
|
{{ 'BUTTON.SAVE' | translate }}
|
|
</button>
|
|
</div>
|
|
</clr-modal>
|