Skip to content

Commit

Permalink
Merge pull request #985 from aneoconsulting/show-component-better-ref…
Browse files Browse the repository at this point in the history
…resh

chore: show component is now refreshed with subjects
  • Loading branch information
ngruelaneo authored Mar 26, 2024
2 parents 2099e71 + 3095fcf commit 03e999a
Show file tree
Hide file tree
Showing 17 changed files with 210 additions and 71 deletions.
2 changes: 1 addition & 1 deletion src/app/components/show-action-area.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
{{element.name}}
</a>

<button mat-flat-button *ngIf="element.action$ && !element.link" (click)="element.action$.next()" [disabled]="element.disabled" [color]="element.color" >
<button mat-flat-button *ngIf="element.action$ && !element.link" (click)="element.action$.next()" [disabled]="isDisabled[element.id]" [color]="element.color" >
<mat-icon [fontIcon]="element.icon ?? ''" />
{{element.name}}
</button>
Expand Down
82 changes: 82 additions & 0 deletions src/app/components/show-action-area.component.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { Subject } from 'rxjs';
import { ShowActionButton } from '@app/types/components/show';
import { ShowActionAreaComponent } from './show-action-area.component';

describe('ShowActionAreaComponent', () => {
let component: ShowActionAreaComponent;

const disableCancel = new Subject<boolean>();
const disableClose = new Subject<boolean>();

const actions: ShowActionButton[] = [
{
id: 'tasks',
name: 'See tasks',
icon: 'tasks',
link: '/tasks',
queryParams: {},
},
{
id: 'results',
name: 'See results',
icon: 'results',
link: '/results',
queryParams: {},
},
{
id: 'partitions',
name: 'See partitions',
icon: 'partitions',
link: '/partitions',
queryParams: {},
},
{
id: 'cancel',
name: 'Cancel Session',
icon: 'cancel',
action$: new Subject(),
disabled: disableCancel,
color: 'accent',
area: 'right'
},
{
id: 'close',
name: 'Close Session',
icon: 'close',
action$: new Subject(),
disabled: disableClose,
color: 'accent',
area: 'right'
},
{
id: 'delete',
name: 'Delete Session',
icon: 'delete',
action$: new Subject(),
color: 'accent',
area: 'right'
}
];

beforeEach(() => {
component = new ShowActionAreaComponent();
component.actions = actions;
});

it('should create', () => {
expect(component).toBeTruthy();
});

it('should set actions', () => {
expect(component.actions).toEqual(actions);
});

it('should set isDisabled', () => {
disableCancel.next(true);
expect(component.isDisabled).toEqual({
cancel: true,
close: false
});
});

});
24 changes: 23 additions & 1 deletion src/app/components/show-action-area.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ import { ShowActionButton } from '@app/types/components/show';
@Component({
selector: 'app-show-action-area',
templateUrl: './show-action-area.component.html',
styles: [`
button {
margin-right: 3px;
}
`],
standalone: true,
imports: [
NgIf,
Expand All @@ -18,5 +23,22 @@ import { ShowActionButton } from '@app/types/components/show';
]
})
export class ShowActionAreaComponent {
@Input({required: true}) actions: ShowActionButton[];

isDisabled: { [x: string]: boolean } = {};

private _actions: ShowActionButton[] = [];

get actions() {
return this._actions;
}

@Input({required: true}) set actions(entries : ShowActionButton[]) {
entries.filter(entry => entry.disabled !== undefined).forEach(entry => {
if (entry.disabled) {
this.isDisabled[entry.id] = false;
entry.disabled.subscribe(value => this.isDisabled[entry.id] = value);
}
});
this._actions = entries;
}
}
2 changes: 1 addition & 1 deletion src/app/components/show-actions.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<div class="smallSpace"></div>

<button mat-flat-button color="primary" (click)="onRefreshClick()" matTooltip="Refresh data">
<mat-icon aria-hidden="true" [fontIcon]="getRefreshIcon()"></mat-icon>
<mat-icon aria-hidden="true" [fontIcon]="getRefreshIcon()"/>
<span i18n>Refresh</span>
</button>

Expand Down
3 changes: 0 additions & 3 deletions src/app/components/show-actions.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { MatIconModule } from '@angular/material/icon';
import { MatToolbarModule } from '@angular/material/toolbar';
import { RouterModule } from '@angular/router';
import { ShowActionButton } from '@app/types/components/show';
import { DataRaw } from '@app/types/data';
import { IconsService } from '@services/icons.service';
import { ShowActionAreaComponent } from './show-action-area.component';

Expand Down Expand Up @@ -38,8 +37,6 @@ import { ShowActionAreaComponent } from './show-action-area.component';
})
export class ShowActionsComponent implements OnInit {
@Input({ required: true }) actionsButton: ShowActionButton[];
@Input({ required: true }) data: DataRaw = {} as DataRaw;
@Input() id: string | null = null;
@Output() refresh = new EventEmitter<never>();

rightActions: ShowActionButton[];
Expand Down
8 changes: 8 additions & 0 deletions src/app/components/show-card.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<mat-card>
<mat-card-content>
<mat-spinner *ngIf="!data" strokeWidth="4" diameter="40"/>
<ng-container *ngIf="data">
<app-show-card-content [data]="data" [statuses]="statuses"/>
</ng-container>
</mat-card-content>
</mat-card>
27 changes: 27 additions & 0 deletions src/app/components/show-card.component.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Subject } from 'rxjs';
import { ResultRaw } from '@app/results/types';
import { ShowCardComponent } from './show-card.component';

describe('ShowCardComponent', () => {

let component: ShowCardComponent<ResultRaw>;

const spy = {
subscribe: jest.fn()
} as unknown as Subject<ResultRaw>;

beforeEach(() => {
component = new ShowCardComponent();
component.data$ = spy;
component.ngOnInit();
});

it('should create', () => {
expect(component).toBeTruthy();
});

it('should subscribe to data$', () => {
expect(spy.subscribe).toHaveBeenCalled();
});

});
27 changes: 12 additions & 15 deletions src/app/components/show-card.component.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,20 @@
import { JsonPipe, NgFor, NgIf } from '@angular/common';
import { Component, Input } from '@angular/core';
import { Component, Input, OnInit } from '@angular/core';
import { MatCardModule } from '@angular/material/card';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { Subject } from 'rxjs';
import { DataRaw } from '@app/types/data';
import { ShowCardContentComponent } from './show-card-content.component';

@Component({
selector: 'app-show-card',
template: `
<mat-card>
<mat-card-content>
<mat-spinner *ngIf="!data" strokeWidth="4" diameter="40"></mat-spinner>
<ng-container *ngIf="data">
<app-show-card-content [data]="data" [statuses]="statuses"></app-show-card-content>
</ng-container>
</mat-card-content>
</mat-card>
`,
templateUrl: 'show-card.component.html',
styles: [`
pre {
margin-top: 0;
}
`],
standalone: true,
providers: [
],
imports: [
NgIf,
NgFor,
Expand All @@ -33,7 +24,13 @@ pre {
MatProgressSpinnerModule
]
})
export class ShowCardComponent<T extends object> {
@Input({ required: true }) data: T | null = null;
export class ShowCardComponent<T extends DataRaw> implements OnInit {
@Input({ required: true }) data$: Subject<T>;
@Input() statuses: Record<number, string> = [];

data: T | null = null;

ngOnInit(): void {
this.data$.subscribe(data => this.data = data);
}
}
11 changes: 11 additions & 0 deletions src/app/components/show-page.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<app-page-header [sharableURL]="sharableURL">
<ng-content></ng-content>
<span>{{ id }}</span>
<button mat-icon-button [cdkCopyToClipboard]="id ?? ''" (cdkCopyToClipboardCopied)="onCopiedTaskId()">
<mat-icon aria-hidden="true" fontIcon="content_copy" />
</button>
</app-page-header>

<app-show-actions [actionsButton]="actionsButton" (refresh)="onRefresh()" />

<app-show-card [data$]="data$" [statuses]="statuses" />
3 changes: 2 additions & 1 deletion src/app/components/show-page.component.spec.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { TestBed } from '@angular/core/testing';
import { DataRaw } from '@app/types/data';
import { NotificationService } from '@services/notification.service';
import { ShowPageComponent } from './show-page.component';

describe('ShowPageComponent', () => {
let component: ShowPageComponent;
let component: ShowPageComponent<DataRaw>;

const mockNotificationService = {
success: jest.fn()
Expand Down
21 changes: 4 additions & 17 deletions src/app/components/show-page.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Component, EventEmitter, Input, Output, inject } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon';
import { MatSnackBar } from '@angular/material/snack-bar';
import { Subject } from 'rxjs';
import { ShowActionButton } from '@app/types/components/show';
import { DataRaw } from '@app/types/data';
import { NotificationService } from '@services/notification.service';
Expand All @@ -13,21 +14,7 @@ import { ShowCardComponent } from './show-card.component';

@Component({
selector: 'app-show-page',
template: `
<app-page-header [sharableURL]="sharableURL">
<ng-content> </ng-content>
<span>{{ id }}</span>
<button mat-icon-button [cdkCopyToClipboard]="id ?? ''" (cdkCopyToClipboardCopied)="onCopiedTaskId()">
<mat-icon aria-hidden="true" fontIcon="content_copy" />
</button>
</app-page-header>
<ng-container *ngIf="data">
<app-show-actions [id]="id" [actionsButton]="actionsButton" [data]="data" (refresh)="onRefresh()" />
</ng-container>
<app-show-card [data]="data" [statuses]="statuses" />
`,
templateUrl: './show-page.component.html',
styles: [`
span {
font-style: italic;
Expand All @@ -49,9 +36,9 @@ span {
MatButtonModule
]
})
export class ShowPageComponent {
export class ShowPageComponent<T extends DataRaw>{
@Input({ required: true }) id: string | null = null;
@Input({ required: true }) data: DataRaw | null = null;
@Input({ required: true }) data$: Subject<T>;
@Input() statuses: Record<number, string> = [];
@Input() sharableURL: string | null = null;
@Input({ required: true }) actionsButton: ShowActionButton[];
Expand Down
5 changes: 2 additions & 3 deletions src/app/partitions/show.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,12 @@ import { TableService } from '@services/table.service';
import { UtilsService } from '@services/utils.service';
import { PartitionsFiltersService } from './services/partitions-filters.service';
import { PartitionsGrpcService } from './services/partitions-grpc.service';
import { PartitionsIndexService } from './services/partitions-index.service';
import { PartitionRaw } from './types';

@Component({
selector: 'app-partitions-show',
template: `
<app-show-page [id]="data?.id ?? ''" [data]="data" [sharableURL]="sharableURL" [actionsButton]="actionButtons" (refresh)="onRefresh()">
<app-show-page [id]="data?.id ?? ''" [data$]="data$" [sharableURL]="sharableURL" [actionsButton]="actionButtons" (refresh)="onRefresh()">
<mat-icon matListItemIcon aria-hidden="true" [fontIcon]="getPageIcon('partitions')"></mat-icon>
<span i18n="Page title">Partition</span>
</app-show-page>
Expand All @@ -34,7 +33,6 @@ import { PartitionRaw } from './types';
ShareUrlService,
QueryParamsService,
PartitionsGrpcService,
PartitionsIndexService,
PartitionsFiltersService,
TableService,
TableURLService,
Expand Down Expand Up @@ -89,6 +87,7 @@ export class ShowComponent extends AppShowComponent<PartitionRaw, PartitionsGrpc
this.data = data;
this._filtersService.createFilterQueryParams(this.actionButtons, 'sessions', this.partitionsKey, this.data.id);
this._filtersService.createFilterQueryParams(this.actionButtons, 'tasks', this.tasksKey, this.data.id);
this.data$.next(data);
}
});

Expand Down
5 changes: 2 additions & 3 deletions src/app/results/show.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,13 @@ import { TableService } from '@services/table.service';
import { UtilsService } from '@services/utils.service';
import { ResultsFiltersService } from './services/results-filters.service';
import { ResultsGrpcService } from './services/results-grpc.service';
import { ResultsIndexService } from './services/results-index.service';
import { ResultsStatusesService } from './services/results-statuses.service';import { ResultRaw } from './types';


@Component({
selector: 'app-result-show',
template: `
<app-show-page [id]="data?.resultId ?? ''" [data]="data" [sharableURL]="sharableURL" [statuses]="statuses" [actionsButton]="actionButtons" (refresh)="onRefresh()">
<app-show-page [id]="data?.resultId ?? ''" [data$]="data$" [sharableURL]="sharableURL" [statuses]="statuses" [actionsButton]="actionButtons" (refresh)="onRefresh()">
<mat-icon matListItemIcon aria-hidden="true" [fontIcon]="getPageIcon('results')"></mat-icon>
<span i18n="Page title"> Result </span>
</app-show-page>
Expand All @@ -34,7 +33,6 @@ import { ResultsStatusesService } from './services/results-statuses.service';imp
QueryParamsService,
ResultsGrpcService,
ResultsStatusesService,
ResultsIndexService,
TableService,
TableStorageService,
TableURLService,
Expand Down Expand Up @@ -85,6 +83,7 @@ export class ShowComponent extends AppShowComponent<ResultRaw, ResultsGrpcServic
this.data = data;
this.setLink('session', 'sessions', data.sessionId);
this.setLink('task', 'tasks', data.ownerTaskId);
this.data$.next(data);
}
});

Expand Down
2 changes: 1 addition & 1 deletion src/app/sessions/services/sessions-statuses.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export class SessionsStatusesService implements StatusesServiceI<SessionStatus>
}

canCancel(status: SessionStatus) {
return status !== SessionStatus.SESSION_STATUS_RUNNING;
return status === SessionStatus.SESSION_STATUS_RUNNING;
}

canClose(status: SessionStatus) {
Expand Down
Loading

1 comment on commit 03e999a

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lines Statements Branches Functions
Coverage: 90%
90.08% (2743/3045) 73.13% (509/696) 82.58% (645/781)

JUnit

Tests Skipped Failures Errors Time
785 0 💤 0 ❌ 0 🔥 1m 1s ⏱️
Files coverage (90%)
File% Stmts% Branch% Funcs% LinesUncovered Line #s
All files90.0873.1382.5890.54 
applications100100100100 
   index.component.ts100100100100 
applications/components92.382.681.8195.16 
   table.component.ts92.382.681.8195.16134, 190, 204
applications/services87.577.7776.1988.23 
   applications-filters.service.ts79.1610062.581.8175–81
   applications-grpc.service.ts9271.4210091.6676–82
   applications-index.service.ts91.366.668090.970–74
components96.291.392.5396.68 
   actions-toolbar-group.component.ts100100100100 
   actions-toolbar.component.ts100100100100 
   auto-refresh-button.component.html100100100100 
   auto-refresh-button.component.ts1006010010036, 59
   auto-refresh-dialog.component.html100100100100 
   auto-refresh-dialog.component.ts100100100100 
   columns-button.component.ts100100100100 
   columns-modify-dialog.component.html100100100100 
   columns-modify-dialog.component.ts94.599089.4710050
   count-tasks-by-status.component.ts1005010010056
   icon-picker-dialog.component.html100100100100 
   icon-picker-dialog.component.ts92.855010092.5958, 71
   page-header.component.html100100100100 
   page-header.component.ts8010008033
   page-section-header.component.ts8010008031
   page-section.component.ts100100100100 
   refresh-button.component.ts100100100100 
   share-url.component.ts92.851007592.337
   show-action-area.component.html100100100100 
   show-action-area.component.ts100100100100 
   show-actions.component.html100100100100 
   show-actions.component.ts100100100100 
   show-card-content.component.html100100100100 
   show-card-content.component.ts100100100100 
   show-card.component.html100100100100 
   show-card.component.ts90.910066.66100 
   show-page.component.html100100100100 
   show-page.component.ts100100100100 
   spinner.component.ts100100100100 
   table-actions-toolbar.component.html100100100100 
   table-actions-toolbar.component.ts100100100100 
   table-container.component.ts100100100100 
   view-tasks-by-status-dialog.component.html100100100100 
   view-tasks-by-status-dialog.component.ts100100100100 
   view-tasks-by-status.component.ts73.5206072.7259, 88–106
components/filters94.2187.493.5894.24 
   filters-chips.component.html100100100100 
   filters-chips.component.ts100100100100 
   filters-dialog-and.component.html100100100100 
   filters-dialog-and.component.ts100100100100 
   filters-dialog-filter-field.component.html100100100100 
   filters-dialog-filter-field.component.ts92.9487.597.2992.36104, 114, 124, 136–139, 147, 192–194, 201, 334
   filters-dialog-input.component.html100100100100 
   filters-dialog-input.component.ts8278.7871.4283.3357, 85–86, 142–151
   filters-dialog-or.component.html100100100100 
   filters-dialog-or.component.ts100100100100 
   filters-dialog.component.html100100100100 
   filters-dialog.component.ts100100100100 
   filters-toolbar.component.html100100100100 
   filters-toolbar.component.ts100100100100 
components/navigation99.1197.0595.8399.07 
   add-external-service-dialog.component.html100100100100 
   add-external-service-dialog.component.ts100100100100 
   change-language-button.component.html100100100100 
   change-language-button.component.ts97.291009096.9657
   edit-external-service-dialog.component.html100100100100 
   edit-external-service-dialog.component.ts100100100100 
   form-external-service.component.html100100100100 
   form-external-service.component.ts100100100100 
   manage-external-services-dialog.component.html100100100100 
   manage-external-services-dialog.component.ts100100100100 
   navigation.component.html100100100100 
   navigation.component.ts98.1893.3388.8898.14113
   theme-selector.component.html100100100100 
   theme-selector.component.ts100100100100 
components/table79.7964.767.8579.59 
   table-actions.component.html100100100100 
   table-actions.component.ts87.5100087.529
   table-cell.component.html100100100100 
   table-cell.component.ts89.4778.5790.4789.4749, 102, 116, 126–130
   table-empty-data.component.ts100100100100 
   table-inspect-object-dialog.component.html100100100100 
   table-inspect-object-dialog.component.ts41.66100041.6626–40
   table-inspect-object.component.html100100100100 
   table-inspect-object.component.ts60006031–50
dashboard89.0135.7193.3388.88 
   index.component.html100100100100 
   index.component.ts88.8835.7193.3388.76166–180, 193, 231
dashboard/components99.210098.5799.19 
   add-line-dialog.component.ts100100100100 
   add-statuses-group-dialog.component.ts100100100100 
   edit-name-line-dialog.component.ts100100100100 
   edit-status-group-dialog.component.ts100100100100 
   form-name-line.component.html100100100100 
   form-name-line.component.ts95.6510083.3395.6586
   form-statuses-group.component.html100100100100 
   form-statuses-group.component.ts100100100100 
   manage-groups-dialog.component.html100100100100 
   manage-groups-dialog.component.ts100100100100 
   reorganize-lines-dialog.component.html100100100100 
   reorganize-lines-dialog.component.ts100100100100 
   split-lines-dialog.component.ts100100100100 
   statuses-group-card.component.html100100100100 
   statuses-group-card.component.ts97.9110010097.72138
dashboard/components/lines98.0188.8895.7497.96 
   applications-line.component.html100100100100 
   applications-line.component.ts97.4390.996.2997.36138–140
   task-by-status-line.component.html100100100100 
   task-by-status-line.component.ts98.7985.719598.76210
dashboard/services100100100100 
   dashboard-index.service.ts100100100100 
   dashboard-storage.service.ts100100100100 
directives50100050 
   no-wrap.directive.ts501000505–6
healthcheck100100100100 
   index.component.html100100100100 
   index.component.ts100100100100 
healthcheck/services100100100100 
   healthcheck-grpc.service.ts100100100100 
   healthcheck-index.service.ts100100100100 
partitions/components96.159088.8896.07 
   table.component.html100100100100 
   table.component.ts96.079088.889674, 121
partitions/services21.730018.18 
   partitions-index.service.ts21.730018.1811–120
pipes250018.18 
   duration.pipe.ts16.660011.767–27
   empty-cell.pipe.ts5000406–10
results/components97.051007596.96 
   table.component.html100100100100 
   table.component.ts96.961007596.8776
results/services34.4808.3329.62 
   results-index.service.ts21.730018.1810–117
   results-statuses.service.ts83.33100508016
services93.577.5386.9193.54 
   auto-refresh.service.ts100100100100 
   default-config.service.ts10050100100193
   environment.service.ts80100507519
   filters.service.ts50037.55277–93
   grpc-build-request.service.ts64.288.3316.6664.2826, 39, 49, 59, 69
   icons.service.ts100100100100 
   navigation.service.ts10080100100116
   notification.service.ts100100100100 
   query-params.service.ts100100100100 
   share-url.service.ts100100100100 
   storage.service.ts98.0310010097.9595
   table-storage.service.ts500042.8511–31
   table-url.service.ts100100100100 
   table.service.ts100100100100 
   tasks-by-status.service.ts100100100100 
   user-grpc.service.ts100100100100 
   user.service.ts100100100100 
   utils.service.ts97.5694.1110097.43119
   versions-grpc.service.ts100100100100 
   versions.service.ts1007010010014, 25, 32
sessions/components82.0770.8353.8487.62 
   table.component.html100100100100 
   table.component.ts81.970.8353.8487.5128–144, 219–229, 251
sessions/services46.3721.4225.9245.31 
   sessions-filters.service.ts66.66506070168–186
   sessions-index.service.ts17.850014.8111–218
   sessions-statuses.service.ts62.51002557.1418–26
tasks/components76.9242.8554.1681.63 
   table.component.html100100100100 
   table.component.ts76.6942.8554.1681.44131–143, 167–189, 202
tasks/services60.95266060.6 
   tasks-filters.service.ts69.6983.336073.33207–220
   tasks-grpc.service.ts21.210018.7513–155
   tasks-index.service.ts87.09808086.66229, 295–300
   tasks-statuses.service.ts87.507585.7141
tokens100100100100 
   filters.token.ts100100100100 
types100100100100 
   filter-definition.ts100100100100 
types/components89.655088.8892.15 
   table.ts89.655088.8892.1549, 81, 88–89

Please sign in to comment.