Commit cf1c3a54 authored by PECQUOT's avatar PECQUOT

[enh] add resizable module (see sampling-equipment.table.html for example)

parent abb3eefa
......@@ -5,25 +5,10 @@ import {ReferentialForm} from "./form/referential.form";
import {ReferentialMemoryTable} from "./list/referential-memory.table";
import {ReferentialToStringPipe} from "./pipes/referential-to-string.pipe";
import {TranslateModule} from "@ngx-translate/core";
import {SharedMaterialModule} from "sumaris-lib";
import {QuadrigeCoreModule} from "../core/quadrige.core.module";
import {QuadrigeSharedModule} from "../shared/quadrige.shared.module";
import {IonicModule} from "@ionic/angular";
import {ReferentialMenu} from "@app/referential/menu/referential.menu";
import {MatButtonModule} from "@angular/material/button";
import {MatMenuModule} from "@angular/material/menu";
import {MatIconModule} from "@angular/material/icon";
import {CommonModule} from "@angular/common";
import {ReferentialGenericTable} from "@app/referential/table/referential.generic.table";
import {MatExpansionModule} from "@angular/material/expansion";
import {MatTableModule} from "@angular/material/table";
import {MatToolbarModule} from "@angular/material/toolbar";
import {MatFormFieldModule} from "@angular/material/form-field";
import {MatSelectModule} from "@angular/material/select";
import {MatCheckboxModule} from "@angular/material/checkbox";
import {MatPaginatorModule} from "@angular/material/paginator";
import {ReactiveFormsModule} from "@angular/forms";
import {MatInputModule} from "@angular/material/input";
import {SamplingEquipmentTable} from "@app/referential/table/sampling-equipment.table";
......@@ -46,6 +31,8 @@ import {SamplingEquipmentTable} from "@app/referential/table/sampling-equipment.
SamplingEquipmentTable
],
exports: [
QuadrigeCoreModule,
QuadrigeSharedModule,
TranslateModule,
// Pipes
......
......@@ -120,7 +120,7 @@
</ion-item>
<div class="table-container">
<table mat-table #table [dataSource]="dataSource" matSort matSortActive="id" matSortDirection="asc" [resizableTable]="true"
<table mat-table #table [dataSource]="dataSource" matSort matSortActive="id" matSortDirection="asc" [resizableTable]="false"
matSortDisableClear [trackBy]="trackByFn"
cdkDropList
cdkDropListOrientation="horizontal"
......@@ -176,7 +176,7 @@
<!-- Label column -->
<ng-container matColumnDef="label">
<th mat-header-cell *matHeaderCellDef [resizableColumn]="true" [resizableColumnDef]="'label'">
<th mat-header-cell *matHeaderCellDef [resizableColumn]="true" [resizableColumnDef]="'label'" resizable>
<span mat-sort-header cdkDrag><ion-label translate>REFERENTIAL.LABEL</ion-label></span>
</th>
<td mat-cell *matCellDef="let row">
......@@ -190,7 +190,7 @@
<!-- Description column -->
<ng-container matColumnDef="description">
<th mat-header-cell *matHeaderCellDef [resizableColumn]="true" [resizableColumnDef]="'description'">
<th mat-header-cell *matHeaderCellDef [resizableColumn]="true" [resizableColumnDef]="'description'" resizable>
<span mat-sort-header cdkDrag><ion-label translate>REFERENTIAL.DESCRIPTION</ion-label></span>
</th>
<td mat-cell *matCellDef="let row">
......@@ -204,7 +204,7 @@
<!-- Size column -->
<ng-container matColumnDef="size">
<th mat-header-cell *matHeaderCellDef [resizableColumn]="true" [resizableColumnDef]="'size'">
<th mat-header-cell *matHeaderCellDef [resizableColumn]="true" [resizableColumnDef]="'size'" resizable>
<span mat-sort-header cdkDrag><ion-label translate>REFERENTIAL.SAMPLING_EQUIPMENT.SIZE</ion-label></span>
</th>
<td mat-cell *matCellDef="let row">
......@@ -218,7 +218,7 @@
<!-- Unit column -->
<!-- <ng-container matColumnDef="unit">-->
<!-- <th mat-header-cell *matHeaderCellDef [resizableColumn]="true" [resizableColumnDef]="'unit'">-->
<!-- <th mat-header-cell *matHeaderCellDef [resizableColumn]="true" [resizableColumnDef]="'unit'" resizable>-->
<!-- <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">-->
......
......@@ -20,13 +20,13 @@
.mat-table {
.mat-column-size {
min-width: 50px;
max-width: 150px;
width: 50px;
//max-width: 150px;
}
.mat-column-unit {
min-width: 50px;
max-width: 150px;
width: 50px;
//max-width: 150px;
}
......
......@@ -3,7 +3,6 @@ import {EntitiesTableDataSource, EnvironmentService, RESERVED_END_COLUMNS, RESER
import {ReferentialTable} from "@app/referential/table/referential.table";
import {SamplingEquipment, SamplingEquipmentFilter} from "@app/referential/model/sampling-equipment.model";
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";
......
......@@ -16,9 +16,5 @@
<app-referential-table #referentialTable entityName="AnalysisInstrument">
</app-referential-table>
<h1>Table with resizable columns (method 2)</h1>
<app-resizable-table-test>
</app-resizable-table-test>
</ion-content>
.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 {
}
onResizeEnd(event: ResizeEvent, columnName): void {
if (event.edges.right) {
const cssValue = event.rectangle.width + 'px';
const columnElts = document.getElementsByClassName('mat-column-' + columnName);
for (let i = 0; i < columnElts.length; i++) {
const currentEl = columnElts[i] as HTMLDivElement;
currentEl.style.width = cssValue;
}
}
}
}
export interface Element {
name: string;
position: number;
weight: number;
symbol: string;
}
const ELEMENT_DATA: Element[] = [
{position: 1, name: 'Hydrogen', weight: 1.0079, symbol: 'H'},
{position: 2, name: 'Helium', weight: 4.0026, symbol: 'He'},
{position: 3, name: 'Lithium', weight: 6.941, symbol: 'Li'},
{position: 4, name: 'Beryllium', weight: 9.0122, symbol: 'Be'},
{position: 5, name: 'Boron', weight: 10.811, symbol: 'B'},
{position: 6, name: 'Carbon', weight: 12.0107, symbol: 'C'},
{position: 7, name: 'Nitrogen', weight: 14.0067, symbol: 'N'},
{position: 8, name: 'Oxygen', weight: 15.9994, symbol: 'O'},
{position: 9, name: 'Fluorine', weight: 18.9984, symbol: 'F'},
{position: 10, name: 'Neon', weight: 20.1797, symbol: 'Ne'},
{position: 11, name: 'Sodium', weight: 22.9897, symbol: 'Na'},
{position: 12, name: 'Magnesium', weight: 24.305, symbol: 'Mg'},
{position: 13, name: 'Aluminum', weight: 26.9815, symbol: 'Al'},
{position: 14, name: 'Silicon', weight: 28.0855, symbol: 'Si'},
{position: 15, name: 'Phosphorus', weight: 30.9738, symbol: 'P'},
{position: 16, name: 'Sulfur', weight: 32.065, symbol: 'S'},
{position: 17, name: 'Chlorine', weight: 35.453, symbol: 'Cl'},
{position: 18, name: 'Argon', weight: 39.948, symbol: 'Ar'},
{position: 19, name: 'Potassium', weight: 39.0983, symbol: 'K'},
{position: 20, name: 'Calcium', weight: 40.078, symbol: 'Ca'},
];
import {Component, HostBinding} from "@angular/core";
@Component({
selector: "th[resizable]",
templateUrl: "./resizable.template.html",
styleUrls: ["./resizable.style.scss"],
})
export class ResizableComponent {
@HostBinding("style.width.px")
width: number | null = null;
@HostBinding("style.min-width.px")
minWidth: number | null = null;
onResize(width: number) {
this.width = width;
this.minWidth = width;
}
}
import {DOCUMENT} from "@angular/common";
import {Directive, ElementRef, Inject, Output} from "@angular/core";
import {distinctUntilChanged, map, switchMap, takeUntil, tap} from "rxjs/operators";
import {fromEvent} from "rxjs";
@Directive({
selector: "[resizable]"
})
export class ResizableDirective {
@Output()
readonly resizable = fromEvent<MouseEvent>(
this.elementRef.nativeElement,
"mousedown"
).pipe(
tap(e => e.preventDefault()),
switchMap(() => {
const {width, right} = this.elementRef.nativeElement
.closest("th")
.getBoundingClientRect();
return fromEvent<MouseEvent>(this.documentRef, "mousemove").pipe(
map(({clientX}) => width + clientX - right),
distinctUntilChanged(),
takeUntil(fromEvent(this.documentRef, "mouseup"))
);
})
);
constructor(
@Inject(DOCUMENT) private readonly documentRef: Document,
@Inject(ElementRef)
private readonly elementRef: ElementRef<HTMLElement>
) {
}
}
import {NgModule} from '@angular/core';
import {ResizableComponent} from './resizable.component';
import {ResizableDirective} from './resizable.directive';
@NgModule({
declarations: [ResizableComponent, ResizableDirective],
exports: [ResizableComponent],
})
export class ResizableModule {
}
:host {
&:last-child .bar {
display: none;
}
}
.wrapper {
display: flex;
justify-content: flex-end;
align-items: center;
}
.content {
flex: 1;
}
.bar {
// absolute
//position: absolute;
//top: 0;
//bottom: 0;
// or relative
height: 55px;
width: 10px;
margin: 0 -16px 0 16px;
justify-self: flex-end;
border-left: 4px solid transparent;
border-right: 4px solid transparent;
background: var(--ion-color-secondary);
background-clip: content-box;
cursor: ew-resize;
opacity: 0;
transition: opacity .3s;
&:hover,
&:active {
opacity: 1;
}
}
<div class="wrapper">
<div class="content">
<ng-content></ng-content>
</div>
<div class="bar" (resizable)="onResize($event)"></div>
</div>
......@@ -4,12 +4,11 @@ import {SharedModule} from "sumaris-lib";
import {ResizableColumnDirective} from "./directive/resizable-column.directive";
import {ResizableTableDirective} from "./directive/resizable-table.directive";
import {environment} from "@environments/environment";
import {ComponentDirtyGuard} from "@app/shared/table/component-dirty.guard";
import {CommentModal} from "@app/shared/comment/comment.modal";
import {CommentForm} from "@app/shared/comment/comment.form";
import {IonicModule} from "@ionic/angular";
import {TranslateModule} from "@ngx-translate/core";
import {MatFormFieldModule} from "@angular/material/form-field";
import {ResizableModule} from "@app/shared/directive/resizable/resizable.module";
@NgModule({
......@@ -18,7 +17,8 @@ import {MatFormFieldModule} from "@angular/material/form-field";
// TranslateModule.forChild(),
SharedModule.forRoot(environment),
IonicModule,
TranslateModule
TranslateModule,
ResizableModule
],
declarations: [
ResizableColumnDirective,
......@@ -31,6 +31,7 @@ import {MatFormFieldModule} from "@angular/material/form-field";
SharedModule,
IonicModule,
TranslateModule,
ResizableModule,
ResizableColumnDirective,
ResizableTableDirective,
......
......@@ -6,8 +6,6 @@ import {IonicModule} from "@ionic/angular";
import {TranslateModule} from "@ngx-translate/core";
import {ReferentialModule} from "../referential/referential.module";
import {QuadrigeSharedModule} from "../shared/quadrige.shared.module";
import {ResizableTableTestPage} from "@app/referential/testing/resizable.table.test";
import {ResizableModule} from "angular-resizable-element";
const routes: Routes = [
{
......@@ -26,15 +24,12 @@ const routes: Routes = [
TranslateModule.forChild(),
RouterModule.forChild(routes),
ReferentialModule,
ResizableModule
],
declarations: [
ReferentialTableTestPage,
ResizableTableTestPage,
],
exports: [
ReferentialTableTestPage,
ResizableTableTestPage,
]
})
......
......@@ -465,9 +465,8 @@ ion-list {
// Material Table
// --------------------------------------------------
.table-container {
//width: 550px;
max-width: 100%;
overflow: auto;
overflow-x: auto;
}
.mat-table {
......@@ -476,7 +475,7 @@ ion-list {
.mat-cell, .mat-header-cell, .mat-footer-cell {
padding: 0 10px;
min-width: 300px;
//min-width: 300px;
}
.mat-header-cell.disabled {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment