From 0edc01a39530b6df17df2959cde5937dadcf1534 Mon Sep 17 00:00:00 2001 From: Shijun Sun <30999793+AllForNothing@users.noreply.github.com> Date: Tue, 1 Nov 2022 12:33:40 +0800 Subject: [PATCH] Add copy_by-chunk checkbox for replication rule (#17617) Signed-off-by: AllForNothing Signed-off-by: AllForNothing --- .../create-edit-rule.component.html | 46 +++++++++++++---- .../create-edit-rule.component.scss | 14 ++++- .../create-edit-rule.component.spec.ts | 3 ++ .../create-edit-rule.component.ts | 51 +++++++++++++++---- src/portal/src/i18n/lang/de-de-lang.json | 4 +- src/portal/src/i18n/lang/en-us-lang.json | 4 +- src/portal/src/i18n/lang/es-es-lang.json | 4 +- src/portal/src/i18n/lang/fr-fr-lang.json | 4 +- src/portal/src/i18n/lang/pt-br-lang.json | 4 +- src/portal/src/i18n/lang/tr-tr-lang.json | 4 +- src/portal/src/i18n/lang/zh-cn-lang.json | 4 +- src/portal/src/i18n/lang/zh-tw-lang.json | 4 +- 12 files changed, 119 insertions(+), 27 deletions(-) diff --git a/src/portal/src/app/base/left-side-nav/replication/replication/create-edit-rule/create-edit-rule.component.html b/src/portal/src/app/base/left-side-nav/replication/replication/create-edit-rule/create-edit-rule.component.html index 0e92d0511..90ae5f419 100644 --- a/src/portal/src/app/base/left-side-nav/replication/replication/create-edit-rule/create-edit-rule.component.html +++ b/src/portal/src/app/base/left-side-nav/replication/replication/create-edit-rule/create-edit-rule.component.html @@ -537,7 +537,7 @@ -
+
@@ -704,7 +704,7 @@
-
+
@@ -776,18 +776,21 @@
- +
- -
-
+ + +
+
-
+ class="clr-checkbox-wrapper" + [hidden]="!showChunkOption"> + + +
+
{ listRegistries() { return of(mockEndpoints).pipe(delay(0)); }, + getRegistryInfo() { + return of(mockRegistryInfo).pipe(delay(0)); + }, }; beforeEach(async () => { await TestBed.configureTestingModule({ 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 e84b6f8e8..ae3c67707 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 @@ -53,6 +53,7 @@ import { } from '../../replication'; import { errorHandler as errorHandlerFn } from '../../../../../shared/units/shared.utils'; import { ReplicationPolicy } from '../../../../../../../ng-swagger-gen/models/replication-policy'; +import { RegistryInfo } from 'ng-swagger-gen/models'; const PREFIX: string = '0 '; const PAGE_SIZE: number = 100; @@ -116,6 +117,7 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy { ]; selectedUnit: string = BandwidthUnit.KB; copySpeedUnit: string = BandwidthUnit.KB; + showChunkOption: boolean = false; constructor( private fb: UntypedFormBuilder, private repService: ReplicationService, @@ -128,18 +130,21 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy { } initRegistryInfo(id: number): void { - this.onGoing = true; - this.repService - .getRegistryInfo(id) - .pipe(finalize(() => (this.onGoing = false))) - .subscribe( - adapter => { + this.inProgress = true; + this.endpointService + .getRegistryInfo({ id: id }) + .pipe(finalize(() => (this.inProgress = false))) + .subscribe({ + next: adapter => { this.setFilterAndTrigger(adapter); + if (id) { + this.checkChunkOption(id, adapter); + } }, - (error: any) => { + error: error => { this.inlineAlert.showInlineError(error); - } - ); + }, + }); } getAllRegistries() { this.endpointService @@ -240,6 +245,7 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy { pushModeChange(): void { this.setFilter([]); this.initRegistryInfo(0); + this.checkChunkOption(this.ruleForm?.get('dest_registry')?.value?.id); } pullModeChange(): void { @@ -247,6 +253,8 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy { if (selectId) { this.setFilter([]); this.initRegistryInfo(selectId.id); + } else { + this.checkChunkOption(0); } } @@ -316,6 +324,7 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy { deletion: false, override: true, speed: -1, + copy_by_chunk: false, }); } @@ -348,6 +357,7 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy { override: true, dest_namespace_replace_count: Flatten_Level.FLATTEN_LEVEl_1, speed: -1, + copy_by_chunk: false, }); this.isPushMode = true; this.selectedUnit = BandwidthUnit.KB; @@ -355,6 +365,7 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy { updateRuleFormAndCopyUpdateForm(rule: ReplicationPolicy): void { this.isPushMode = rule.dest_registry.id !== 0; + this.checkChunkOption(rule.dest_registry.id || rule.src_registry.id); setTimeout(() => { // convert speed unit to KB or MB let speed: number = this.convertToInputValue(rule.speed); @@ -374,6 +385,7 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy { enabled: rule.enabled, override: rule.override, speed: speed, + copy_by_chunk: rule.copy_by_chunk, }); let filtersArray = this.getFilterArray(rule); this.noSelectedEndpoint = false; @@ -448,6 +460,7 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy { return; } this.noSelectedEndpoint = false; + this.initRegistryInfo(this.ruleForm.get('dest_registry').value.id); } } @@ -504,6 +517,10 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy { copyRuleForm.filters.splice(i, 1); } } + if (!this.showChunkOption) { + delete copyRuleForm?.copy_by_chunk; + delete this.ruleForm?.value?.copy_by_chunk; + } if (this.policyId < 0) { this.repService.createReplicationRule(copyRuleForm).subscribe( @@ -549,6 +566,7 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy { this.policyId = -1; this.createEditRuleOpened = true; this.noEndpointInfo = ''; + this.showChunkOption = false; if (this.targetList.length === 0) { this.noEndpointInfo = 'REPLICATION.NO_ENDPOINT_INFO'; } @@ -876,4 +894,19 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy { return label; } } + checkChunkOption(id: number, info?: RegistryInfo) { + this.showChunkOption = false; + this.ruleForm.get('copy_by_chunk').reset(false); + if (info) { + this.showChunkOption = info.supported_copy_by_chunk; + } else { + if (id) { + this.endpointService.getRegistryInfo({ id }).subscribe(res => { + if (res) { + this.showChunkOption = res.supported_copy_by_chunk; + } + }); + } + } + } } diff --git a/src/portal/src/i18n/lang/de-de-lang.json b/src/portal/src/i18n/lang/de-de-lang.json index 9e7323e76..e8aba2172 100644 --- a/src/portal/src/i18n/lang/de-de-lang.json +++ b/src/portal/src/i18n/lang/de-de-lang.json @@ -659,7 +659,9 @@ "BANDWIDTH_TOOLTIP": "Legt die maximale Netzwerkbandbreite für jede Ausführung fest. Bitte auf die Anzahl der parallelen Ausführungen achten. Für umbegrenzte Bandbreite, bitte -1 eingeben", "UNLIMITED": "Unbegrenzt", "UNREACHABLE_SOURCE_REGISTRY": "Failed to connect to the source registry, please make sure the source registry is available before editing this rule: {{error}}", - "CRON_ERROR_TIP": "Field is required and \"*\" is not allowed for the \"Minutes\" field" + "CRON_ERROR_TIP": "Field is required and \"*\" is not allowed for the \"Minutes\" field", + "COPY_BY_CHUNK": "Copy by chunk", + "COPY_BY_CHUNK_TIP": "Specify whether to copy the blob by chunk. Transfer by chunk may increase the number of API requests." }, "DESTINATION": { "NEW_ENDPOINT": "Neuer Endpunkt", diff --git a/src/portal/src/i18n/lang/en-us-lang.json b/src/portal/src/i18n/lang/en-us-lang.json index 831a75ae9..4b19ffbfb 100644 --- a/src/portal/src/i18n/lang/en-us-lang.json +++ b/src/portal/src/i18n/lang/en-us-lang.json @@ -659,7 +659,9 @@ "BANDWIDTH_TOOLTIP": "Set the maximum network bandwidth for each execution. Please pay attention to the number of concurrent executions. For unlimited bandwidth, please enter -1", "UNLIMITED": "Unlimited", "UNREACHABLE_SOURCE_REGISTRY": "Failed to connect to the source registry, please make sure the source registry is available before editing this rule: {{error}}", - "CRON_ERROR_TIP": "Field is required and \"*\" is not allowed for the \"Minutes\" field" + "CRON_ERROR_TIP": "Field is required and \"*\" is not allowed for the \"Minutes\" field", + "COPY_BY_CHUNK": "Copy by chunk", + "COPY_BY_CHUNK_TIP": "Specify whether to copy the blob by chunk. Transfer by chunk may increase the number of API requests." }, "DESTINATION": { "NEW_ENDPOINT": "New Endpoint", diff --git a/src/portal/src/i18n/lang/es-es-lang.json b/src/portal/src/i18n/lang/es-es-lang.json index edd2052f0..0fb2fa40e 100644 --- a/src/portal/src/i18n/lang/es-es-lang.json +++ b/src/portal/src/i18n/lang/es-es-lang.json @@ -661,7 +661,9 @@ "BANDWIDTH_TOOLTIP": "Set the maximum network bandwidth for each execution. Please pay attention to the number of concurrent executions. For unlimited bandwidth, please enter -1", "UNLIMITED": "Unlimited", "UNREACHABLE_SOURCE_REGISTRY": "Failed to connect to the source registry, please make sure the source registry is available before editing this rule: {{error}}", - "CRON_ERROR_TIP": "Field is required and \"*\" is not allowed for the \"Minutes\" field" + "CRON_ERROR_TIP": "Field is required and \"*\" is not allowed for the \"Minutes\" field", + "COPY_BY_CHUNK": "Copy by chunk", + "COPY_BY_CHUNK_TIP": "Specify whether to copy the blob by chunk. Transfer by chunk may increase the number of API requests." }, "DESTINATION": { "NEW_ENDPOINT": "Nuevo Endpoint", diff --git a/src/portal/src/i18n/lang/fr-fr-lang.json b/src/portal/src/i18n/lang/fr-fr-lang.json index 3d46e0053..a5b674c36 100644 --- a/src/portal/src/i18n/lang/fr-fr-lang.json +++ b/src/portal/src/i18n/lang/fr-fr-lang.json @@ -649,7 +649,9 @@ "BANDWIDTH_TOOLTIP": "Définissez la bande passante réseau maximale pour chaque exécution. Veuillez faire attention au nombre d'exécutions simultanées. Pour une bande passante illimitée, veuillez entrer -1", "UNLIMITED": "Illimitée", "UNREACHABLE_SOURCE_REGISTRY": "Failed to connect to the source registry, please make sure the source registry is available before editing this rule: {{error}}", - "CRON_ERROR_TIP": "Field is required and \"*\" is not allowed for the \"Minutes\" field" + "CRON_ERROR_TIP": "Field is required and \"*\" is not allowed for the \"Minutes\" field", + "COPY_BY_CHUNK": "Copy by chunk", + "COPY_BY_CHUNK_TIP": "Specify whether to copy the blob by chunk. Transfer by chunk may increase the number of API requests." }, "DESTINATION": { "NEW_ENDPOINT": "Nouveau Endpoint", diff --git a/src/portal/src/i18n/lang/pt-br-lang.json b/src/portal/src/i18n/lang/pt-br-lang.json index 7535082dc..d6832ad1b 100644 --- a/src/portal/src/i18n/lang/pt-br-lang.json +++ b/src/portal/src/i18n/lang/pt-br-lang.json @@ -659,7 +659,9 @@ "BANDWIDTH_TOOLTIP": "Informe o limite de banda para cada execução. Tome cuidado e observe a relação com o número de execuções simultâneas. Para remover qualquer limite, informe -1", "UNLIMITED": "Ilimitado", "UNREACHABLE_SOURCE_REGISTRY": "Failed to connect to the source registry, please make sure the source registry is available before editing this rule: {{error}}", - "CRON_ERROR_TIP": "Field is required and \"*\"is not allowed for the \"Minutes\" field" + "CRON_ERROR_TIP": "Field is required and \"*\"is not allowed for the \"Minutes\" field", + "COPY_BY_CHUNK": "Copy by chunk", + "COPY_BY_CHUNK_TIP": "Specify whether to copy the blob by chunk. Transfer by chunk may increase the number of API requests." }, "DESTINATION": { "NEW_ENDPOINT": "Novo Endereço", diff --git a/src/portal/src/i18n/lang/tr-tr-lang.json b/src/portal/src/i18n/lang/tr-tr-lang.json index bf1b22300..f1cddd514 100644 --- a/src/portal/src/i18n/lang/tr-tr-lang.json +++ b/src/portal/src/i18n/lang/tr-tr-lang.json @@ -659,7 +659,9 @@ "BANDWIDTH_TOOLTIP": "Set the maximum network bandwidth for each execution. Please pay attention to the number of concurrent executions. For unlimited bandwidth, please enter -1", "UNLIMITED": "Unlimited", "UNREACHABLE_SOURCE_REGISTRY": "Failed to connect to the source registry, please make sure the source registry is available before editing this rule: {{error}}", - "CRON_ERROR_TIP": "Field is required and \"*\" is not allowed for the \"Minutes\" field" + "CRON_ERROR_TIP": "Field is required and \"*\" is not allowed for the \"Minutes\" field", + "COPY_BY_CHUNK": "Copy by chunk", + "COPY_BY_CHUNK_TIP": "Specify whether to copy the blob by chunk. Transfer by chunk may increase the number of API requests." }, "DESTINATION": { "NEW_ENDPOINT": "Yeni Uç Nokta", diff --git a/src/portal/src/i18n/lang/zh-cn-lang.json b/src/portal/src/i18n/lang/zh-cn-lang.json index 857dbe71f..aa20d22e3 100644 --- a/src/portal/src/i18n/lang/zh-cn-lang.json +++ b/src/portal/src/i18n/lang/zh-cn-lang.json @@ -661,7 +661,9 @@ "BANDWIDTH_TOOLTIP": "设置执行该条同步规则时的最大网络带宽。实际总带宽需要考虑并发执行的情况。如无需限制,请输入-1", "UNLIMITED": "无限制", "UNREACHABLE_SOURCE_REGISTRY": "连接源仓库失败,在编辑此规则前请先确保源仓库可用: {{error}}", - "CRON_ERROR_TIP": "此项必填且\"分钟\"项不能为\"*\"" + "CRON_ERROR_TIP": "此项必填且\"分钟\"项不能为\"*\"", + "COPY_BY_CHUNK": "分块复制", + "COPY_BY_CHUNK_TIP": "请指定是否开启分块复制。开启此项可能导致相应的 API 请求数量增加。" }, "DESTINATION": { "NEW_ENDPOINT": "新建目标", diff --git a/src/portal/src/i18n/lang/zh-tw-lang.json b/src/portal/src/i18n/lang/zh-tw-lang.json index fb19844c9..de8d2a2dc 100644 --- a/src/portal/src/i18n/lang/zh-tw-lang.json +++ b/src/portal/src/i18n/lang/zh-tw-lang.json @@ -656,7 +656,9 @@ "BANDWIDTH_TOOLTIP": "Set the maximum network bandwidth for each execution. Please pay attention to the number of concurrent executions. For unlimited bandwidth, please enter -1", "UNLIMITED": "Unlimited", "UNREACHABLE_SOURCE_REGISTRY": "Failed to connect to the source registry, please make sure the source registry is available before editing this rule: {{error}}", - "CRON_ERROR_TIP": "Field is required and \"*\" is not allowed for the \"Minutes\" field" + "CRON_ERROR_TIP": "Field is required and \"*\" is not allowed for the \"Minutes\" field", + "COPY_BY_CHUNK": "Copy by chunk", + "COPY_BY_CHUNK_TIP": "Specify whether to copy the blob by chunk. Transfer by chunk may increase the number of API requests." }, "DESTINATION":{ "NEW_ENDPOINT": "新建目標",