Commit abb3eefa authored by PECQUOT's avatar PECQUOT

[enh] sampling-equipment.table with sticky columns

TODO must rework resizable columns
parent 4014b5e1
......@@ -22,7 +22,6 @@
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.app.json",
"aot": true,
"allowedCommonJsDependencies": [
"hammerjs",
"angular2-text-mask",
......@@ -87,7 +86,6 @@
}
],
"styles": [
"node_modules/@angular/material/prebuilt-themes/indigo-pink.css",
"src/global.scss",
"node_modules/leaflet/dist/leaflet.css",
"node_modules/prismjs/themes/prism-okaidia.css"
......@@ -119,6 +117,7 @@
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"aot": true,
"budgets": [
{
"type": "initial",
......@@ -143,7 +142,6 @@
],
"optimization": true,
"buildOptimizer": true,
"aot": true,
"outputHashing": "all",
"sourceMap": false,
"extractCss": true,
......
......@@ -57,7 +57,7 @@ const routes: Routes = [
// Table
{
path: 'table',
loadChildren: () => import('./testing/table.testing.module').then(m => m.WrappingTestingModule)
loadChildren: () => import('./testing/table.testing.module').then(m => m.TableTestingModule)
}
]
},
......
......@@ -9,14 +9,11 @@
<!-- Username -->
<mat-form-field>
<input matInput [appAutofocus]="true" [autofocusDelay]="500"
[placeholder]="'USER.EMAIL'|translate"
[placeholder]="'USER.LOGIN'|translate"
formControlName="username"
autocomplete="off"
required>
<mat-error *ngIf="form.controls.username.hasError('required') && form.controls.username.dirty" translate>ERROR.FIELD_REQUIRED</mat-error>
<mat-error *ngIf="form.controls.username.hasError('email') && form.controls.username.dirty">
<span>{{'ERROR.FIELD_NOT_VALID_EMAIL' | translate }}</span>
</mat-error>
</mat-form-field>
<!-- Password -->
......
......@@ -20,23 +20,6 @@ import {HomePage} from "@app/core/home/home";
CacheModule,
IonicStorageModule,
// CommonModule,
// IonicModule,
// TranslateModule,
// ReactiveFormsModule,
// ColorPickerModule,
// TextMaskModule,
// DragDropModule,
// QuicklinkModule,
// Sub-modules
// SharedMaterialModule,
// SharedDirectivesModule,
// SharedPipesModule,
// SharedHotkeysModule,
// HomePage
// FormButtonsBarComponent
],
declarations: [
......@@ -62,24 +45,6 @@ import {HomePage} from "@app/core/home/home";
AuthModal,
// CommonModule,
// IonicModule,
// TranslateModule,
// ReactiveFormsModule,
// ColorPickerModule,
// TextMaskModule,
// DragDropModule,
// QuicklinkModule,
// Sub-modules
// SharedMaterialModule,
// SharedDirectivesModule,
// SharedPipesModule,
// SharedHotkeysModule,
// FormButtonsBarComponent
]
})
export class QuadrigeCoreModule {
......
......@@ -31,22 +31,7 @@ import {SamplingEquipmentTable} from "@app/referential/table/sampling-equipment.
imports: [
QuadrigeCoreModule,
QuadrigeSharedModule,
SharedMaterialModule,
TranslateModule.forChild(),
IonicModule,
MatButtonModule,
MatMenuModule,
MatIconModule,
CommonModule,
MatExpansionModule,
MatTableModule,
MatToolbarModule,
MatFormFieldModule,
MatSelectModule,
MatCheckboxModule,
MatPaginatorModule,
ReactiveFormsModule,
MatInputModule
],
declarations: [
// Pipes
......
......@@ -119,29 +119,34 @@
<ion-label color="danger" class="error" [innerHTML]="error|translate"></ion-label>
</ion-item>
<mat-table #table [dataSource]="dataSource" class="trips-table" matSort matSortActive="id" matSortDirection="asc" [resizable]="true"
matSortDisableClear [trackBy]="trackByFn">
<ng-container matColumnDef="select">
<mat-header-cell class="hidden-xs hidden-sm" *matHeaderCellDef [class.cdk-visually-hidden]="!canEdit">
<div class="table-container">
<table mat-table #table [dataSource]="dataSource" matSort matSortActive="id" matSortDirection="asc" [resizableTable]="true"
matSortDisableClear [trackBy]="trackByFn"
cdkDropList
cdkDropListOrientation="horizontal"
(cdkDropListDropped)="drop($event)"
>
<ng-container matColumnDef="select" sticky>
<th mat-header-cell *matHeaderCellDef [class.cdk-visually-hidden]="!canEdit">
<mat-checkbox (change)="$event ? masterToggle() : null" [checked]="selection.hasValue() && isAllSelected()"
[indeterminate]="selection.hasValue() && !isAllSelected()">
</mat-checkbox>
</mat-header-cell>
<mat-cell class="hidden-xs hidden-sm" *matCellDef="let row" [class.cdk-visually-hidden]="!canEdit">
</th>
<td mat-cell *matCellDef="let row" [class.cdk-visually-hidden]="!canEdit">
<mat-checkbox (click)="$event.stopPropagation()" (change)="$event ? selection.toggle(row) : null" [checked]="selection.isSelected(row)">
</mat-checkbox>
</mat-cell>
</td>
</ng-container>
<!-- Id/code column -->
<ng-container matColumnDef="id">
<mat-header-cell class="hidden-xs hidden-sm" *matHeaderCellDef mat-sort-header [resizableColumn]="true" [resizableColumnDef]="'id'">
<ng-container matColumnDef="id" sticky>
<th mat-header-cell *matHeaderCellDef [resizableColumn]="false" [resizableColumnDef]="'id'">
<app-loading-spinner [loading]="loadingSubject|async">
<ion-label translate>{{idLabel$|async}}</ion-label>
<span mat-sort-header><ion-label translate>REFERENTIAL.ID</ion-label></span>
</app-loading-spinner>
</mat-header-cell>
<mat-cell class="hidden-xs hidden-sm" *matCellDef="let row">
</th>
<td mat-cell *matCellDef="let row">
<mat-form-field *ngIf="idEditable; else readOnlyId" floatLabel="never">
<input matInput [formControl]="row.validator.controls['id']" [placeholder]="idLabel$|async|translate"
[appAutofocus]="row.id == -1 && row.editing"
......@@ -151,72 +156,72 @@
<ng-template #readOnlyId>
<ion-label>{{ row.currentData?.id }}</ion-label>
</ng-template>
</mat-cell>
</td>
</ng-container>
<!-- Name column -->
<ng-container matColumnDef="name">
<mat-header-cell *matHeaderCellDef mat-sort-header [resizableColumn]="true" [resizableColumnDef]="'name'">
<span translate>REFERENTIAL.NAME</span>
</mat-header-cell>
<mat-cell *matCellDef="let row" [class.mat-form-field-disabled]="!row.editing">
<th mat-header-cell *matHeaderCellDef [resizableColumn]="true" [resizableColumnDef]="'name'" resizable>
<span mat-sort-header cdkDrag><ion-label translate>REFERENTIAL.NAME</ion-label></span>
</th>
<td mat-cell *matCellDef="let row" [class.mat-form-field-disabled]="!row.editing">
<mat-form-field floatLabel="never">
<input matInput [formControl]="row.validator.controls['name']" [placeholder]="'REFERENTIAL.NAME'|translate"
[appAutofocus]="row.id == -1 && row.editing"
[readonly]="!row.editing">
<mat-error *ngIf="row.validator.controls['name'].hasError('required')" translate>ERROR.FIELD_REQUIRED</mat-error>
</mat-form-field>
</mat-cell>
</td>
</ng-container>
<!-- Label column -->
<ng-container matColumnDef="label">
<mat-header-cell *matHeaderCellDef mat-sort-header [resizableColumn]="true" [resizableColumnDef]="'label'">
<span translate>REFERENTIAL.LABEL</span>
</mat-header-cell>
<mat-cell *matCellDef="let row">
<th mat-header-cell *matHeaderCellDef [resizableColumn]="true" [resizableColumnDef]="'label'">
<span mat-sort-header cdkDrag><ion-label translate>REFERENTIAL.LABEL</ion-label></span>
</th>
<td mat-cell *matCellDef="let row">
<mat-form-field floatLabel="never">
<input matInput [formControl]="row.validator.controls['label']" [placeholder]="'REFERENTIAL.LABEL'|translate"
[readonly]="!row.editing">
<mat-error *ngIf="row.validator.controls['label'].hasError('required')" translate>ERROR.FIELD_REQUIRED</mat-error>
</mat-form-field>
</mat-cell>
</td>
</ng-container>
<!-- Description column -->
<ng-container matColumnDef="description">
<mat-header-cell *matHeaderCellDef mat-sort-header [resizableColumn]="true" [resizableColumnDef]="'description'">
<span translate>REFERENTIAL.DESCRIPTION</span>
</mat-header-cell>
<mat-cell *matCellDef="let row">
<th mat-header-cell *matHeaderCellDef [resizableColumn]="true" [resizableColumnDef]="'description'">
<span mat-sort-header cdkDrag><ion-label translate>REFERENTIAL.DESCRIPTION</ion-label></span>
</th>
<td mat-cell *matCellDef="let row">
<mat-form-field floatLabel="never">
<input matInput [formControl]="row.validator.controls['description']" [placeholder]="'REFERENTIAL.DESCRIPTION'|translate"
[readonly]="!row.editing">
<mat-error *ngIf="row.validator.controls['description'].hasError('required')" translate>ERROR.FIELD_REQUIRED</mat-error>
</mat-form-field>
</mat-cell>
</td>
</ng-container>
<!-- Size column -->
<ng-container matColumnDef="size">
<mat-header-cell *matHeaderCellDef mat-sort-header [resizableColumn]="true" [resizableColumnDef]="'size'">
<span translate>REFERENTIAL.SAMPLING_EQUIPMENT.SIZE</span>
</mat-header-cell>
<mat-cell *matCellDef="let row">
<th mat-header-cell *matHeaderCellDef [resizableColumn]="true" [resizableColumnDef]="'size'">
<span mat-sort-header cdkDrag><ion-label translate>REFERENTIAL.SAMPLING_EQUIPMENT.SIZE</ion-label></span>
</th>
<td mat-cell *matCellDef="let row">
<mat-form-field floatLabel="never">
<input matInput [formControl]="row.validator.controls['size']" [placeholder]="'REFERENTIAL.SAMPLING_EQUIPMENT.SIZE'|translate"
[readonly]="!row.editing">
<mat-error *ngIf="row.validator.controls['size'].hasError('double')" translate>ERROR.FIELD_INVALID</mat-error>
</mat-form-field>
</mat-cell>
</td>
</ng-container>
<!-- Unit column -->
<!-- <ng-container matColumnDef="unit">-->
<!-- <mat-header-cell *matHeaderCellDef mat-sort-header [resizableColumn]="true" [resizableColumnDef]="'unit'">-->
<!-- <span translate>REFERENTIAL.SAMPLING_EQUIPMENT.UNIT</span>-->
<!-- </mat-header-cell>-->
<!-- <mat-cell *matCellDef="let row" [class.mat-form-field-disabled]="!row.editing">-->
<!-- <th mat-header-cell *matHeaderCellDef [resizableColumn]="true" [resizableColumnDef]="'unit'">-->
<!-- <span mat-sort-header cdkDrag><ion-label translate>REFERENTIAL.SAMPLING_EQUIPMENT.UNIT</ion-label></span>-->
<!-- </th>-->
<!-- <td mat-cell *matCellDef="let row" [class.mat-form-field-disabled]="!row.editing">-->
<!-- <mat-form-field floatLabel="never">-->
<!-- <ion-icon matPrefix *ngIf="row.validator.controls.unitId.value >= 0" [name]="statusById[row.validator.controls.unitId.value]?.icon"></ion-icon>-->
<!-- <mat-select [formControl]="row.validator.controls.unitId" [placeholder]="'REFERENTIAL.SAMPLING_EQUIPMENT.UNIT'|translate">-->
......@@ -230,29 +235,29 @@
<!-- </mat-option>-->
<!-- </mat-select>-->
<!-- </mat-form-field>-->
<!-- </mat-cell>-->
<!-- </td>-->
<!-- </ng-container>-->
<!-- Comment column -->
<ng-container matColumnDef="comments">
<mat-header-cell *matHeaderCellDef class="hidden-xs hidden-sm" [resizableColumn]="false" [resizableColumnDef]="'comment'">
<span translate>REFERENTIAL.COMMENTS</span>
</mat-header-cell>
<mat-cell *matCellDef="let row" class="hidden-xs hidden-sm" >
<th mat-header-cell *matHeaderCellDef [resizableColumn]="false" [resizableColumnDef]="'comment'">
<span cdkDrag><ion-label translate>REFERENTIAL.COMMENTS</ion-label></span>
</th>
<td mat-cell *matCellDef="let row" >
<button mat-icon-button
(click)="openCommentModal($event, row)"
[title]="row.validator.controls.comments.value != null ? row.validator.controls.comments.value : ''">
<ion-icon [color]="row.validator.controls.comments.value ? 'tertiary' : 'medium'" name="chatbox" slot="icon-only"></ion-icon>
</button>
</mat-cell>
</td>
</ng-container>
<!-- Status column -->
<ng-container matColumnDef="status">
<mat-header-cell *matHeaderCellDef mat-sort-header [resizableColumn]="false" [resizableColumnDef]="'status'">
<span translate>REFERENTIAL.STATUS</span>
</mat-header-cell>
<mat-cell *matCellDef="let row" [class.mat-form-field-disabled]="!row.editing">
<th mat-header-cell *matHeaderCellDef [resizableColumn]="false" [resizableColumnDef]="'status'">
<span mat-sort-header cdkDrag><ion-label translate>REFERENTIAL.STATUS</ion-label></span>
</th>
<td mat-cell *matCellDef="let row" [class.mat-form-field-disabled]="!row.editing">
<mat-form-field floatLabel="never">
<ion-icon matPrefix *ngIf="row.validator.controls.statusId.value >= 0" [name]="statusById[row.validator.controls.statusId.value]?.icon"></ion-icon>
<mat-select [formControl]="row.validator.controls.statusId" [placeholder]="'REFERENTIAL.STATUS'|translate">
......@@ -267,36 +272,35 @@
</mat-select>
<mat-error *ngIf="row.validator.controls.statusId.hasError('required')" translate>ERROR.FIELD_REQUIRED</mat-error>
</mat-form-field>
</mat-cell>
</td>
</ng-container>
<!-- CreationDate column -->
<ng-container matColumnDef="creationDate">
<mat-header-cell *matHeaderCellDef mat-sort-header class="mat-cell-date-time">
<span translate>REFERENTIAL.CREATION_DATE</span>
</mat-header-cell>
<mat-cell *matCellDef="let row" class="mat-cell-date-time">
<th mat-header-cell *matHeaderCellDef class="mat-cell-date-time">
<span mat-sort-header cdkDrag><ion-label translate>REFERENTIAL.CREATION_DATE</ion-label></span>
</th>
<td mat-cell *matCellDef="let row" class="mat-cell-date-time">
{{ row.currentData.creationDate | dateFormat: {time: true} }}
</mat-cell>
</td>
</ng-container>
<!-- UpdateDate column -->
<ng-container matColumnDef="updateDate">
<mat-header-cell *matHeaderCellDef mat-sort-header class="mat-cell-date-time">
<span translate>REFERENTIAL.UPDATE_DATE</span>
</mat-header-cell>
<mat-cell *matCellDef="let row" class="mat-cell-date-time">
<th mat-header-cell *matHeaderCellDef class="mat-cell-date-time">
<span mat-sort-header cdkDrag><ion-label translate>REFERENTIAL.UPDATE_DATE</ion-label></span>
</th>
<td mat-cell *matCellDef="let row" class="mat-cell-date-time">
{{ row.currentData.updateDate | dateFormat: {time: true} }}
</mat-cell>
</td>
</ng-container>
<!-- Actions buttons column -->
<ng-container matColumnDef="actions">
<mat-header-cell *matHeaderCellDef [hidden]="!inlineEdition">
<ng-container matColumnDef="actions" stickyEnd>
<th mat-header-cell *matHeaderCellDef [hidden]="!inlineEdition">
<span></span>
</mat-header-cell>
<mat-cell *matCellDef="let row" [hidden]="!inlineEdition">
</th>
<td mat-cell *matCellDef="let row" [hidden]="!inlineEdition">
<!-- undo or delete -->
<button mat-icon-button color="light"
*ngIf="row.validator.invalid"
......@@ -317,16 +321,17 @@
(click)="confirmAndAddRow($event, row)">
<mat-icon>add</mat-icon>
</button>
</mat-cell>
</td>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns;"
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"
[class.mat-row-error]="row.validator.invalid"
[class.mat-row-disabled]="!row.editing"
[class.mat-row-dirty]="row.validator.dirty"
(click)="clickRow($event, row)"></mat-row>
</mat-table>
(click)="clickRow($event, row)"></tr>
</table>
</div>
<!-- Paginator -->
<ion-row class="ion-no-padding">
......
......@@ -18,10 +18,6 @@
}
.mat-table {
.mat-column-id {
max-width: 100px;
padding-left: 0;
}
.mat-column-size {
min-width: 50px;
......@@ -33,17 +29,10 @@
max-width: 150px;
}
.mat-column-status {
max-width: 150px;
}
.mat-column-comments {
max-width: 90px;
}
mat-header-cell.hidden,
mat-cell.hidden {
visibility: hidden;
display: none;
}
//.mat-header-cell.hidden,
//.mat-cell.hidden {
// visibility: hidden;
// display: none;
//}
}
......@@ -6,6 +6,7 @@ import {ActivatedRoute} from "@angular/router";
import {ReferentialValidatorService} from "@app/referential/validator/referential.validator";
import {SamplingEquipmentService} from "@app/referential/services/sampling-equipment.service";
import {SamplingEquipmentValidator} from "@app/referential/validator/sampling-equipment.validator";
import {CdkDragDrop, moveItemInArray} from "@angular/cdk/drag-drop";
@Component({
selector: 'app-sampling-equipment-table',
......@@ -57,4 +58,9 @@ export class SamplingEquipmentTable extends ReferentialTable<SamplingEquipment,
this.submitFilter();
}
drop(event: CdkDragDrop<string[]>) {
const offset = RESERVED_START_COLUMNS.length;
moveItemInArray(this.columns, event.previousIndex + offset, event.currentIndex + offset);
}
}
......@@ -11,14 +11,14 @@
<ion-content class="ion-padding">
<h1>Table with resizable columns</h1>
<h1>Table with resizable columns (method 1)</h1>
<app-referential-table #referentialTable entityName="AnalysisInstrument">
</app-referential-table>
<h1>Table with fixed columns</h1>
<h1>Table with resizable columns (method 2)</h1>
<app-referential-table #referentialTable2 entityName="AnalysisInstrument" [resizable]="false">
</app-referential-table>
<app-resizable-table-test>
</app-resizable-table-test>
</ion-content>
......@@ -10,7 +10,6 @@ import {Referential, ReferentialUtils} from "sumaris-lib";
export class ReferentialTableTestPage implements AfterViewInit {
@ViewChild('referentialTable', {static: true}) referentialTable: ReferentialMemoryTable;
@ViewChild('referentialTable2', {static: true}) referentialTable2: ReferentialMemoryTable;
constructor() {
......@@ -28,7 +27,6 @@ export class ReferentialTableTestPage implements AfterViewInit {
data.push(ReferentialUtils.fromObject({id: 2, label: 'test2', name: 'name2'}));
this.referentialTable.setValue(data);
this.referentialTable2.setValue(data);
}
......
.example-container {
display: flex;
flex-direction: column;
max-height: 500px;
min-width: 300px;
}
.mat-table {
overflow: auto;
max-height: 500px;
}
mwlResizable {
box-sizing: border-box;
}
mat-cell,
mat-footer-cell,
mat-header-cell {
width: 200px;
word-break: break-all;
flex: none;
display: block;
}
mat-header-cell {
border-left: 1px solid #eee;
}
.mat-header-cell {
padding-left: 12px;
padding-right: 12px;
line-height: 46px;
}
.mat-sort-header-button {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.mat-cell {
padding-left: 12px;
padding-right: 12px;
border-left: 1px solid #eee;
}
.mat-cell {
display: inline-block;
vertical-align: middle;
line-height: 2.6em;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
<div class="example-container mat-elevation-z8">
<mat-table #table [dataSource]="dataSource" matSort (matSortChange)="sortData($event)">
<div>
<mat-header-row *matHeaderRowDef="displayedColumns;" class="mat-elevation-z1"></mat-header-row>
</div>
<ng-container *ngFor="let column of displayedColumns" [matColumnDef]="column">
<mat-header-cell *matHeaderCellDef mat-sort-header mwlResizable [enableGhostResize]="true" (resizeEnd)="onResizeEnd($event, column)"
[resizeEdges]="{bottom: false, right: true, top: false, left: true}">
{{ column | titlecase }}
</mat-header-cell>
<mat-cell *matCellDef="let item">{{ item[column] }}</mat-cell>
</ng-container>
<mat-row matRipple id="row-{{index}}" *matRowDef="let row; columns: displayedColumns; let index = index;" (click)="selectRow(index)">
</mat-row>
</mat-table>
</div>
import {AfterViewInit, Component} from "@angular/core";
import {MatTableDataSource} from "@angular/material/table";
import {ResizeEvent} from "angular-resizable-element";
@Component({
selector: 'app-resizable-table-test',
templateUrl: './resizable.table.test.html',
styleUrls: ['./resizable.table.test.css']
})
export class ResizableTableTestPage implements AfterViewInit {
displayedColumns = ['position', 'name', 'weight', 'symbol'];
dataSource = new MatTableDataSource<Element>(ELEMENT_DATA);
constructor() {
}
ngAfterViewInit(): void {