Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NAS-131013 / 25.04 / Migrate more components to signal inputs #10621

Merged
merged 7 commits into from
Sep 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<mat-list role="list">
@for (subItem of subMenuItems; track subItem) {
@for (subItem of subMenuItems(); track subItem) {
@if (!subItem.isVisible$ || (subItem.isVisible$ | async)) {
<mat-list-item
*ixHasAccess="!subItem.hasAccess$ || (subItem.hasAccess$ | async)"
Expand All @@ -8,7 +8,7 @@
role="listitem"
(click)="toggleMenu.emit()"
>
<a class="slidein-nav-link" [ixTest]="subItem.name" [routerLink]="['/', menuName, subItem.state]">
<a class="slidein-nav-link" [ixTest]="subItem.name" [routerLink]="['/', menuName(), subItem.state]">
{{ subItem.name | translate }}
</a>
</mat-list-item>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { createComponentFactory, Spectator } from '@ngneat/spectator/jest';
import { of } from 'rxjs';
import { SecondaryMenuComponent } from 'app/modules/layout/secondary-menu/secondary-menu.component';

describe('SecondaryMenuComponent', () => {
let spectator: Spectator<SecondaryMenuComponent>;
const createComponent = createComponentFactory({
component: SecondaryMenuComponent,
});

beforeEach(() => {
spectator = createComponent({
props: {
menuName: 'credentials',
},
});
});

it('renders a list of submenu items', () => {
spectator.setInput({
subMenuItems: [
{
name: 'Users',
state: 'users',
},
{
name: 'Groups',
state: 'groups',
},
],
});

const items = spectator.queryAll('.sidebar-list-item a');
expect(items).toHaveLength(2);
expect(items[0]).toHaveText('Users');
expect(items[1]).toHaveText('Groups');
expect(items[0]).toHaveAttribute('href', '/credentials/users');
expect(items[1]).toHaveAttribute('href', '/credentials/groups');
});

it('does not render items that have isVisible$ resolve to false', () => {
spectator.setInput({
subMenuItems: [
{
name: 'Users',
state: 'users',
},
{
name: 'Groups',
state: 'groups',
isVisible$: of(false),
},
],
});

const items = spectator.queryAll('.sidebar-list-item a');
expect(items).toHaveLength(1);
expect(items[0]).toHaveText('Users');
});
});
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { AsyncPipe } from '@angular/common';
import {
ChangeDetectionStrategy, Component, Input, output,
ChangeDetectionStrategy, Component, input, output,
} from '@angular/core';
import { MatList, MatListItem } from '@angular/material/list';
import { RouterLinkActive, RouterLink } from '@angular/router';
Expand All @@ -26,8 +26,8 @@ import { TestIdModule } from 'app/modules/test-id/test-id.module';
],
})
export class SecondaryMenuComponent {
@Input() menuName: string;
@Input() subMenuItems: SubMenuItem[];
readonly menuName = input<string>();
readonly subMenuItems = input<SubMenuItem[]>();

readonly toggleMenu = output();
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ <h2 class="title">

<div class="cards">
<div class="scroll-window">
<ix-metadata-details-card [log]="log"></ix-metadata-details-card>
<ix-event-data-details-card [log]="log"></ix-event-data-details-card>
<ix-metadata-details-card [log]="log()"></ix-metadata-details-card>
<ix-event-data-details-card [log]="log()"></ix-event-data-details-card>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Spectator, createComponentFactory } from '@ngneat/spectator/jest';
import { MockComponents } from 'ng-mocks';
import { AuditEntry } from 'app/interfaces/audit/audit.interface';
import { EventDataDetailsCardComponent } from 'app/pages/audit/components/event-data-details-card/event-data-details-card.component';
import { LogDetailsPanelComponent } from 'app/pages/audit/components/log-details-panel/log-details-panel.component';
import { MetadataDetailsCardComponent } from 'app/pages/audit/components/metadata-details-card/metadata-details-card.component';
Expand All @@ -14,12 +15,14 @@ describe('LogDetailsPanelComponent', () => {
EventDataDetailsCardComponent,
),
],
providers: [],
imports: [],
});

beforeEach(() => {
spectator = createComponent();
spectator = createComponent({
props: {
log: {} as AuditEntry,
},
});
});

it('checks card title', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {
ChangeDetectionStrategy, Component, Input, output,
ChangeDetectionStrategy, Component, input, output,
} from '@angular/core';
import { AuditEntry } from 'app/interfaces/audit/audit.interface';

Expand All @@ -10,7 +10,7 @@ import { AuditEntry } from 'app/interfaces/audit/audit.interface';
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class LogDetailsPanelComponent {
@Input() log: AuditEntry;
readonly log = input.required<AuditEntry>();

readonly hide = output();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ <h3 mat-card-title>
</h3>
</mat-card-header>
<mat-card-content>
<p>{{ 'Audit ID' | translate }}: {{ log.audit_id || '-' }}</p>
<p>{{ 'Version' | translate }}: {{ log.service_data.vers.major ? ('Major' | translate) : ('Minor' | translate) }}</p>
<p>{{ 'Session' | translate }}: {{ log.session || '-' }}</p>
<p>{{ 'Audit ID' | translate }}: {{ log().audit_id || '-' }}</p>
<p>{{ 'Version' | translate }}: {{ log().service_data.vers.major ? ('Major' | translate) : ('Minor' | translate) }}</p>
<p>{{ 'Session' | translate }}: {{ log().session || '-' }}</p>
</mat-card-content>
</mat-card>
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
import {
ChangeDetectionStrategy, Component, input,
} from '@angular/core';
import { AuditEntry } from 'app/interfaces/audit/audit.interface';

@Component({
Expand All @@ -8,5 +10,5 @@ import { AuditEntry } from 'app/interfaces/audit/audit.interface';
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class MetadataDetailsCardComponent {
@Input() log: AuditEntry;
readonly log = input.required<AuditEntry>();
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,25 @@ <h2 class="title">
>
<ix-icon name="mdi-chevron-left"></ix-icon>
</a>
{{ 'Task Details for {task}' | translate: { task: backup.description } }}
{{ 'Task Details for {task}' | translate: { task: backup().description } }}
</div>

<span class="prefix">
{{ 'Task Details for {task}' | translate: { task: backup.description } }}
{{ 'Task Details for {task}' | translate: { task: backup().description } }}
</span>
</h2>
</div>

<div class="cards">
<div class="scroll-window">
<ix-cloud-backup-schedule [backup]="backup"></ix-cloud-backup-schedule>
<ix-cloud-backup-schedule [backup]="backup()"></ix-cloud-backup-schedule>

<ix-cloud-backup-stats [backup]="backup"></ix-cloud-backup-stats>
<ix-cloud-backup-stats [backup]="backup()"></ix-cloud-backup-stats>

@if (backup.exclude?.length) {
<ix-cloud-backup-excluded-paths [backup]="backup"></ix-cloud-backup-excluded-paths>
@if (backup().exclude?.length) {
<ix-cloud-backup-excluded-paths [backup]="backup()"></ix-cloud-backup-excluded-paths>
}

<ix-cloud-backup-snapshots [backup]="backup"></ix-cloud-backup-snapshots>
<ix-cloud-backup-snapshots [backup]="backup()"></ix-cloud-backup-snapshots>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {
ChangeDetectionStrategy, Component, Input, output,
ChangeDetectionStrategy, Component, input, output,
} from '@angular/core';
import { CloudBackup } from 'app/interfaces/cloud-backup.interface';

Expand All @@ -10,7 +10,7 @@ import { CloudBackup } from 'app/interfaces/cloud-backup.interface';
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CloudBackupDetailsComponent {
@Input() backup: CloudBackup;
readonly backup = input.required<CloudBackup>();

readonly closeMobileDetails = output();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ <h3 mat-card-title>
</h3>
</mat-card-header>
<mat-card-content>
<p>{{ 'Task Name' | translate }}: {{ backup.description || '-' }}</p>
<p>{{ 'Frequency' | translate }}: {{ frequency }}</p>
<p>{{ 'Schedule' | translate }}: {{ schedule || '-' }}</p>
<p>{{ 'Task Name' | translate }}: {{ backup().description || '-' }}</p>
<p>{{ 'Frequency' | translate }}: {{ frequency() }}</p>
<p>{{ 'Schedule' | translate }}: {{ schedule() || '-' }}</p>
</mat-card-content>
</mat-card>
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
import {
ChangeDetectionStrategy, Component, computed, input,
} from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import { CloudBackup } from 'app/interfaces/cloud-backup.interface';
import { scheduleToCrontab } from 'app/modules/scheduler/utils/schedule-to-crontab.utils';
Expand All @@ -11,15 +13,15 @@ import { TaskService } from 'app/services/task.service';
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CloudBackupScheduleComponent {
@Input() backup: CloudBackup;
readonly backup = input.required<CloudBackup>();

get frequency(): string {
return this.taskService.getTaskCronDescription(scheduleToCrontab(this.backup.schedule));
}
protected readonly frequency = computed(() => {
return this.taskService.getTaskCronDescription(scheduleToCrontab(this.backup().schedule));
});

get schedule(): string {
return (this.backup.enabled ? scheduleToCrontab(this.backup.schedule) : this.translate.instant('Disabled'));
}
protected readonly schedule = computed(() => {
return this.backup().enabled ? scheduleToCrontab(this.backup().schedule) : this.translate.instant('Disabled');
});

constructor(
private taskService: TaskService,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ <h3 mat-card-title>
</h3>
</mat-card-header>
<mat-card-content>
<p>{{ 'Path' | translate }}: {{ backup.path || '-' }}</p>
<p>{{ 'Credentials' | translate }}: {{ backup.credentials.name || '-' }}</p>
<p>{{ 'Bucket' | translate }}: {{ backup.attributes.bucket || '-' }}</p>
<p>{{ 'Folder' | translate }}: {{ backup.attributes.folder || '-' }}</p>
<p>{{ 'Keep Last' | translate }}: {{ backup.keep_last || '-' }}</p>
<p>{{ 'Transfers' | translate }}: {{ backup.transfers || '-' }}</p>
<p>{{ 'Post Script' | translate }}: {{ backup.post_script || '-' }}</p>
<p>{{ 'Pre Script' | translate }}: {{ backup.pre_script || '-' }}</p>
<p>{{ 'Path' | translate }}: {{ backup().path || '-' }}</p>
<p>{{ 'Credentials' | translate }}: {{ backup().credentials.name || '-' }}</p>
<p>{{ 'Bucket' | translate }}: {{ backup().attributes.bucket || '-' }}</p>
<p>{{ 'Folder' | translate }}: {{ backup().attributes.folder || '-' }}</p>
<p>{{ 'Keep Last' | translate }}: {{ backup().keep_last || '-' }}</p>
<p>{{ 'Transfers' | translate }}: {{ backup().transfers || '-' }}</p>
<p>{{ 'Post Script' | translate }}: {{ backup().post_script || '-' }}</p>
<p>{{ 'Pre Script' | translate }}: {{ backup().pre_script || '-' }}</p>
</mat-card-content>
</mat-card>
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
import {
ChangeDetectionStrategy, Component, input,
} from '@angular/core';
import { CloudBackup } from 'app/interfaces/cloud-backup.interface';

@Component({
Expand All @@ -8,5 +10,5 @@ import { CloudBackup } from 'app/interfaces/cloud-backup.interface';
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CloudBackupStatsComponent {
@Input() backup: CloudBackup;
readonly backup = input.required<CloudBackup>();
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<div class="header">
<div class="image">
<img [src]="image" [src-fallback]="imagePlaceholder">
<img [src]="image()" [src-fallback]="imagePlaceholder">
</div>
<div class="name">{{ name }}</div>
<div class="name">{{ name() }}</div>
</div>
<div class="body">
<p>{{ description }}</p>
<p>{{ description() }}</p>
</div>
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { Spectator, createComponentFactory } from '@ngneat/spectator/jest';
import { createComponentFactory, Spectator } from '@ngneat/spectator/jest';
import { ImgFallbackModule } from 'ngx-img-fallback';
import { CloudSyncProviderName } from 'app/enums/cloudsync-provider.enum';
import {
cloudsyncProviderDescriptionMap,
} from 'app/pages/data-protection/cloudsync/cloudsync-provider-description/cloudsync-provider-description';
import { CloudSyncProviderDescriptionComponent } from './cloudsync-provider-description.component';

describe('CloudSyncProviderDescriptionComponent', () => {
Expand All @@ -11,14 +14,23 @@ describe('CloudSyncProviderDescriptionComponent', () => {
});

beforeEach(() => {
spectator = createComponent();
spectator = createComponent({
props: {
provider: CloudSyncProviderName.Storj,
},
});
});

it('should have the correct details for Storj', () => {
spectator.setInput('provider', CloudSyncProviderName.Storj);

expect(spectator.component.image).toBe('/assets/images/cloudsync/STORJ_IX.png');
expect(spectator.component.name).toBe('Storj');
expect(spectator.component.description).toBe('Storj is a decentralized, open-source cloud storage platform. It uses blockchain technology and cryptography to secure files. Instead of storing files in a centralized server, Storj splits up files, encrypts them, and distributes them across a network of computers around the world.');
const image = spectator.query('.image img');
expect(image).toHaveAttribute('src', '/assets/images/cloudsync/STORJ_IX.png');

const name = spectator.query('.name');
expect(name).toHaveText('Storj');

const description = spectator.query('.body');
expect(description).toHaveText(cloudsyncProviderDescriptionMap.get(CloudSyncProviderName.Storj));
});
});
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
import {
ChangeDetectionStrategy, Component, computed, input,
} from '@angular/core';
import { ImgFallbackModule } from 'ngx-img-fallback';
import { appImagePlaceholder } from 'app/constants/catalog.constants';
import { CloudSyncProviderName, cloudSyncProviderNameMap } from 'app/enums/cloudsync-provider.enum';
Expand All @@ -13,18 +15,19 @@ import { cloudsyncProviderDescriptionMap } from 'app/pages/data-protection/cloud
imports: [ImgFallbackModule],
})
export class CloudSyncProviderDescriptionComponent {
@Input() provider: CloudSyncProviderName;
readonly provider = input.required<CloudSyncProviderName>();

readonly imagePlaceholder = appImagePlaceholder;

get image(): string {
return `/assets/images/cloudsync/${this.provider}.png`;
}
protected readonly image = computed(() => {
return `/assets/images/cloudsync/${this.provider()}.png`;
});

get name(): string {
return cloudSyncProviderNameMap.get(this.provider);
}
protected readonly name = computed(() => {
return cloudSyncProviderNameMap.get(this.provider());
});

get description(): string {
return cloudsyncProviderDescriptionMap.get(this.provider);
}
protected readonly description = computed(() => {
return cloudsyncProviderDescriptionMap.get(this.provider());
});
}
Loading
Loading