Skip to content

Commit

Permalink
NAS-130213 / 24.10 / Add smaller apps widgets (#10378)
Browse files Browse the repository at this point in the history
* NAS-130213: Slice Widget App into chunks

* NAS-130213: Revert temp changes

* NAS-130213: Move files around

* NAS-130213: Add widget-app-info and widget-app-stats

* NAS-130213: Add widget-app-cpu and widget-app-memory

* NAS-130213: Add widget-app-network

* NAS-130213: Adapt more changes

* NAS-130213: Adapt more changes

* NAS-130213: Adapt tests

* NAS-130213: Adapt more changes

* NAS-130213: Adapt tests

* NAS-130213: Do not show apps widgets

* NAS-130213: Cleanup
  • Loading branch information
denysbutenko authored Aug 9, 2024
1 parent dd49e61 commit 3c6657c
Show file tree
Hide file tree
Showing 146 changed files with 2,274 additions and 285 deletions.
3 changes: 2 additions & 1 deletion src/app/interfaces/catalog.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@ export interface CatalogAppVersion {

export interface ChartMetadata {
apiVersion: string;
appVersion: string;
appVersion?: string;
app_version: string;
dependencies: ChartMetadataDependency[];
latest_chart_version: string;
description: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ describe('AppInfoCardComponent', () => {
});

// TODO:
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
it.skip('opens rollback app dialog when Roll Back button is pressed', async () => {

Check warning on line 195 in src/app/pages/apps/components/installed-apps/app-info-card/app-info-card.component.spec.ts

View workflow job for this annotation

GitHub Actions / Validate code style

Disabled test
const rollbackButton = await loader.getHarness(MatButtonHarness.with({ text: 'Roll Back' }));
await rollbackButton.click();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ describe('AppRowComponent', () => {
metadata: { icon: 'https://image/' },
} as App;

const status = AppStatus.Started;
const status = AppStatus.Running;

const createComponent = createComponentFactory({
component: AppRowComponent,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export class AppRowComponent {
return this.app().upgrade_available;
});

readonly isAppStopped = computed(() => this.status() === AppStatus.Started);
readonly isAppStopped = computed(() => this.status() === AppStatus.Running);

readonly inProgress = computed(() => {
return [AppStatus.Deploying].includes(this.status()) || this.isStartingOrStopping();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
padding: 3px 18px;
}

&.started {
&.running {
border-color: var(--green);
color: var(--green);
}
Expand Down
6 changes: 3 additions & 3 deletions src/app/pages/apps/enum/app-status.enum.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
import { marker as T } from '@biesbjerg/ngx-translate-extract-marker';

export enum AppStatus {
Started = 'STARTED',
Running = 'RUNNING',
Starting = 'STARTING',
Deploying = 'DEPLOYING',
Stopped = 'STOPPED',
Stopping = 'STOPPING',
}

export const appStatusIcons = new Map<AppStatus, string>([
[AppStatus.Started, 'mdi-check-circle'],
[AppStatus.Running, 'mdi-check-circle'],
[AppStatus.Starting, 'mdi-progress-wrench'],
[AppStatus.Deploying, 'mdi-progress-wrench'],
[AppStatus.Stopping, 'mdi-progress-wrench'],
[AppStatus.Stopped, 'mdi-stop-circle'],
]);

export const appStatusLabels = new Map<AppStatus, string>([
[AppStatus.Started, T('Running')],
[AppStatus.Running, T('Running')],
[AppStatus.Starting, T('Starting')],
[AppStatus.Deploying, T('Deploying')],
[AppStatus.Stopped, T('Stopped')],
Expand Down
2 changes: 1 addition & 1 deletion src/app/pages/apps/utils/get-app-status.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export function getAppStatus(app: App, _?: Job<void, AppStartQueryParams>): AppS

switch (app.state) {
case CatalogAppState.Running:
status = AppStatus.Started;
status = AppStatus.Running;
break;
case CatalogAppState.Deploying:
status = AppStatus.Deploying;
Expand Down
6 changes: 0 additions & 6 deletions src/app/pages/dashboard/dashboard.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,6 @@ import { FormatDateTimePipe } from 'app/modules/pipes/format-date-time/format-da
import { MapValuePipe } from 'app/modules/pipes/map-value/map-value.pipe';
import { NetworkSpeedPipe } from 'app/modules/pipes/network-speed/network-speed.pipe';
import { TestIdModule } from 'app/modules/test-id/test-id.module';
import { AppCardLogoComponent } from 'app/pages/apps/components/app-card-logo/app-card-logo.component';
import { AppStatusCellComponent } from 'app/pages/apps/components/installed-apps/app-status-cell/app-status-cell.component';
import { AppUpdateCellComponent } from 'app/pages/apps/components/installed-apps/app-update-cell/app-update-cell.component';
import { DashboardComponent } from 'app/pages/dashboard/components/dashboard/dashboard.component';
import {
WidgetGroupControlsComponent,
Expand Down Expand Up @@ -122,9 +119,6 @@ import { PoolUsageGaugeComponent } from './widgets/storage/widget-pool/common/po
ImgFallbackModule,
InterfaceStatusIconComponent,
UptimePipe,
AppCardLogoComponent,
AppStatusCellComponent,
AppUpdateCellComponent,
FormatDateTimePipe,
FileSizePipe,
CopyButtonComponent,
Expand Down
26 changes: 16 additions & 10 deletions src/app/pages/dashboard/services/widget-resources.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ import { Store } from '@ngrx/store';
import { subHours, subMinutes } from 'date-fns';
import {
Observable, Subject, combineLatestWith, debounceTime,
forkJoin, map, repeat, shareReplay, switchMap, take, timer,
forkJoin, map, of, repeat, shareReplay, switchMap, take, timer,
} from 'rxjs';
import { SystemUpdateStatus } from 'app/enums/system-update.enum';
import { toLoadingState } from 'app/helpers/operators/to-loading-state.helper';
import { App } from 'app/interfaces/app.interface';
import { Dataset } from 'app/interfaces/dataset.interface';
import { Disk } from 'app/interfaces/disk.interface';
import { Job } from 'app/interfaces/job.interface';
import { Pool } from 'app/interfaces/pool.interface';
import { ReportingData } from 'app/interfaces/reporting.interface';
import { VolumesData, VolumeData } from 'app/interfaces/volume-data.interface';
Expand Down Expand Up @@ -57,9 +58,7 @@ export class WidgetResourcesService {
shareReplay({ bufferSize: 1, refCount: true }),
);

readonly installedApps$ = this.ws.call('app.query', [[]]).pipe(
toLoadingState(),
);
readonly installedApps$ = this.ws.call('app.query').pipe(toLoadingState());

readonly pools$ = this.ws.callAndSubscribe('pool.query');

Expand Down Expand Up @@ -133,12 +132,7 @@ export class WidgetResourcesService {
}

getApp(appName: string): Observable<App> {
return this.ws.call(
'app.query',
[
[['name', '=', appName]],
],
).pipe(
return this.ws.call('app.query', [[['name', '=', appName]]]).pipe(
map((apps) => {
if (apps.length === 0) {
throw new Error(`App «${appName}» not found. Configure widget to choose another app.`);
Expand All @@ -149,6 +143,18 @@ export class WidgetResourcesService {
);
}

// TODO: Fix when stats API is ready
getAppStats(appName: string): Observable<unknown> {
console.error(`getAppStats(${appName}) not implemented yet`);
return of();
}

// TODO: Fix when stats API is ready
getAppStatusUpdates(appName: string): Observable<Job> {
console.error(`getAppStatusUpdates(${appName}) not implemented yet`);
return of();
}

constructor(
private ws: WebSocketService,
private store$: Store<AppState>,
Expand Down
1 change: 0 additions & 1 deletion src/app/pages/dashboard/types/widget.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
* Provide migration if possible.
*/
export enum WidgetType {
App = 'app',
Ipv4Address = 'ipv4-address',
Ipv6Address = 'ipv6-address',
Help = 'help',
Expand Down
4 changes: 0 additions & 4 deletions src/app/pages/dashboard/widgets/all-widgets.constant.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { WidgetType } from 'app/pages/dashboard/types/widget.interface';
import { appWidget } from 'app/pages/dashboard/widgets/apps/widget-app/widget-app.definition';
import { backupTasksWidget } from 'app/pages/dashboard/widgets/backup/widget-backup/widget-backup.definition';
import { cpuWidget } from 'app/pages/dashboard/widgets/cpu/widget-cpu/widget-cpu.definition';
import { cpuTemperatureBarWidget } from 'app/pages/dashboard/widgets/cpu/widget-cpu-temperature-bar/widget-cpu-temperature-bar.definition';
Expand Down Expand Up @@ -34,8 +33,6 @@ import { systemImageWidget } from 'app/pages/dashboard/widgets/system/widget-sys
import { systemUptimeWidget } from 'app/pages/dashboard/widgets/system/widget-system-uptime/widget-system-uptime.definition';

export const widgetComponents = [
appWidget.component,
appWidget.settingsComponent,
ipv4AddressWidget.component,
ipv4AddressWidget.settingsComponent,
helpWidget.component,
Expand Down Expand Up @@ -68,7 +65,6 @@ export const widgetComponents = [
];

export const widgetRegistry = {
[WidgetType.App]: appWidget,
[WidgetType.Pool]: poolWidget,
[WidgetType.PoolUsageGauge]: poolUsageGaugeWidget,
[WidgetType.PoolStatus]: poolStatusWidget,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<div class="app-header">
<h3 *ixWithLoadingState="app() as app" class="name">{{ app.name }}</h3>
<div *ixWithLoadingState="app() as app" class="version">v{{ app.metadata?.app_version }}</div>
</div>
<div class="app-status">
<ix-app-status-cell
*ixWithLoadingState="app() as app"
[app]="app"
[job]="job()"
[showIcon]="true"
></ix-app-status-cell>
<ix-app-update-cell
*ixWithLoadingState="app() as app"
[app]="app"
[showIcon]="true"
></ix-app-update-cell>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
:host {
background: var(--bg1);
display: inline-flex;
flex: 1 1 70%;
flex-direction: column;
max-width: 70%;

.app-header {
align-items: baseline;
border-bottom: 1px solid var(--lines);
display: flex;
justify-content: space-between;
min-height: 48px;
padding: 8px;
}

.app-status {
display: flex;
flex-direction: column;
font-size: 16px;
font-weight: bold;
padding: 8px 12px;

ix-app-update-cell {
gap: 8px;
}

::ng-deep ix-with-loading-state-loader {
height: 24px;
margin-bottom: 4px;
margin-top: 4px;
}
}

.ix-icon {
&.mdi-check-circle {
color: var(--green);
}

&.mdi-progress-wrench,
&.mdi-alert-circle {
color: var(--yellow);
}

&.mdi-stop-circle {
color: var(--red);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { Spectator } from '@ngneat/spectator';
import { createComponentFactory } from '@ngneat/spectator/jest';
import { MockComponents } from 'ng-mocks';
import { LoadingState } from 'app/helpers/operators/to-loading-state.helper';
import { App, AppStartQueryParams } from 'app/interfaces/app.interface';
import { Job } from 'app/interfaces/job.interface';
import { AppStatusCellComponent } from 'app/pages/apps/components/installed-apps/app-status-cell/app-status-cell.component';
import { AppUpdateCellComponent } from 'app/pages/apps/components/installed-apps/app-update-cell/app-update-cell.component';
import { AppCardInfoComponent } from './app-card-info.component';

describe('AppCardInfoComponent', () => {
let spectator: Spectator<AppCardInfoComponent>;
const createComponent = createComponentFactory({
component: AppCardInfoComponent,
declarations: [MockComponents(AppStatusCellComponent, AppUpdateCellComponent)],
});

beforeEach(() => {
spectator = createComponent({
props: {
app: {
isLoading: false,
error: null,
value: {
name: 'TestApp',
metadata: {
app_version: '1.0.0',
},
},
} as LoadingState<App>,
job: {} as Job<void, AppStartQueryParams>,
},
});
});

it('checks app name', () => {
const appName = spectator.query('.name');
expect(appName).toHaveText('TestApp');
});

it('checks app version', () => {
const appVersion = spectator.query('.version');
expect(appVersion).toHaveText('v1.0.0');
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Component, ChangeDetectionStrategy, input } from '@angular/core';
import { LoadingState } from 'app/helpers/operators/to-loading-state.helper';
import { App, AppStartQueryParams } from 'app/interfaces/app.interface';
import { Job } from 'app/interfaces/job.interface';

@Component({
selector: 'ix-app-card-info',
templateUrl: './app-card-info.component.html',
styleUrls: ['./app-card-info.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AppCardInfoComponent {
app = input.required<LoadingState<App>>();
job = input.required<Job<void, AppStartQueryParams>>();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<ng-container *ixWithLoadingState="app() as app">
@if ((app.portals | keyvalue).length > 0) {
<button
mat-icon-button
ixTest="apps-web-portal"
matTooltipPosition="above"
[attr.aria-label]="'Web Portal' | translate"
[matTooltip]="'Web Portal' | translate"
(click)="openWebPortal(app)"
>
<ix-icon name="mdi-web"></ix-icon>
</button>
}

<button
mat-icon-button
ixTest="apps-restart"
matTooltipPosition="above"
[attr.aria-label]="'Restart App' | translate"
[matTooltip]="'Restart App' | translate"
[disabled]="isRestarting()"
(click)="onRestartApp(app)"
>
<ix-icon name="mdi-restart"></ix-icon>
</button>

<button
mat-icon-button
ixTest="apps-details"
matTooltipPosition="above"
[attr.aria-label]="'Check App Details' | translate"
[matTooltip]="'Check App Details' | translate"
(click)="openAppDetails(app)"
>
<ix-icon name="mdi-cog"></ix-icon>
</button>
</ng-container>
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
:host {
align-items: center;
color: var(--fg2);
display: flex;
flex-direction: row;
}
Loading

0 comments on commit 3c6657c

Please sign in to comment.