1 import { ChangeDetectorRef, Component, Inject, OnInit, Optional } from '@angular/core';
9 } from '@angular/forms';
10 import { CdFormBuilder } from '~/app/shared/forms/cd-form-builder';
11 import { CdFormGroup } from '~/app/shared/forms/cd-form-group';
12 import { CdValidators } from '~/app/shared/forms/cd-validators';
13 import { Bucket } from '../models/rgw-bucket';
14 import { RgwBucketService } from '~/app/shared/api/rgw-bucket.service';
15 import { NotificationService } from '~/app/shared/services/notification.service';
16 import { NotificationType } from '~/app/shared/enum/notification-type.enum';
17 import { RgwZonegroupService } from '~/app/shared/api/rgw-zonegroup.service';
18 import { BucketTieringUtils } from '../utils/rgw-bucket-tiering';
19 import { StorageClass, ZoneGroupDetails } from '../models/rgw-storage-class.model';
20 import { CdForm } from '~/app/shared/forms/cd-form';
21 import { Router } from '@angular/router';
22 import { ActionLabelsI18n } from '~/app/shared/constants/app.constants';
24 export interface Tags {
30 selector: 'cd-rgw-bucket-tiering',
31 templateUrl: './rgw-bucket-tiering-form.component.html',
32 styleUrls: ['./rgw-bucket-tiering-form.component.scss']
34 export class RgwBucketTieringFormComponent extends CdForm implements OnInit {
35 tieringForm: CdFormGroup;
36 tagsToRemove: Tags[] = [];
37 storageClassList: StorageClass[] = null;
38 configuredLifecycle: any;
39 isStorageClassFetched = false;
42 @Inject('bucket') public bucket: Bucket,
43 @Optional() @Inject('selectedLifecycle') public selectedLifecycle: any,
44 @Optional() @Inject('editing') public editing = false,
45 public actionLabels: ActionLabelsI18n,
46 private rgwBucketService: RgwBucketService,
47 private fb: CdFormBuilder,
48 private cd: ChangeDetectorRef,
49 private rgwZonegroupService: RgwZonegroupService,
50 private notificationService: NotificationService,
51 private router: Router
58 .getLifecycle(this.bucket.bucket, this.bucket.owner)
59 .subscribe((lifecycle) => {
60 this.configuredLifecycle = lifecycle || { LifecycleConfiguration: { Rules: [] } };
62 const ruleToEdit = this.configuredLifecycle?.['LifecycleConfiguration']?.['Rules'].filter(
63 (rule: any) => rule?.['ID'] === this.selectedLifecycle?.['ID']
65 this.tieringForm.patchValue({
66 name: ruleToEdit?.['ID'],
67 hasPrefix: this.checkIfRuleHasFilters(ruleToEdit),
69 ruleToEdit?.['Prefix'] ||
70 ruleToEdit?.['Filter']?.['Prefix'] ||
71 ruleToEdit?.['Filter']?.['And']?.['Prefix'] ||
73 status: ruleToEdit?.['Status'],
74 days: ruleToEdit?.['Transition']?.['Days']
76 this.setTags(ruleToEdit);
77 this.tieringForm.get('name').disable();
80 this.tieringForm = this.fb.group({
81 name: [null, [Validators.required, this.duplicateConfigName.bind(this)]],
82 storageClass: [null, Validators.required],
83 hasPrefix: [false, [Validators.required]],
84 prefix: [null, [CdValidators.composeIf({ hasPrefix: true }, [Validators.required])]],
85 tags: this.fb.array([]),
86 status: ['Enabled', [Validators.required]],
87 days: [60, [Validators.required, CdValidators.number(false)]]
89 this.loadStorageClass();
92 checkIfRuleHasFilters(rule: any) {
94 this.isValidPrefix(rule?.['Prefix']) ||
95 this.isValidPrefix(rule?.['Filter']?.['Prefix']) ||
96 this.isValidArray(rule?.['Filter']?.['Tags']) ||
97 this.isValidPrefix(rule?.['Filter']?.['And']?.['Prefix']) ||
98 this.isValidArray(rule?.['Filter']?.['And']?.['Tags'])
105 isValidPrefix(value: string) {
106 return value !== undefined && value !== '';
109 isValidArray(value: object[]) {
110 return Array.isArray(value) && value.length > 0;
114 if (rule?.['Filter']?.['Tags']?.length > 0) {
115 rule?.['Filter']?.['Tags']?.forEach((tag: { Key: string; Value: string }) =>
116 this.addTags(tag.Key, tag.Value)
119 if (rule?.['Filter']?.['And']?.['Tags']?.length > 0) {
120 rule?.['Filter']?.['And']?.['Tags']?.forEach((tag: { Key: string; Value: string }) =>
121 this.addTags(tag.Key, tag.Value)
127 return this.tieringForm.get('tags') as FormArray;
130 addTags(key?: string, value?: string) {
133 Key: new FormControl(key),
134 Value: new FormControl(value)
137 this.cd.detectChanges();
140 duplicateConfigName(control: AbstractControl): ValidationErrors | null {
141 if (this.configuredLifecycle?.LifecycleConfiguration?.Rules?.length > 0) {
142 const ruleIds = this.configuredLifecycle.LifecycleConfiguration.Rules.map(
143 (rule: any) => rule.ID
145 return ruleIds.includes(control.value) ? { duplicate: true } : null;
150 removeTags(idx: number) {
151 this.tags.removeAt(idx);
152 this.cd.detectChanges();
155 loadStorageClass(): Promise<void> {
156 return new Promise((resolve, reject) => {
157 this.rgwZonegroupService.getAllZonegroupsInfo().subscribe(
158 (data: ZoneGroupDetails) => {
159 this.storageClassList = [];
160 const tierObj = BucketTieringUtils.filterAndMapTierTargets(data);
161 this.isStorageClassFetched = true;
162 this.storageClassList.push(...tierObj);
166 .setValue(this.selectedLifecycle?.['Transition']?.['StorageClass']);
178 submitTieringConfig() {
179 const formValue = this.tieringForm.value;
180 if (!this.tieringForm.valid) {
184 let lifecycle: any = {
185 ID: this.tieringForm.getRawValue().name,
186 Status: formValue.status,
189 Days: formValue.days,
190 StorageClass: formValue.storageClass
194 if (formValue.hasPrefix) {
195 if (this.tags.length > 0) {
196 Object.assign(lifecycle, {
199 Prefix: formValue.prefix,
205 Object.assign(lifecycle, {
207 Prefix: formValue.prefix
212 Object.assign(lifecycle, {
217 this.configuredLifecycle.LifecycleConfiguration.Rules.push(lifecycle);
218 this.rgwBucketService
221 JSON.stringify(this.configuredLifecycle.LifecycleConfiguration),
226 this.notificationService.show(
227 NotificationType.success,
228 $localize`Bucket lifecycle created succesfully`
231 error: (error: any) => {
232 this.notificationService.show(NotificationType.error, error);
233 this.tieringForm.setErrors({ cdSubmitButton: true });
240 const rules = this.configuredLifecycle.LifecycleConfiguration.Rules;
241 const index = rules.findIndex((rule: any) => rule?.['ID'] === this.selectedLifecycle?.['ID']);
242 rules.splice(index, 1, lifecycle);
243 this.rgwBucketService
246 JSON.stringify(this.configuredLifecycle.LifecycleConfiguration),
251 this.notificationService.show(
252 NotificationType.success,
253 $localize`Bucket lifecycle modified succesfully`
256 error: (error: any) => {
257 this.notificationService.show(NotificationType.error, error);
258 this.tieringForm.setErrors({ cdSubmitButton: true });
267 goToCreateStorageClass() {
268 this.router.navigate(['rgw/tiering/create']);