2 [columnNumbers]="{ md: 4 }">
3 <ng-container *cdFormLoading="loading">
4 <form name="storageClassForm"
6 [formGroup]="storageClassForm"
10 {{ action | titlecase }} {{ resource | upperFirst }}
12 <cd-help-text [formAllFieldsRequired]="true"></cd-help-text>
14 <div class="form-item">
18 for="storageClassType"
19 formControlName="storageClassType"
20 [helperText]="helpTextLabels.storageClassText"
22 [invalid]="storageClassForm.showError('storageClassType', formDir, 'required')"
23 [invalidText]="storageError"
25 <option *ngFor="let opt of storageClassOptions"
31 <ng-template #storageError>
32 @if (storageClassForm.showError('storageClassType', formDir, 'required')) {
33 <span class="invalid-feedback"
34 i18n> This field is required. </span>
38 <div class="form-item form-item-append"
43 label="Zone Group Name"
45 formControlName="zonegroup"
47 [invalid]="storageClassForm.showError('zonegroup', formDir, 'required')"
48 (change)="onZonegroupChange()"
49 [invalidText]="zonegroupError"
52 *ngFor="let zonegrp of zonegroupNames"
53 [value]="zonegrp.name"
54 [selected]="zonegrp.name === storageClassForm.getValue('zonegroup')"
60 <ng-template #zonegroupError>
61 @if (storageClassForm.showError('zonegroup', formDir, 'required')) {
62 <span class="invalid-feedback"
63 i18n>This field is required.</span>
67 @if( isTierMatch(TIER_TYPE.CLOUD_TIER, TIER_TYPE.GLACIER )){
69 <ng-container *ngTemplateOutlet="storageClassField"></ng-container>
72 @if( isTierMatch(TIER_TYPE.LOCAL )){
77 formControlName="zone"
79 [invalid]="storageClassForm.showError('zone', formDir, 'required')"
80 [invalidText]="zoneError"
83 i18n>--Select--</option>
84 <option *ngFor="let zone of zones"
86 [selected]="zone.name === storageClassForm.getValue('zone')"
91 <ng-template #zoneError>
93 class="invalid-feedback"
94 *ngIf="storageClassForm.showError('zone', formDir, 'required')"
96 >This field is required.</span
102 @if( isTierMatch(TIER_TYPE.LOCAL )){
103 <ng-container *ngTemplateOutlet="storageClassField"></ng-container>
104 <div class="form-item">
105 <cd-alert-panel type="info"
108 (action)="navigateCreatePool()">
109 <span i18n>To create a new pool click <a [routerLink]="[POOL.PATH]">here</a></span>
114 formControlName="pool"
116 [invalid]="storageClassForm.showError('pool', formDir, 'required')"
117 [invalidText]="poolError"
120 i18n>--Select--</option>
121 <option *ngFor="let pool of rgwPools"
122 [value]="pool.pool_name"
127 <ng-template #poolError>
129 class="invalid-feedback"
130 *ngIf="storageClassForm.showError('pool', formDir, 'required')"
132 >This field is required.</span
136 } @if( isTierMatch( TIER_TYPE.CLOUD_TIER, TIER_TYPE.GLACIER )){
138 <div class="form-item form-item-append"
141 <!-- Target Region -->
143 labelInputID="region"
145 [invalid]="storageClassForm.showError('region', formDir, 'required')"
146 [invalidText]="regionError"
147 [helperText]="helpTextLabels.targetRegionText"
153 formControlName="region"
154 placeholder="e.g, us-east-1"
156 [invalid]="storageClassForm.showError('region', formDir, 'required')"
159 <ng-template #regionError>
160 @if (storageClassForm.showError('region', formDir, 'required')) {
161 <span class="invalid-feedback"
162 i18n>This field is required.</span>
167 <!-- Target Endpoint -->
169 labelInputID="target_endpoint"
172 storageClassForm.showError('target_endpoint', formDir, 'invalidURL') ||
173 storageClassForm.showError('target_endpoint', formDir, 'required')
175 [invalidText]="endpointError"
176 [helperText]="helpTextLabels.targetEndpointText"
181 placeholder="http://ceph-node-00.com:80"
184 formControlName="target_endpoint"
186 storageClassForm.showError('target_endpoint', formDir, 'invalidURL') ||
187 storageClassForm.showError('target_endpoint', formDir, 'required')
189 [invalidText]="endpointError"
192 <ng-template #endpointError>
193 @if (storageClassForm.showError('target_endpoint', formDir, 'required')) {
194 <span class="invalid-feedback"
195 i18n> This field is required. </span>
196 } @else if (storageClassForm.showError('target_endpoint', formDir, 'invalidURL')) {
197 <span class="invalid-feedback"
198 i18n> Please enter a valid URL.</span>
204 <div class="form-item">
206 [columnNumbers]="{ md: 12 }"
209 labelInputID="access_key"
210 [invalid]="storageClassForm.showError('access_key', formDir, 'required')"
211 [invalidText]="accessError"
212 [helperText]="helpTextLabels.targetAccessKeyText"
219 formControlName="access_key"
220 [invalid]="storageClassForm.showError('access_key', formDir, 'required')"
222 </cds-password-label>
223 <cd-copy-2-clipboard-button class="clipboard"></cd-copy-2-clipboard-button>
224 <ng-template #accessError>
225 @if (storageClassForm.showError('access_key', formDir, 'required')) {
226 <span class="invalid-feedback"
227 i18n> This field is required. </span>
233 <div class="form-item">
235 [columnNumbers]="{ md: 12 }"
238 labelInputID="secret_key"
239 [helperText]="helpTextLabels.targetSecretKeyText"
240 [invalid]="storageClassForm.showError('secret_key', formDir, 'required')"
241 [invalidText]="secretError"
248 formControlName="secret_key"
249 [invalid]="storageClassForm.showError('secret_key', formDir, 'required')"
251 </cds-password-label>
252 <cd-copy-2-clipboard-button class="clipboard"> </cd-copy-2-clipboard-button>
253 <ng-template #secretError>
254 @if (storageClassForm.showError('secret_key', formDir, 'required')) {
255 <span class="invalid-feedback"
256 i18n> This field is required. </span>
262 <div class="form-item">
264 labelInputID="target_path"
266 [invalid]="storageClassForm.showError('target_path', formDir, 'required')"
267 [invalidText]="targetError"
268 [helperText]="helpTextLabels.targetPathText"
274 formControlName="target_path"
275 [invalid]="storageClassForm.showError('target_path', formDir, 'required')"
278 <ng-template #targetError>
279 @if (storageClassForm.showError('target_path', formDir, 'required')) {
280 <span class="invalid-feedback"
281 i18n> This field is required. </span>
285 <div class="form-item">
287 id="allow_read_through"
288 formControlName="allow_read_through"
289 cdOptionalField="Allow Read Through"
291 (change)="onAllowReadThroughChange($event)"
293 <cd-help-text>{{ helpTextLabels?.allowReadThroughText }}</cd-help-text>
296 <div class="form-item">
298 id="retain_head_object"
299 formControlName="retain_head_object"
300 cdOptionalField="Head Object (Stub File)"
302 >Head Object (Stub File)
303 <cd-help-text>{{ helpTextLabels?.retainHeadObjectText }}</cd-help-text>
306 <div class="form-item form-item-append"
310 name="read_through_restore_days"
311 formControlName="read_through_restore_days"
312 id="read_through_restore_days"
314 label="ReadThrough Restore Days"
315 [helperText]="helpTextLabels.readthroughrestoreDaysText"
320 storageClassForm.controls.read_through_restore_days.invalid &&
321 storageClassForm.controls.read_through_restore_days.dirty
323 [invalidText]="readThroughError"
325 <ng-template #readThroughError>
326 @if (storageClassForm.showError('read_through_restore_days', formDir, 'pattern')) {
327 <span class="invalid-feedback"
329 ReadThrough Restore Days must be positive.
336 formControlName="restore_storage_class"
337 label="Restore Storage Class"
338 id="restore_storage_class"
339 [helperText]="helpTextLabels.restoreStorageClassText"
343 i18n>-- Select the glacier restore storage class --</option>
344 <option [ngValue]="standard"
345 i18n>Standard</option>
350 } @if(isTierMatch(TIER_TYPE.GLACIER)){
352 <legend class="cd-header"
353 i18n>Glacier Configuration</legend>
354 <div class="form-item form-item-append"
358 formControlName="glacier_restore_tier_type"
359 label="Glacier Restore Tier Type"
360 cdRequiredField="Glacier Restore Tier Type"
361 id="glacier_restore_tier_type"
363 storageClassForm.controls.glacier_restore_tier_type.invalid &&
364 storageClassForm.controls.glacier_restore_tier_type.dirty
366 [invalidText]="glacierError"
367 [helperText]="helpTextLabels.tiertypeText"
371 i18n>-- Select the glacier restore tier type --</option>
372 <option [ngValue]="standard"
373 i18n>Standard</option>
374 <option [ngValue]="expedited"
375 i18n>Expedited</option>
377 <ng-template #glacierError>
378 @if (storageClassForm.showError('glacier_restore_tier_type', formDir, 'required')) {
379 <span class="invalid-feedback"
380 i18n> This field is required. </span>
386 [id]="'glacier_restore_days'"
387 [formControlName]="'glacier_restore_days'"
388 [label]="'Glacier Restore Days'"
389 [helperText]="helpTextLabels.restoreDaysText"
395 storageClassForm.controls.glacier_restore_days.invalid &&
396 storageClassForm.controls.glacier_restore_days.dirty
398 [invalidText]="glacierRestoreError"
401 <ng-template #glacierRestoreError>
402 @if (storageClassForm.showError('glacier_restore_days', formDir, 'pattern')) {
403 <span class="invalid-feedback"
405 The entered value must be a positive integer.
416 <h5 class="cds--accordion__title cd-header">Advanced</h5>
419 <cds-accordion size="lg"
423 id="advanced-fieldset"
424 (selected)="showAdvanced = !showAdvanced"
426 @if( isTierMatch( TIER_TYPE.CLOUD_TIER, TIER_TYPE.GLACIER )){
427 <!-- Multi Part Sync Threshold -->
428 <div class="form-item form-item-append"
432 labelInputID="multipart_sync_threshold"
434 [helperText]="helpTextLabels.multipartSyncThresholdText"
435 cdOptionalField="Multipart Sync Threshold"
436 >Multipart Sync Threshold
440 id="multipart_sync_threshold"
441 formControlName="multipart_sync_threshold"
448 labelInputID="multipart_min_part_size"
450 [helperText]="helpTextLabels.multipartMinPartText"
451 cdOptionalField="Multipart Minimum Part Size"
452 >Multipart Minimum Part Size
456 id="multipart_min_part_size"
457 formControlName="multipart_min_part_size"
465 <legend class="cd-header"
466 i18n>ACLs Mapping</legend>
467 <ng-container formArrayName="acls">
468 @for (acl of acls.controls; let i = $index; track acl) {
469 <ng-container [formGroupName]="i">
470 <div class="form-item form-item-append"
473 [columnNumbers]="{ lg: 7 }">
474 <cds-select id="type"
475 formControlName="type"
478 @for (type of typeOptions; track type.value) {
479 <option [value]="type.value"
488 class="form-item form-item-append">
491 labelInputID="source_id"
493 [helperText]="getAclHelperText(acl.get('type')?.value, 'source')"
495 acl.get('source_id')?.invalid && acl.get('source_id')?.touched
498 acl.get('source_id')?.errors?.['required'] ? 'This field is required.' :
499 acl.get('source_id')?.errors?.['email'] ? 'Please enter a valid email address.' :
500 acl.get('source_id')?.errors?.['invalidUrl'] ? 'Please enter a valid URL.' : ''
503 {{ getAclLabel('source', acl.get('type')?.value) }}
507 formControlName="source_id"
509 acl.get('source_id')?.errors?.['required'] ? 'This field is required.' :
510 acl.get('source_id')?.errors?.['email'] ? 'Please enter a valid email address.' :
511 acl.get('source_id')?.errors?.['invalidUrl'] ? 'Please enter a valid URL.' : ''
518 labelInputID="dest_id"
520 [helperText]="getAclHelperText(acl.get('type')?.value, 'destination')"
521 [invalid]="acl.get('dest_id')?.invalid && acl.get('dest_id')?.touched"
523 acl.get('dest_id')?.errors?.['required'] ? 'This field is required.' :
524 acl.get('dest_id')?.errors?.['email'] ? 'Please enter a valid email address.' :
525 acl.get('dest_id')?.errors?.['invalidUrl'] ? 'Please enter a valid URL.' : ''
528 {{ getAclLabel('destination', acl.get('type')?.value) }}
532 formControlName="dest_id"
534 acl.get('dest_id')?.errors?.['required'] ? 'This field is required.' :
535 acl.get('dest_id')?.errors?.['email'] ? 'Please enter a valid email address.' :
536 acl.get('dest_id')?.errors?.['invalidUrl'] ? 'Please enter a valid URL.' : ''
544 [columnNumbers]="{ lg: 1, md: 1 }"
545 class="item-action-btn spacing"
547 <cds-icon-button kind="primary"
549 (click)="addAcls(acls, i)">
552 class="cds--btn__icon"></svg>
556 [columnNumbers]="{ lg: 1, md: 1 }"
557 class="item-action-btn">
558 <cds-icon-button kind="danger"
560 (click)="removeAcl(i)">
561 <svg cdsIcon="trash-can"
563 class="cds--btn__icon"></svg>
572 <div class="form-item form-item-append"
575 <!-- Placement Target -->
577 label="Placement Target"
579 formControlName="placement_target"
581 storageClassForm.showError('placement_target', formDir, 'required')
583 [invalidText]="placementError"
585 @for (placementTarget of placementTargets; track placementTarget) {
587 [value]="placementTarget"
589 placementTarget === storageClassForm.getValue('placement_target')
593 {{ placementTarget }}
597 <ng-template #placementError>
598 @if (storageClassForm.showError('placement_target', formDir, 'required')) {
599 <span class="invalid-feedback"
600 i18n> This field is required. </span>
605 </cds-accordion-item>
610 @if( isTierMatch( TIER_TYPE.CLOUD_TIER, TIER_TYPE.GLACIER )){
611 <cd-alert-panel type="warning"
613 <span i18n>RGW service would be restarted after creating the storage class.</span>
616 <cd-form-button-panel
617 (submitActionEvent)="submitAction()"
618 [form]="storageClassForm"
619 [submitText]="(action | titlecase) + ' ' + (resource | upperFirst)"
620 wrappingClass="text-right"
621 ></cd-form-button-panel>
626 <ng-template #storageClassField
627 [formGroup]="storageClassForm">
628 <cds-text-label labelInputID="storage_class"
631 [invalid]="storageClassForm.controls.storage_class.invalid && storageClassForm.controls.storage_class.dirty"
632 [invalidText]="storageClassError"
637 formControlName="storage_class"
638 [invalid]="storageClassForm.showError('storage_class', formDir, 'required')"/>
640 <ng-template #storageClassError>
641 <span class="invalid-feedback"
642 *ngIf="storageClassForm.showError('storage_class', formDir, 'required')"
643 i18n>This field is required.</span>