Skip to content

Commit

Permalink
feat: lock and unlock columns for tables (#742)
Browse files Browse the repository at this point in the history
Co-authored-by: yannick-aneo <[email protected]>
  • Loading branch information
fdewas-aneo and yannick-aneo authored Oct 18, 2023
1 parent f8b24b2 commit 95dbad6
Show file tree
Hide file tree
Showing 19 changed files with 198 additions and 11 deletions.
11 changes: 10 additions & 1 deletion src/app/applications/index.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,13 @@ import { ApplicationRaw, ApplicationRawColumnKey, ApplicationRawFieldKey, Applic
[columnsLabels]="columnsLabels()"
[displayedColumns]="displayedColumns"
[availableColumns]="availableColumns"
[lockColumns]="lockColumns"
(refresh)="onRefresh()"
(intervalValueChange)="onIntervalValueChange($event)"
(displayedColumnsChange)="onColumnsChange($event)"
(resetColumns)="onColumnsReset()"
(resetFilters)="onFiltersReset()"
(lockColumnsChange)="onLockColumnsChange()"
>
<ng-container extra-menu-items>
<button mat-menu-item (click)="personalizeTasksByStatus()">
Expand All @@ -85,7 +87,7 @@ import { ApplicationRaw, ApplicationRawColumnKey, ApplicationRawFieldKey, Applic
</mat-toolbar>
<app-table-container>
<table mat-table matSort [matSortActive]="options.sort.active" matSortDisableClear [matSortDirection]="options.sort.direction" [dataSource]="data" cdkDropList cdkDropListOrientation="horizontal" (cdkDropListDropped)="onDrop($event)">
<table mat-table matSort [matSortActive]="options.sort.active" matSortDisableClear [matSortDirection]="options.sort.direction" [dataSource]="data" cdkDropList cdkDropListOrientation="horizontal" [cdkDropListDisabled]="lockColumns" (cdkDropListDropped)="onDrop($event)">
<ng-container *ngFor="let column of displayedColumns" [matColumnDef]="column">
<!-- Header -->
Expand Down Expand Up @@ -210,6 +212,7 @@ export class IndexComponent implements OnInit, AfterViewInit, OnDestroy {

displayedColumns: ApplicationRawColumnKey[] = [];
availableColumns: ApplicationRawColumnKey[] = [];
lockColumns: boolean = false;

isLoading = true;
data: ApplicationRaw[] = [];
Expand Down Expand Up @@ -243,6 +246,7 @@ export class IndexComponent implements OnInit, AfterViewInit, OnDestroy {
ngOnInit(): void {
this.displayedColumns = this._applicationsIndexService.restoreColumns();
this.availableColumns = this._applicationsIndexService.availableColumns;
this.lockColumns = this._applicationsIndexService.restoreLockColumns();

this.options = this._applicationsIndexService.restoreOptions();

Expand Down Expand Up @@ -380,6 +384,11 @@ export class IndexComponent implements OnInit, AfterViewInit, OnDestroy {
this.refresh.next();
}

onLockColumnsChange() {
this.lockColumns = !this.lockColumns;
this._applicationsIndexService.saveLockColumns(this.lockColumns);
}

autoRefreshTooltip() {
return this._autoRefreshService.autoRefreshTooltip(this.intervalValue);
}
Expand Down
13 changes: 13 additions & 0 deletions src/app/applications/services/applications-index.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export class ApplicationsIndexService {
readonly defaultOptions: ApplicationRawListOptions = this.#defaultConfigService.defaultApplications.options;

readonly defaultIntervalValue = this.#defaultConfigService.defaultApplications.interval;
readonly defaultLockColumnValue = this.#defaultConfigService.defaultApplications.lockColumns;

#tableService = inject(TableService);

Expand Down Expand Up @@ -62,6 +63,18 @@ export class ApplicationsIndexService {
return this.#tableService.restoreIntervalValue('applications-interval') ?? this.defaultIntervalValue;
}

/**
* Lock columns
*/

saveLockColumns(value: boolean): void {
this.#tableService.saveLockColumns('applications-lock-columns', value);
}

restoreLockColumns(): boolean {
return this.#tableService.restoreLockColumns('applications-lock-columns') ?? this.defaultLockColumnValue;
}

/**
* Options
*/
Expand Down
3 changes: 2 additions & 1 deletion src/app/components/columns-button.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { ColumnsModifyDialogComponent } from './columns-modify-dialog.component'
@Component({
selector: 'app-columns-button',
template: `
<button mat-stroked-button (click)="openModifyColumnsDialog()">
<button [disabled]="disabled" mat-stroked-button (click)="openModifyColumnsDialog()">
<mat-icon aria-hidden="true" [fontIcon]="getIcon('modify-columns')"></mat-icon>
<span i18n="Open a dialog on click">Modify Columns</span>
</button>
Expand All @@ -31,6 +31,7 @@ export class ColumnsButtonComponent<T extends object, O extends object> {
@Input({ required: true }) columnsLabels: Record<ColumnKey<T, O>, string>;
@Input({ required: true }) displayedColumns: ColumnKey<T, O>[] = [];
@Input({ required: true }) availableColumns: ColumnKey<T, O>[];
@Input({ required: true}) disabled: boolean = false;

@Output() displayedColumnsChange: EventEmitter<ColumnKey<T, O>[]> = new EventEmitter<ColumnKey<T, O>[]>();

Expand Down
6 changes: 6 additions & 0 deletions src/app/components/table-actions-toolbar.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,10 @@ describe('TableActionsToolbarComponent', () => {
component.onResetFilters();
expect(spyOnEventEmitter).toHaveBeenCalled();
});

test('onLockColumns should emit', () => {
spyOnEventEmitter = jest.spyOn(component.lockColumnsChange, 'emit');
component.onLockColumnsChange();
expect(spyOnEventEmitter).toHaveBeenCalled();
});
});
16 changes: 16 additions & 0 deletions src/app/components/table-actions-toolbar.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,23 @@ import { SpinnerComponent } from './spinner.component';
[displayedColumns]="displayedColumns"
[availableColumns]="availableColumns"
(displayedColumnsChange)="onDisplayedColumnsChange($event)"
[disabled]="lockColumns"
>
</app-columns-button>
<button mat-icon-button [matMenuTriggerFor]="menu" aria-label="Show more options" i18n-aria-label matTooltip="More Options" i18n-matTooltip>
<mat-icon aria-hidden="true" [fontIcon]="getIcon('more')"></mat-icon>
</button>
<mat-menu #menu="matMenu">
<button mat-menu-item (click)="onLockColumnsChange()">
<mat-icon aria-hidden="true" [fontIcon]="lockColumns ? getIcon('unlock') : getIcon('lock')"></mat-icon>
<span *ngIf="!lockColumns" i18n>
Lock columns
</span>
<span *ngIf="lockColumns" i18n>
Unlock columns
</span>
</button>
<button mat-menu-item (click)="onResetColumns()">
<mat-icon aria-hidden="true" [fontIcon]="getIcon('format-clear')"></mat-icon>
<span i18n>
Expand Down Expand Up @@ -83,12 +93,14 @@ export class TableActionsToolbarComponent<T extends object, O extends object> {
@Input({ required: true }) columnsLabels: Record<ColumnKey<T, O>, string>;
@Input({ required: true }) displayedColumns: ColumnKey<T, O>[] = [];
@Input({ required: true }) availableColumns: ColumnKey<T, O>[] = [];
@Input({ required: true }) lockColumns = false;

@Output() refresh: EventEmitter<void> = new EventEmitter<void>();
@Output() intervalValueChange: EventEmitter<number> = new EventEmitter<number>();
@Output() displayedColumnsChange: EventEmitter<ColumnKey<T, O>[]> = new EventEmitter<ColumnKey<T, O>[]>();
@Output() resetColumns: EventEmitter<void> = new EventEmitter<void>();
@Output() resetFilters: EventEmitter<void> = new EventEmitter<void>();
@Output() lockColumnsChange = new EventEmitter<void>();

getIcon(name: string): string {
return this.#iconsService.getIcon(name);
Expand All @@ -113,4 +125,8 @@ export class TableActionsToolbarComponent<T extends object, O extends object> {
onResetFilters(): void {
this.resetFilters.emit();
}

onLockColumnsChange(): void {
this.lockColumnsChange.emit();
}
}
14 changes: 12 additions & 2 deletions src/app/partitions/index.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,14 @@ import { PartitionRaw, PartitionRawColumnKey, PartitionRawFieldKey, PartitionRaw
[columnsLabels]="columnsLabels()"
[displayedColumns]="displayedColumns"
[availableColumns]="availableColumns"
[lockColumns]="lockColumns"
(refresh)="onRefresh()"
(intervalValueChange)="onIntervalValueChange($event)"
(displayedColumnsChange)="onColumnsChange($event)"
(resetColumns)="onColumnsReset()"
(resetFilters)="onFiltersReset()">
(resetFilters)="onFiltersReset()"
(lockColumnsChange)="onLockColumnsChange()"
>
<ng-container extra-menu-items>
<button mat-menu-item (click)="personalizeTasksByStatus()">
<mat-icon aria-hidden="true" [fontIcon]="getIcon('tune')"></mat-icon>
Expand All @@ -85,7 +88,7 @@ import { PartitionRaw, PartitionRawColumnKey, PartitionRawFieldKey, PartitionRaw
</mat-toolbar>
<app-table-container>
<table mat-table matSort [matSortActive]="options.sort.active" matSortDisableClear [matSortDirection]="options.sort.direction" [dataSource]="data" cdkDropList cdkDropListOrientation="horizontal" (cdkDropListDropped)="onDrop($event)">
<table mat-table matSort [matSortActive]="options.sort.active" matSortDisableClear [matSortDirection]="options.sort.direction" [dataSource]="data" cdkDropList cdkDropListOrientation="horizontal" [cdkDropListDisabled]="lockColumns" (cdkDropListDropped)="onDrop($event)">
<ng-container *ngFor="let column of displayedColumns" [matColumnDef]="column">
<!-- Header -->
Expand Down Expand Up @@ -228,6 +231,7 @@ export class IndexComponent implements OnInit, AfterViewInit, OnDestroy {

displayedColumns: PartitionRawColumnKey[] = [];
availableColumns: PartitionRawColumnKey[] = [];
lockColumns: boolean;

isLoading = true;
data: PartitionRaw[] = [];
Expand All @@ -254,6 +258,7 @@ export class IndexComponent implements OnInit, AfterViewInit, OnDestroy {
ngOnInit() {
this.displayedColumns = this.#partitionsIndexService.restoreColumns();
this.availableColumns = this.#partitionsIndexService.availableColumns;
this.lockColumns = this.#partitionsIndexService.restoreLockColumns();

this.options = this.#partitionsIndexService.restoreOptions();

Expand Down Expand Up @@ -398,6 +403,11 @@ export class IndexComponent implements OnInit, AfterViewInit, OnDestroy {
this.paginator.pageIndex = 0;
this.refresh.next();
}

onLockColumnsChange() {
this.lockColumns = !this.lockColumns;
this.#partitionsIndexService.saveLockColumns(this.lockColumns);
}

autoRefreshTooltip() {
return this.#autoRefreshService.autoRefreshTooltip(this.intervalValue);
Expand Down
13 changes: 13 additions & 0 deletions src/app/partitions/services/partitions-index.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export class PartitionsIndexService {
readonly tableName: string = 'partitions';

readonly defaultColumns: PartitionRawColumnKey[] = this.#defaultConfigService.defaultPartitions.columns;
readonly defaultLockColumns: boolean = this.#defaultConfigService.defaultPartitions.lockColumns;
readonly availableColumns: PartitionRawColumnKey[] = ['id', 'priority', 'parentPartitionIds', 'podConfiguration', 'podMax', 'podReserved', 'preemptionPercentage', 'actions', 'count'];

// TODO: We could use a custom type to know which columns are objects
Expand Down Expand Up @@ -77,6 +78,18 @@ export class PartitionsIndexService {
return this.#tableService.restoreIntervalValue('partitions-interval') ?? this.defaultIntervalValue;
}

/**
* Lock columns
*/

saveLockColumns(value: boolean): void {
this.#tableService.saveLockColumns('partitions-lock-columns', value);
}

restoreLockColumns(): boolean {
return this.#tableService.restoreLockColumns('partitions-lock-columns') ?? this.defaultLockColumns;
}

/**
* Options
*/
Expand Down
14 changes: 12 additions & 2 deletions src/app/results/index.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,14 @@ import { ResultRaw, ResultRawColumnKey, ResultRawFieldKey, ResultRawFiltersOr, R
[columnsLabels]="columnsLabels()"
[displayedColumns]="displayedColumns"
[availableColumns]="availableColumns"
[lockColumns]="lockColumns"
(refresh)="onRefresh()"
(intervalValueChange)="onIntervalValueChange($event)"
(displayedColumnsChange)="onColumnsChange($event)"
(resetColumns)="onColumnsReset()"
(resetFilters)="onFiltersReset()">
(resetFilters)="onFiltersReset()"
(lockColumnsChange)="onLockColumnsChange()"
>
</app-table-actions-toolbar>
</mat-toolbar-row>
Expand All @@ -70,7 +73,7 @@ import { ResultRaw, ResultRawColumnKey, ResultRawFieldKey, ResultRawFiltersOr, R
</mat-toolbar>
<app-table-container>
<table mat-table matSort [matSortActive]="options.sort.active" matSortDisableClear [matSortDirection]="options.sort.direction" [dataSource]="data" cdkDropList cdkDropListOrientation="horizontal" (cdkDropListDropped)="onDrop($event)">
<table mat-table matSort [matSortActive]="options.sort.active" matSortDisableClear [matSortDirection]="options.sort.direction" [dataSource]="data" cdkDropList cdkDropListOrientation="horizontal" [cdkDropListDisabled]="lockColumns" (cdkDropListDropped)="onDrop($event)">
<ng-container *ngFor="let column of displayedColumns" [matColumnDef]="column">
<!-- Header -->
Expand Down Expand Up @@ -202,6 +205,7 @@ export class IndexComponent implements OnInit, AfterViewInit, OnDestroy {

displayedColumns: ResultRawColumnKey[] = [];
availableColumns: ResultRawColumnKey[] = [];
lockColumns: boolean = false;

isLoading = true;
data: ResultRaw[] = [];
Expand Down Expand Up @@ -234,6 +238,7 @@ export class IndexComponent implements OnInit, AfterViewInit, OnDestroy {
ngOnInit(): void {
this.displayedColumns = this._resultsIndexService.restoreColumns();
this.availableColumns = this._resultsIndexService.availableColumns;
this.lockColumns = this._resultsIndexService.restoreLockColumns();

this.options = this._resultsIndexService.restoreOptions();

Expand Down Expand Up @@ -392,6 +397,11 @@ export class IndexComponent implements OnInit, AfterViewInit, OnDestroy {
this.paginator.pageIndex = 0;
this.refresh.next();
}

onLockColumnsChange() {
this.lockColumns = !this.lockColumns;
this._resultsIndexService.saveLockColumns(this.lockColumns);
}

autoRefreshTooltip() {
return this._autoRefreshService.autoRefreshTooltip(this.intervalValue);
Expand Down
13 changes: 13 additions & 0 deletions src/app/results/services/results-index.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export class ResultsIndexService {
#resultsStatusesService = inject(ResultsStatusesService);

readonly defaultColumns: ResultRawColumnKey[] = this.#defaultConfigService.defaultResults.columns;
readonly defaultLockColumns: boolean = this.#defaultConfigService.defaultResults.lockColumns;
readonly availableColumns: ResultRawColumnKey[] = ['name', 'status', 'ownerTaskId', 'createdAt', 'sessionId', 'actions'];

readonly dateColumns: ResultRawColumnKey[] = ['createdAt'];
Expand Down Expand Up @@ -75,6 +76,18 @@ export class ResultsIndexService {
return this.#tableService.restoreIntervalValue('results-interval') ?? this.defaultIntervalValue;
}

/**
* Lock columns
*/

saveLockColumns(value: boolean): void {
this.#tableService.saveLockColumns('results-lock-columns', value);
}

restoreLockColumns(): boolean {
return this.#tableService.restoreLockColumns('results-lock-columns') ?? this.defaultLockColumns;
}

/**
* Options
*/
Expand Down
10 changes: 10 additions & 0 deletions src/app/services/default-config.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ export class DefaultConfigService {

readonly #defaultApplications: ScopeConfig<ApplicationRawColumnKey, ApplicationRawListOptions, ApplicationRawFilter> = {
interval: 10,
lockColumns: false,
columns: [
'name',
'version',
Expand Down Expand Up @@ -108,6 +109,7 @@ export class DefaultConfigService {

readonly #defaultPartitions: ScopeConfig<PartitionRawColumnKey, PartitionRawListOptions, PartitionRawFiltersOr> = {
interval: 10,
lockColumns: false,
columns: [
'id',
'actions',
Expand All @@ -125,6 +127,7 @@ export class DefaultConfigService {

readonly #defaultSessions: ScopeConfig<SessionRawColumnKey, SessionRawListOptions, SessionRawFiltersOr> = {
interval: 10,
lockColumns: false,
columns: [
'sessionId',
'count',
Expand All @@ -143,6 +146,7 @@ export class DefaultConfigService {

readonly #defaultResults: ScopeConfig<ResultRawColumnKey, ResultRawListOptions, ResultRawFiltersOr> = {
interval: 10,
lockColumns: false,
columns: [
'name',
'actions',
Expand All @@ -160,6 +164,7 @@ export class DefaultConfigService {

readonly #defaultTasks: ScopeConfig<TaskSummaryColumnKey, TaskSummaryListOptions, TaskSummaryFiltersOr> = {
interval: 10,
lockColumns: false,
columns: [
'id',
'status',
Expand Down Expand Up @@ -246,23 +251,28 @@ export class DefaultConfigService {
'applications-options': this.#defaultApplications.options,
'applications-filters': this.#defaultApplications.filters,
'applications-interval': this.#defaultApplications.interval,
'applications-lock-columns': this.#defaultApplications.lockColumns,
'partitions-columns': this.#defaultPartitions.columns,
'partitions-options': this.#defaultPartitions.options,
'partitions-filters': this.#defaultPartitions.filters,
'partitions-interval': this.#defaultPartitions.interval,
'partitions-lock-columns': this.#defaultPartitions.lockColumns,
'sessions-columns': this.#defaultSessions.columns,
'sessions-options': this.#defaultSessions.options,
'sessions-filters': this.#defaultSessions.filters,
'sessions-interval': this.#defaultSessions.interval,
'sessions-lock-columns': this.#defaultSessions.lockColumns,
'results-columns': this.#defaultResults.columns,
'results-options': this.#defaultResults.options,
'results-filters': this.#defaultResults.filters,
'results-interval': this.#defaultResults.interval,
'results-lock-columns': this.#defaultResults.lockColumns,
'tasks-columns': this.#defaultTasks.columns,
'tasks-options': this.#defaultTasks.options,
'tasks-filters': this.#defaultTasks.filters,
'tasks-interval': this.#defaultTasks.interval,
'tasks-view-in-logs': this.#defaultTasksViewInLogs,
'tasks-lock-columns': this.#defaultTasks.lockColumns
};

get exportedDefaultConfig(): ExportedDefaultConfig {
Expand Down
2 changes: 2 additions & 0 deletions src/app/services/icons.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ export class IconsService {
'list': 'view_list',
'vertical-split': 'vertical_split',
'find-logs': 'plagiarism',
'lock': 'lock',
'unlock': 'lock_open'
};

getIcon(name: string): string {
Expand Down
Loading

1 comment on commit 95dbad6

@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: 88%
88.77% (1423/1603) 79.82% (273/342) 79.85% (341/427)

JUnit

Tests Skipped Failures Errors Time
479 0 💤 0 ❌ 0 🔥 1m 6s ⏱️
Files coverage (88%)
File% Stmts% Branch% Funcs% LinesUncovered Line #s
All files88.7779.8279.8588.93 
applications/services100100100100 
   applications-filters.service.ts100100100100 
components92.0394.1181.4493.6 
   actions-toolbar-group.component.ts100100100100 
   actions-toolbar.component.ts100100100100 
   auto-refresh-button.component.ts100100100100 
   auto-refresh-dialog.component.ts100100100100 
   columns-button.component.ts100100100100 
   columns-modify-dialog.component.ts26.660033.3365–123
   count-tasks-by-status.component.ts1005010010048
   page-header.component.ts8010008039
   page-section-header.component.ts8010008031
   page-section.component.ts100100100100 
   refresh-button.component.ts100100100100 
   share-url.component.ts92.851007592.337
   show-card-content.component.ts100100100100 
   spinner.component.ts100100100100 
   table-actions-toolbar.component.ts100100100100 
   view-tasks-by-status-dialog.component.ts100100100100 
   view-tasks-by-status.component.ts100100100100 
components/filters9578.9495.7494.89 
   filters-chips.component.ts100100100100 
   filters-dialog-and.component.ts100100100100 
   filters-dialog-filter-field.component.ts86.275.7592.385.9699–100, 132, 174, 198–202
   filters-dialog-input.component.ts92.8563.6387.592.5973–74
   filters-dialog-or.component.ts100100100100 
   filters-dialog.component.ts100100100100 
   filters-toolbar.component.ts100100100100 
components/navigation99.4410097.3699.42 
   add-external-service-dialog.component.ts100100100100 
   edit-external-service-dialog.component.ts100100100100 
   form-external-service.component.ts100100100100 
   manage-external-services-dialog.component.ts100100100100 
   navigation.component.ts98.1410088.8898.11215
   theme-selector.component.ts100100100100 
dashboard100100100100 
   index.component.ts100100100100 
dashboard/components68.138.8845.6768.24 
   add-line-dialog.component.ts55.55100055.5527–38
   add-statuses-group-dialog.component.ts45.45100045.4529–45
   edit-name-line-dialog.component.ts5010005031–46
   edit-status-group-dialog.component.ts41.66100041.6630–47
   form-name-line.component.ts47.360047.3657–88
   form-statuses-group.component.ts22.50022.582–159
   line.component.ts100100100100 
   manage-groups-dialog.component.ts100100100100 
   reorganize-lines-dialog.component.ts32.430034.28104–160
   split-lines-dialog.component.ts42.850042.8538–61
   statuses-group-card.component.ts100100100100 
dashboard/services52.533.3326.6652.77 
   dashboard-index.service.ts240022.7210–49
   dashboard-storage.service.ts100100100100 
services98.3695.4195.6998.24 
   auto-refresh.service.ts100100100100 
   date-handler.service.ts100100100100 
   default-config.service.ts100100100100 
   environment.service.ts80100507519
   filters.service.ts100100100100 
   icons.service.ts100100100100 
   navigation.service.ts10080100100109
   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.ts100100100100 
   versions-grpc.service.ts100100100100 
   versions.service.ts1007010010014, 25, 32
tasks/services77.455083.7876.53 
   tasks-filters.service.ts100100100100 
   tasks-grpc.service.ts23.330020.6813–151
   tasks-index.service.ts100100100100 
   tasks-statuses.service.ts100100100100 
tokens100100100100 
   filters.token.ts100100100100 

Please sign in to comment.