Skip to content

Commit

Permalink
NAS-130953: PR update
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexKarpov98 committed Sep 3, 2024
2 parents d185fe7 + e067aa9 commit 013a36f
Show file tree
Hide file tree
Showing 182 changed files with 472 additions and 298 deletions.
2 changes: 1 addition & 1 deletion src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export class AppComponent {
// save currenturl
if (event instanceof NavigationEnd) {
const navigation = this.router.getCurrentNavigation();
if (this.isAuthenticated && event.url !== '/sessions/signin' && !navigation?.extras?.skipLocationChange) {
if (this.isAuthenticated && event.url !== '/signin' && !navigation?.extras?.skipLocationChange) {
this.window.sessionStorage.setItem('redirectUrl', event.url);
}
}
Expand Down
15 changes: 8 additions & 7 deletions src/app/app.routing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ import { marker as T } from '@biesbjerg/ngx-translate-extract-marker';
import { TranslationsLoadedGuard } from 'app/core/guards/translations-loaded.guard';
import { WebSocketConnectionGuard } from 'app/core/guards/websocket-connection.guard';
import { AdminLayoutComponent } from 'app/modules/layout/components/admin-layout/admin-layout.component';
import { BlankLayoutComponent } from 'app/modules/layout/components/blank-layout/blank-layout.component';
import { SigninComponent } from 'app/pages/signin/signin.component';
import { TwoFactorGuardService } from 'app/services/auth/two-factor-guard.service';
import { AuthLayoutComponent } from './modules/layout/components/auth-layout/auth-layout.component';
import { AuthGuardService } from './services/auth/auth-guard.service';

export const rootRouterConfig: Routes = [
Expand All @@ -15,17 +16,17 @@ export const rootRouterConfig: Routes = [
},
{
path: '',
component: AuthLayoutComponent,
component: BlankLayoutComponent,
canActivate: [TranslationsLoadedGuard, WebSocketConnectionGuard],
children: [
{
path: 'sessions',
loadChildren: () => import('./views/sessions/sessions.module').then((module) => module.SessionsModule),
data: { title: T('Session') },
path: 'signin',
component: SigninComponent,
data: { title: T('Signin') },
},
{
path: 'others',
loadChildren: () => import('./views/others/others.module').then((module) => module.OthersModule),
path: 'system-tasks',
loadChildren: () => import('app/pages/system-tasks/system-tasks.module').then((module) => module.SystemTasksModule),
data: { title: T('Others'), breadcrumb: T('Others') },
},
],
Expand Down
2 changes: 1 addition & 1 deletion src/app/core/guards/websocket-connection.guard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export class WebSocketConnectionGuard {
private resetUi(): void {
this.closeAllDialogs();
if (!this.wsManager.shutDownInProgress) {
this.router.navigate(['/sessions/signin']);
this.router.navigate(['/signin']);
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/app/enums/disk-bus.enum.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
export enum DiskBus {
Spi = 'SPI',
Usb = 'USB',
Ata = 'ATA',
Unknown = 'UNKNOWN',
}
1 change: 1 addition & 0 deletions src/app/interfaces/device-nested-data-node.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export interface VDevGroup {
group: string;
guid: VdevType;
children: TopologyItem[];
isRoot?: boolean;
}

export type DeviceNestedDataNode = TopologyItem | VDevGroup;
Expand Down
2 changes: 1 addition & 1 deletion src/app/interfaces/storage.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { TopologyItemStatus } from 'app/enums/vdev-status.enum';
import { ZfsProperty } from './zfs-property.interface';

// As returned by pool.query under topology[<vdevtype>]
export type TopologyItem = VDev | TopologyDisk;
export type TopologyItem = (VDev | TopologyDisk) & { isRoot?: boolean };

export interface VDev {
type: Exclude<TopologyItemType, TopologyItemType.Disk>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import { LanguageService } from 'app/services/language.service';
import { ThemeService } from 'app/services/theme/theme.service';

@Component({
selector: 'ix-auth-layout',
templateUrl: './auth-layout.component.html',
selector: 'ix-blank-layout',
templateUrl: './blank-layout.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AuthLayoutComponent implements OnInit {
export class BlankLayoutComponent implements OnInit {
constructor(
public language: LanguageService,
private themeService: ThemeService,
Expand All @@ -25,7 +25,7 @@ export class AuthLayoutComponent implements OnInit {
const palette = Object.keys(theme) as (keyof Theme)[];
palette.splice(0, 6);

const adminLayoutElement = document.getElementsByTagName('IX-AUTH-LAYOUT')[0] as HTMLElement;
const adminLayoutElement = document.getElementsByTagName('IX-BLANK-LAYOUT')[0] as HTMLElement;

palette.forEach((color) => {
adminLayoutElement.style.setProperty('--' + color, theme[color] as string);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ describe('PowerMenuComponent', () => {
expect(spectator.inject(DialogService).confirm).toHaveBeenCalledWith(expect.objectContaining({
message: 'Restart the system?',
}));
expect(spectator.inject(Router).navigate).toHaveBeenCalledWith(['/others/reboot'], { skipLocationChange: true });
expect(spectator.inject(Router).navigate).toHaveBeenCalledWith(['/system-tasks/reboot'], { skipLocationChange: true });
});

it('has a Shutdown menu item that shuts down system after confirmation', async () => {
Expand All @@ -49,6 +49,6 @@ describe('PowerMenuComponent', () => {
expect(spectator.inject(DialogService).confirm).toHaveBeenCalledWith(expect.objectContaining({
message: 'Shut down the system?',
}));
expect(spectator.inject(Router).navigate).toHaveBeenCalledWith(['/others/shutdown'], { skipLocationChange: true });
expect(spectator.inject(Router).navigate).toHaveBeenCalledWith(['/system-tasks/shutdown'], { skipLocationChange: true });
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export class PowerMenuComponent {
filter(Boolean),
untilDestroyed(this),
).subscribe(() => {
this.router.navigate(['/others/reboot'], { skipLocationChange: true });
this.router.navigate(['/system-tasks/reboot'], { skipLocationChange: true });
});
}

Expand All @@ -47,7 +47,7 @@ export class PowerMenuComponent {
filter(Boolean),
untilDestroyed(this),
).subscribe(() => {
this.router.navigate(['/others/shutdown'], { skipLocationChange: true });
this.router.navigate(['/system-tasks/shutdown'], { skipLocationChange: true });
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ export class TopbarComponent implements OnInit {
) {
this.systemWillRestart = true;
if (job.state === JobState.Success) {
this.router.navigate(['/others/reboot'], { skipLocationChange: true });
this.router.navigate(['/system-tasks/reboot'], { skipLocationChange: true });
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,6 @@ describe('UserMenuComponent', () => {
jest.spyOn(authService, 'logout');

expect(authService.logout).toHaveBeenCalled();
expect(authService.clearAuthToken).toHaveBeenCalled();
});

it('has an 2fa menu item that redirects user to TwoFactorComponent when clicked', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import {
} from 'app/modules/layout/components/topbar/change-password-dialog/change-password-dialog.component';
import { userMenuElements } from 'app/modules/layout/components/topbar/user-menu/user-menu.elements';
import { AuthService } from 'app/services/auth/auth.service';
import { WebSocketConnectionService } from 'app/services/websocket-connection.service';

@UntilDestroy()
@Component({
Expand All @@ -32,7 +31,6 @@ export class UserMenuComponent {
private matDialog: MatDialog,
private authService: AuthService,
private router: Router,
private wsManager: WebSocketConnectionService,
) { }

openChangePasswordDialog(): void {
Expand All @@ -50,8 +48,10 @@ export class UserMenuComponent {
}

onSignOut(): void {
this.authService.logout().pipe(untilDestroyed(this)).subscribe();
this.authService.clearAuthToken();
this.wsManager.isClosed$ = true;
this.authService.logout()
.pipe(untilDestroyed(this))
.subscribe(() => {
this.router.navigate(['/signin']);
});
}
}
4 changes: 2 additions & 2 deletions src/app/modules/layout/layout.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import { IxSlideInComponent } from 'app/modules/forms/ix-forms/components/ix-sli
import { GlobalSearchModule } from 'app/modules/global-search/global-search.module';
import { IxIconModule } from 'app/modules/ix-icon/ix-icon.module';
import { AdminLayoutComponent } from 'app/modules/layout/components/admin-layout/admin-layout.component';
import { AuthLayoutComponent } from 'app/modules/layout/components/auth-layout/auth-layout.component';
import { BlankLayoutComponent } from 'app/modules/layout/components/blank-layout/blank-layout.component';
import { ConsoleFooterComponent } from 'app/modules/layout/components/console-footer/console-footer.component';
import {
ConsolePanelDialogComponent,
Expand Down Expand Up @@ -99,7 +99,7 @@ import { UserMenuComponent } from './components/topbar/user-menu/user-menu.compo
PowerMenuComponent,
TopbarComponent,
UserMenuComponent,
AuthLayoutComponent,
BlankLayoutComponent,
AdminLayoutComponent,
CopyrightLineComponent,
ConsoleFooterComponent,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,18 @@

@if (isEditing()) {
<div class="edit-mode-buttons">
@if (customLayout()) {
<button
mat-button
type="button"
ixTest="reset"
[disabled]="isLoading()"
(click)="onReset()"
>
{{ 'Reset' | translate }}
</button>
}

<button
mat-button
class="add-button"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,19 @@ import { provideMockStore } from '@ngrx/store/testing';
import { MockComponent, MockDirective } from 'ng-mocks';
import { NgxSkeletonLoaderComponent } from 'ngx-skeleton-loader';
import { BehaviorSubject, of } from 'rxjs';
import { DialogService } from 'app/modules/dialog/dialog.service';
import { IxDropGridDirective } from 'app/modules/ix-drop-grid/ix-drop-grid.directive';
import { IxIconHarness } from 'app/modules/ix-icon/ix-icon.harness';
import { PageHeaderComponent } from 'app/modules/page-header/page-title-header/page-header.component';
import { SnackbarService } from 'app/modules/snackbar/services/snackbar.service';
import { DashboardComponent } from 'app/pages/dashboard/components/dashboard/dashboard.component';
import {
WidgetGroupControlsComponent,
} from 'app/pages/dashboard/components/dashboard/widget-group-controls/widget-group-controls.component';
import { WidgetGroupComponent } from 'app/pages/dashboard/components/widget-group/widget-group.component';
import { WidgetGroupFormComponent } from 'app/pages/dashboard/components/widget-group-form/widget-group-form.component';
import { DashboardStore } from 'app/pages/dashboard/services/dashboard.store';
import { defaultWidgets } from 'app/pages/dashboard/services/default-widgets.constant';
import { WidgetGroup, WidgetGroupLayout } from 'app/pages/dashboard/types/widget-group.interface';
import { ChainedComponentResponse, IxChainedSlideInService } from 'app/services/ix-chained-slide-in.service';

Expand All @@ -40,6 +43,9 @@ describe('DashboardComponent', () => {
MockDirective(IxDropGridDirective),
],
providers: [
mockProvider(DialogService, {
confirm: jest.fn(() => of(true)),
}),
mockProvider(DashboardStore, {
groups$,
isLoading$,
Expand All @@ -49,6 +55,7 @@ describe('DashboardComponent', () => {
mockProvider(IxChainedSlideInService, {
open: jest.fn(() => of({ error: false, response: groupA })),
}),
mockProvider(SnackbarService),
provideMockStore(),
],
});
Expand Down Expand Up @@ -144,6 +151,19 @@ describe('DashboardComponent', () => {
.toHaveBeenCalledWith(WidgetGroupFormComponent, true);
});

it('resets configuration to defaults when Reset is pressed', async () => {
const resetButton = await loader.getHarness(MatButtonHarness.with({ text: 'Reset' }));
await resetButton.click();

expect(spectator.inject(SnackbarService).success).toHaveBeenCalledWith('Default widgets restored');

const saveButton = await loader.getHarness(MatButtonHarness.with({ text: 'Save' }));
await saveButton.click();

expect(spectator.inject(DashboardStore).save).toHaveBeenCalledWith(defaultWidgets);
expect(spectator.inject(SnackbarService).success).toHaveBeenCalledWith('Dashboard settings saved');
});

it('saves new configuration when Save is pressed', async () => {
const deleteIcon = await loader.getHarness(IxIconHarness.with({ name: 'delete' }));
await deleteIcon.click();
Expand All @@ -152,6 +172,7 @@ describe('DashboardComponent', () => {
await saveButton.click();

expect(spectator.inject(DashboardStore).save).toHaveBeenCalledWith([groupB, groupC, groupD]);
expect(spectator.inject(SnackbarService).success).toHaveBeenCalledWith('Dashboard settings saved');
});

it('reverts to loaded configuration when Cancel button is pressed', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ import {
import { toSignal } from '@angular/core/rxjs-interop';
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { TranslateService } from '@ngx-translate/core';
import { isEqual } from 'lodash-es';
import { EmptyType } from 'app/enums/empty-type.enum';
import { EmptyConfig } from 'app/interfaces/empty-config.interface';
import { SnackbarService } from 'app/modules/snackbar/services/snackbar.service';
import { dashboardElements } from 'app/pages/dashboard/components/dashboard/dashboard.elements';
import { WidgetGroupFormComponent } from 'app/pages/dashboard/components/widget-group-form/widget-group-form.component';
import { DashboardStore } from 'app/pages/dashboard/services/dashboard.store';
import { defaultWidgets } from 'app/pages/dashboard/services/default-widgets.constant';
import { WidgetGroup } from 'app/pages/dashboard/types/widget-group.interface';
import { ErrorHandlerService } from 'app/services/error-handler.service';
import { ChainedComponentResponse, IxChainedSlideInService } from 'app/services/ix-chained-slide-in.service';
Expand Down Expand Up @@ -46,6 +48,9 @@ export class DashboardComponent implements OnInit {
key: 'dashboardConfigure',
message: this.translate.instant('New widgets and layouts.'),
};
readonly customLayout = computed(() => {
return !isEqual(this.renderedGroups(), defaultWidgets);
});

emptyDashboardConf: EmptyConfig = {
type: EmptyType.NoPageData,
Expand Down Expand Up @@ -136,6 +141,11 @@ export class DashboardComponent implements OnInit {
});
}

protected onReset(): void {
this.renderedGroups.set(defaultWidgets);
this.snackbar.success(this.translate.instant('Default widgets restored'));
}

private loadGroups(): void {
this.dashboardStore.groups$
.pipe(untilDestroyed(this))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ export class WidgetSysInfoPassiveComponent {
filter(Boolean),
untilDestroyed(this),
).subscribe(() => {
this.router.navigate(['/others/failover'], { skipLocationChange: true });
this.router.navigate(['/system-tasks/failover'], { skipLocationChange: true });
});
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<div class="fake-icon">?</div>
@if (hasFailover) {
@if (hasFailover()) {
<p>
{{ 'Waiting for Active TrueNAS controller to come up...' | translate }}
</p>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { createComponentFactory, Spectator } from '@ngneat/spectator/jest';
import {
DisconnectedMessageComponent,
} from 'app/views/sessions/signin/disconnected-message/disconnected-message.component';
} from 'app/pages/signin/disconnected-message/disconnected-message.component';

describe('DisconnectedMessageComponent', () => {
let spectator: Spectator<DisconnectedMessageComponent>;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import {
ChangeDetectionStrategy, Component, Input,
ChangeDetectionStrategy, Component, input,
} from '@angular/core';
import { TranslateModule } from '@ngx-translate/core';

@Component({
selector: 'ix-disconnected-message',
templateUrl: './disconnected-message.component.html',
styleUrls: ['./disconnected-message.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [TranslateModule],
})
export class DisconnectedMessageComponent {
@Input() hasFailover: boolean;
readonly hasFailover = input(false);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<p class="failover-status-message">{{ statusMessage() | translate }}</p>
@if (!disabledReasons()) {
<ngx-skeleton-loader></ngx-skeleton-loader>
}
@if (areReasonsShown()) {
<div class="failover-reasons">
@for (reason of disabledReasons(); track reason) {
<p>
{{ reason | mapValue: disabledReasonLabels | translate }}
</p>
}
</div>
}

<p class="failover-status">{{ statusDescriptions[status()] }}</p>
@if (!failoverIps()) {
<ngx-skeleton-loader></ngx-skeleton-loader>
}
@if (failoverIps()?.length) {
<div class="failover-ips">
<p>{{ 'Active IP Addresses' | translate }}: {{ failoverIps().join(", ") }}</p>
</div>
}
Loading

0 comments on commit 013a36f

Please sign in to comment.