Skip to content

Commit

Permalink
NAS-131790: Add interface implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
RehanY147 committed Nov 12, 2024
1 parent b3c835b commit 75710eb
Show file tree
Hide file tree
Showing 28 changed files with 182 additions and 50 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { ComponentType } from '@angular/cdk/portal';
import {
AfterViewInit, Directive, Input, OnInit, ViewChild, inject,
AfterViewInit, Directive, Input, OnInit, Type, ViewChild, inject,
} from '@angular/core';
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { TranslateService } from '@ngx-translate/core';
Expand All @@ -9,6 +8,7 @@ import {
Observable, distinctUntilChanged, filter, map, switchMap, take, tap,
} from 'rxjs';
import { Option } from 'app/interfaces/option.interface';
import { SlideIn2CloseConfirmation } from 'app/interfaces/slide-in-close-confirmation.interface';
import { IxSelectComponent, IxSelectValue } from 'app/modules/forms/ix-forms/components/ix-select/ix-select.component';
import { ChainedComponentResponse, ChainedSlideInService } from 'app/services/chained-slide-in.service';

Expand Down Expand Up @@ -47,7 +47,7 @@ export abstract class IxSelectWithNewOption implements OnInit, AfterViewInit {
abstract getValueFromChainedResponse(
result: ChainedComponentResponse,
): IxSelectValue;
abstract getFormComponentType(): ComponentType<unknown>;
abstract getFormComponentType(): Type<SlideIn2CloseConfirmation>;
abstract fetchOptions(): Observable<Option[]>;
getFormInputData(): Record<string, unknown> {
return undefined;
Expand Down
3 changes: 2 additions & 1 deletion src/app/modules/slide-ins/chained-component-ref.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Type } from '@angular/core';
import { SlideIn2CloseConfirmation } from 'app/interfaces/slide-in-close-confirmation.interface';
import { ChainedComponentResponse as ChainedResponse } from 'app/services/chained-slide-in.service';

export class ChainedRef<T> {
Expand All @@ -10,6 +11,6 @@ export class ChainedRef<T> {
* have the same purpose and return the same response type e.g, form to wizard and
* wizard to form.
*/
swap?: (component: Type<unknown>, wide: boolean, data?: unknown) => void;
swap?: (component: Type<SlideIn2CloseConfirmation>, wide: boolean, data?: unknown) => void;
getData: () => T;
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,6 @@ export class ModalHeader2Component implements AfterViewInit {
}

close(): void {
this.chainedSlideInRef.close({ response: false, error: null });
this.chainedSlideInRef.close({ response: false, error: null, cancelled: true });
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ export class SlideIn2Component implements OnInit, OnDestroy {
}

private openSlideIn<T, D>(
componentType: Type<unknown>,
componentType: Type<SlideIn2CloseConfirmation>,
params?: { wide?: boolean; data?: D },
): void {
if (this.isSlideInOpen) {
Expand All @@ -143,7 +143,7 @@ export class SlideIn2Component implements OnInit, OnDestroy {
}

private createInjector<T, D>(
componentType: Type<unknown>,
componentType: Type<SlideIn2CloseConfirmation>,
data?: D,
): void {
const injector = Injector.create({
Expand All @@ -152,7 +152,7 @@ export class SlideIn2Component implements OnInit, OnDestroy {
provide: ChainedRef<D>,
useValue: {
close: (response: ChainedComponentResponse) => {
this.getConfirmation().pipe(
(response.cancelled ? this.getConfirmation() : of(true)).pipe(
filter(Boolean),
untilDestroyed(this),
).subscribe({
Expand All @@ -163,7 +163,7 @@ export class SlideIn2Component implements OnInit, OnDestroy {
},
});
},
swap: (component: Type<unknown>, wide = false, incomingComponentData?: unknown) => {
swap: (component: Type<SlideIn2CloseConfirmation>, wide = false, incomingComponentData?: unknown) => {
this.getConfirmation().pipe(
filter(Boolean),
untilDestroyed(this),
Expand All @@ -186,7 +186,7 @@ export class SlideIn2Component implements OnInit, OnDestroy {
},
],
});
this.componentRef = this.slideInBody.createComponent<T>(componentType as Type<T>, { injector });
this.componentRef = this.slideInBody.createComponent<T>(componentType as unknown as Type<T>, { injector });
}

protected onBackdropClicked(): void {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import {
import { MatButton } from '@angular/material/button';
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { TranslateModule } from '@ngx-translate/core';
import { tap } from 'rxjs';
import { Observable, of, tap } from 'rxjs';
import { SlideIn2CloseConfirmation } from 'app/interfaces/slide-in-close-confirmation.interface';
import { FormActionsComponent } from 'app/modules/forms/ix-forms/components/form-actions/form-actions.component';
import { IxFieldsetComponent } from 'app/modules/forms/ix-forms/components/ix-fieldset/ix-fieldset.component';
import { IxIconGroupComponent } from 'app/modules/forms/ix-forms/components/ix-icon-group/ix-icon-group.component';
Expand Down Expand Up @@ -47,7 +48,7 @@ import { WidgetGroupSlotFormComponent } from './widget-group-slot-form/widget-gr
TranslateModule,
],
})
export class WidgetGroupFormComponent {
export class WidgetGroupFormComponent implements SlideIn2CloseConfirmation {
protected group = signal<WidgetGroup>(
{ layout: WidgetGroupLayout.Full, slots: [{ type: null }] },
);
Expand Down Expand Up @@ -82,6 +83,10 @@ export class WidgetGroupFormComponent {
this.setInitialFormValues();
}

requiresConfirmationOnClose(): Observable<boolean> {
return of(this.layoutControl.dirty);
}

private setInitialFormValues(): void {
const widgetGroup = this.chainedRef.getData();
if (!widgetGroup) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { FormBuilder } from '@ngneat/reactive-forms';
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { TranslateService, TranslateModule } from '@ngx-translate/core';
import {
debounceTime, distinctUntilChanged, map, of,
debounceTime, distinctUntilChanged, map, Observable, of,
} from 'rxjs';
import { RequiresRolesDirective } from 'app/directives/requires-roles/requires-roles.directive';
import { CloudSyncProviderName } from 'app/enums/cloudsync-provider.enum';
Expand All @@ -19,6 +19,7 @@ import { buildNormalizedFileSize } from 'app/helpers/file-size.utils';
import { helptextCloudBackup } from 'app/helptext/data-protection/cloud-backup/cloud-backup';
import { CloudBackup, CloudBackupUpdate } from 'app/interfaces/cloud-backup.interface';
import { SelectOption, newOption } from 'app/interfaces/option.interface';
import { SlideIn2CloseConfirmation } from 'app/interfaces/slide-in-close-confirmation.interface';
import { ExplorerNodeData, TreeNode } from 'app/interfaces/tree-node.interface';
import { CloudCredentialsSelectComponent } from 'app/modules/forms/custom-selects/cloud-credentials-select/cloud-credentials-select.component';
import { FormActionsComponent } from 'app/modules/forms/ix-forms/components/form-actions/form-actions.component';
Expand Down Expand Up @@ -73,7 +74,7 @@ type FormValue = CloudBackupFormComponent['form']['value'];
TranslateModule,
],
})
export class CloudBackupFormComponent implements OnInit {
export class CloudBackupFormComponent implements OnInit, SlideIn2CloseConfirmation {
get isNew(): boolean {
return !this.editingTask;
}
Expand Down Expand Up @@ -143,6 +144,10 @@ export class CloudBackupFormComponent implements OnInit {
this.editingTask = chainedRef.getData();
}

requiresConfirmationOnClose(): Observable<boolean> {
return of(this.form.dirty);
}

ngOnInit(): void {
this.setFileNodeProvider();
this.setBucketNodeProvider();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { CloudSyncTask, CloudSyncTaskUi, CloudSyncTaskUpdate } from 'app/interfa
import { CloudSyncCredential } from 'app/interfaces/cloudsync-credential.interface';
import { CloudSyncProvider } from 'app/interfaces/cloudsync-provider.interface';
import { newOption, SelectOption } from 'app/interfaces/option.interface';
import { SlideIn2CloseConfirmation } from 'app/interfaces/slide-in-close-confirmation.interface';
import { ExplorerNodeData, TreeNode } from 'app/interfaces/tree-node.interface';
import { WebSocketError } from 'app/interfaces/websocket-error.interface';
import { DialogService } from 'app/modules/dialog/dialog.service';
Expand Down Expand Up @@ -94,7 +95,7 @@ type FormValue = CloudSyncFormComponent['form']['value'];
TranslateModule,
],
})
export class CloudSyncFormComponent implements OnInit {
export class CloudSyncFormComponent implements OnInit, SlideIn2CloseConfirmation {
get isNew(): boolean {
return !this.editingTask;
}
Expand Down Expand Up @@ -227,6 +228,10 @@ export class CloudSyncFormComponent implements OnInit {
this.editingTask = this.chainedRef.getData();
}

requiresConfirmationOnClose(): Observable<boolean> {
return of(this.form.dirty);
}

getCredentialsList(): Observable<CloudSyncCredential[]> {
return this.fetchCloudSyncCredentialsList();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { TranslateService, TranslateModule } from '@ngx-translate/core';
import {
BehaviorSubject, Observable, merge,
of,
} from 'rxjs';
import { cloudSyncProviderNameMap } from 'app/enums/cloudsync-provider.enum';
import { Role } from 'app/enums/role.enum';
import { CloudSyncTask, CloudSyncTaskUpdate } from 'app/interfaces/cloud-sync-task.interface';
import { CloudSyncCredential } from 'app/interfaces/cloudsync-credential.interface';
import { SlideIn2CloseConfirmation } from 'app/interfaces/slide-in-close-confirmation.interface';
import { DialogService } from 'app/modules/dialog/dialog.service';
import {
UseIxIconsInStepperComponent,
Expand Down Expand Up @@ -43,7 +45,7 @@ import { CloudSyncProviderComponent } from './steps/cloudsync-provider/cloudsync
UseIxIconsInStepperComponent,
],
})
export class CloudSyncWizardComponent {
export class CloudSyncWizardComponent implements SlideIn2CloseConfirmation {
@ViewChild(forwardRef(() => CloudSyncWhatAndWhenComponent)) whatAndWhen: CloudSyncWhatAndWhenComponent;

protected readonly requiredRoles = [Role.CloudSyncWrite];
Expand All @@ -63,6 +65,10 @@ export class CloudSyncWizardComponent {
private errorHandler: ErrorHandlerService,
) {}

requiresConfirmationOnClose(): Observable<boolean> {
return of(this.whatAndWhen.form.dirty);
}

createTask(payload: CloudSyncTaskUpdate): Observable<CloudSyncTask> {
return this.ws.call('cloudsync.create', [payload]);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { MatButton } from '@angular/material/button';
import { MatCard, MatCardContent } from '@angular/material/card';
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { TranslateService, TranslateModule } from '@ngx-translate/core';
import { merge, of } from 'rxjs';
import { merge, Observable, of } from 'rxjs';
import { debounceTime, switchMap } from 'rxjs/operators';
import { RequiresRolesDirective } from 'app/directives/requires-roles/requires-roles.directive';
import { Direction } from 'app/enums/direction.enum';
Expand All @@ -17,6 +17,7 @@ import { helptextReplicationWizard } from 'app/helptext/data-protection/replicat
import { CountManualSnapshotsParams } from 'app/interfaces/count-manual-snapshots.interface';
import { KeychainSshCredentials } from 'app/interfaces/keychain-credential.interface';
import { ReplicationCreate, ReplicationTask } from 'app/interfaces/replication-task.interface';
import { SlideIn2CloseConfirmation } from 'app/interfaces/slide-in-close-confirmation.interface';
import { WebSocketError } from 'app/interfaces/websocket-error.interface';
import { DialogService } from 'app/modules/dialog/dialog.service';
import { TreeNodeProvider } from 'app/modules/forms/ix-forms/components/ix-explorer/tree-node-provider.interface';
Expand Down Expand Up @@ -74,7 +75,7 @@ import { WebSocketService } from 'app/services/ws.service';
TranslateModule,
],
})
export class ReplicationFormComponent implements OnInit {
export class ReplicationFormComponent implements OnInit, SlideIn2CloseConfirmation {
@ViewChild(GeneralSectionComponent, { static: true }) generalSection: GeneralSectionComponent;
@ViewChild(TransportSectionComponent, { static: true }) transportSection: TransportSectionComponent;
@ViewChild(SourceSectionComponent, { static: true }) sourceSection: SourceSectionComponent;
Expand Down Expand Up @@ -112,6 +113,16 @@ export class ReplicationFormComponent implements OnInit {
this.existingReplication = this.chainedRef.getData();
}

requiresConfirmationOnClose(): Observable<boolean> {
return of(
this.generalSection.form.dirty
|| this.transportSection.form.dirty
|| this.sourceSection.form.dirty
|| this.targetSection.form.dirty
|| this.scheduleSection.form.dirty,
);
}

ngOnInit(): void {
this.countSnapshotsOnChanges();
this.updateExplorersOnChanges();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import { CountManualSnapshotsParams, EligibleManualSnapshotsCount, TargetUnmatch
import { PeriodicSnapshotTask, PeriodicSnapshotTaskCreate } from 'app/interfaces/periodic-snapshot-task.interface';
import { ReplicationCreate, ReplicationTask } from 'app/interfaces/replication-task.interface';
import { Schedule } from 'app/interfaces/schedule.interface';
import { SlideIn2CloseConfirmation } from 'app/interfaces/slide-in-close-confirmation.interface';
import { CreateZfsSnapshot, ZfsSnapshot } from 'app/interfaces/zfs-snapshot.interface';
import { DialogService } from 'app/modules/dialog/dialog.service';
import {
Expand Down Expand Up @@ -69,7 +70,7 @@ import { WebSocketService } from 'app/services/ws.service';
UseIxIconsInStepperComponent,
],
})
export class ReplicationWizardComponent {
export class ReplicationWizardComponent implements SlideIn2CloseConfirmation {
@ViewChild(ReplicationWhatAndWhereComponent) whatAndWhere: ReplicationWhatAndWhereComponent;
@ViewChild(ReplicationWhenComponent) when: ReplicationWhenComponent;

Expand Down Expand Up @@ -98,6 +99,11 @@ export class ReplicationWizardComponent {
private authService: AuthService,
) {}

requiresConfirmationOnClose(): Observable<boolean> {
const steps = this.getSteps();
return of(steps.some((step) => step.form.dirty));
}

getSteps(): [
ReplicationWhatAndWhereComponent,
ReplicationWhenComponent,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { RsyncMode, RsyncSshConnectMode } from 'app/enums/rsync-mode.enum';
import { helptextRsyncForm } from 'app/helptext/data-protection/rsync/rsync-form';
import { newOption } from 'app/interfaces/option.interface';
import { RsyncTask, RsyncTaskUpdate } from 'app/interfaces/rsync-task.interface';
import { SlideIn2CloseConfirmation } from 'app/interfaces/slide-in-close-confirmation.interface';
import { SshCredentialsSelectComponent } from 'app/modules/forms/custom-selects/ssh-credentials-select/ssh-credentials-select.component';
import { UserComboboxProvider } from 'app/modules/forms/ix-forms/classes/user-combobox-provider';
import { IxCheckboxComponent } from 'app/modules/forms/ix-forms/components/ix-checkbox/ix-checkbox.component';
Expand Down Expand Up @@ -68,7 +69,7 @@ import { WebSocketService } from 'app/services/ws.service';
TranslateModule,
],
})
export class RsyncTaskFormComponent implements OnInit {
export class RsyncTaskFormComponent implements OnInit, SlideIn2CloseConfirmation {
readonly requiredRoles = [Role.FullAdmin];

get isNew(): boolean {
Expand Down Expand Up @@ -154,6 +155,10 @@ export class RsyncTaskFormComponent implements OnInit {
this.editingTask = this.chainedSlideInRef.getData();
}

requiresConfirmationOnClose(): Observable<boolean> {
return of(this.form.dirty);
}

get isModuleMode(): boolean {
return this.form.value.mode === RsyncMode.Module;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { Store } from '@ngrx/store';
import { TranslateService, TranslateModule } from '@ngx-translate/core';
import {
filter, finalize, forkJoin, Observable, take,
filter, finalize, forkJoin, Observable, of, take,
} from 'rxjs';
import { RequiresRolesDirective } from 'app/directives/requires-roles/requires-roles.directive';
import { Role } from 'app/enums/role.enum';
import { SlideIn2CloseConfirmation } from 'app/interfaces/slide-in-close-confirmation.interface';
import { DialogService } from 'app/modules/dialog/dialog.service';
import { FormActionsComponent } from 'app/modules/forms/ix-forms/components/form-actions/form-actions.component';
import { IxCheckboxComponent } from 'app/modules/forms/ix-forms/components/ix-checkbox/ix-checkbox.component';
Expand Down Expand Up @@ -55,7 +56,7 @@ import { selectAdvancedConfig, selectGeneralConfig } from 'app/store/system-conf
TranslateModule,
],
})
export class AccessFormComponent implements OnInit {
export class AccessFormComponent implements OnInit, SlideIn2CloseConfirmation {
readonly requiredRoles = [Role.AuthSessionsWrite];

isLoading = false;
Expand Down Expand Up @@ -87,6 +88,10 @@ export class AccessFormComponent implements OnInit {
private chainedSlideInRef: ChainedRef<unknown>,
) {}

requiresConfirmationOnClose(): Observable<boolean> {
return of(this.form.dirty);
}

ngOnInit(): void {
this.store$.select(selectPreferences).pipe(untilDestroyed(this)).subscribe((preferences) => {
if (preferences.lifetime) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { RequiresRolesDirective } from 'app/directives/requires-roles/requires-r
import { Role } from 'app/enums/role.enum';
import { helptextSystemAdvanced } from 'app/helptext/system/advanced';
import { helptextSystemGeneral } from 'app/helptext/system/general';
import { SlideIn2CloseConfirmation } from 'app/interfaces/slide-in-close-confirmation.interface';
import { WebSocketError } from 'app/interfaces/websocket-error.interface';
import { DialogService } from 'app/modules/dialog/dialog.service';
import { FormActionsComponent } from 'app/modules/forms/ix-forms/components/form-actions/form-actions.component';
Expand Down Expand Up @@ -53,7 +54,7 @@ import { generalConfigUpdated } from 'app/store/system-config/system-config.acti
TranslateModule,
],
})
export class AllowedAddressesFormComponent implements OnInit {
export class AllowedAddressesFormComponent implements OnInit, SlideIn2CloseConfirmation {
protected readonly requiredRoles = [Role.FullAdmin];
protected readonly helpText = helptextSystemAdvanced;

Expand All @@ -74,6 +75,10 @@ export class AllowedAddressesFormComponent implements OnInit {
private slideInRef: ChainedRef<unknown>,
) {}

requiresConfirmationOnClose(): Observable<boolean> {
return of(this.form.dirty);
}

ngOnInit(): void {
this.ws.call('system.general.config').pipe(untilDestroyed(this)).subscribe({
next: (config) => {
Expand Down
Loading

0 comments on commit 75710eb

Please sign in to comment.