diff --git a/projects/demo-app/src/app/app.component.html b/projects/demo-app/src/app/app.component.html index 52d0f77a..b345abc9 100644 --- a/projects/demo-app/src/app/app.component.html +++ b/projects/demo-app/src/app/app.component.html @@ -38,6 +38,12 @@

hug/ngx-components Demo

Splitter + + + access_time + Timpe Picker + + diff --git a/projects/demo-app/src/app/app.routes.ts b/projects/demo-app/src/app/app.routes.ts index 9f7ce28f..82ffcdc5 100644 --- a/projects/demo-app/src/app/app.routes.ts +++ b/projects/demo-app/src/app/app.routes.ts @@ -7,5 +7,6 @@ export const appRoutes: Routes = [ { path: 'overlay', loadComponent: () => import('./overlay/overlay-demo.component').then(m => m.OverlayDemoComponent), data: { title: 'Overlay' } }, { path: 'snackbar', loadComponent: () => import('./snackbar/snackbar-demo.component').then(m => m.SnackbarDemoComponent), data: { title: 'Snackbar' } }, { path: 'splitter', loadComponent: () => import('./splitter/splitter-demo.component').then(m => m.SplitterDemoComponent), data: { title: 'Splitter' } }, + { path: 'time-picker', loadComponent: () => import('./time-picker/time-picker-demo.component').then(m => m.TimePickerDemoComponent), data: { title: 'Time Picker' } }, { path: '**', redirectTo: 'message-box', pathMatch: 'prefix' } ]; diff --git a/projects/demo-app/src/app/message-box/message-box-demo.component.ts b/projects/demo-app/src/app/message-box/message-box-demo.component.ts index 06458e37..f0ea203f 100644 --- a/projects/demo-app/src/app/message-box/message-box-demo.component.ts +++ b/projects/demo-app/src/app/message-box/message-box-demo.component.ts @@ -27,9 +27,9 @@ import { Subject, switchMap, takeUntil } from 'rxjs'; ] }) export class MessageBoxDemoComponent extends Destroy { - public tabIndex = 1; + protected tabIndex = 1; - public closeAction = [ + protected closeAction = [ { action: (): void => alert('test action'), icon: 'clear' diff --git a/projects/demo-app/src/app/numeric-stepper/numeric-stepper-demo.component.ts b/projects/demo-app/src/app/numeric-stepper/numeric-stepper-demo.component.ts index 923bfe30..842a50fc 100644 --- a/projects/demo-app/src/app/numeric-stepper/numeric-stepper-demo.component.ts +++ b/projects/demo-app/src/app/numeric-stepper/numeric-stepper-demo.component.ts @@ -8,7 +8,7 @@ import { MatTabsModule } from '@angular/material/tabs'; import { MatToolbarModule } from '@angular/material/toolbar'; import { Destroy } from '@hug/ngx-core'; import { NumericStepperComponent } from '@hug/ngx-numeric-stepper'; -import { debounceTime, distinctUntilChanged, map, Subject, takeUntil } from 'rxjs'; +import { Subject, debounceTime, distinctUntilChanged, map, takeUntil } from 'rxjs'; interface NumberFormControls { numberValue3: FormControl; @@ -47,19 +47,19 @@ const numberValidator = (control: AbstractControl): string[] | null => { ] }) export class NumericStepperDemoComponent extends Destroy { - public tabIndex = 1; + protected tabIndex = 1; - public value1 = 90; - public value2 = 9.5; - public value3 = 5; - public value4 = 1; - public value5 = 1; - public value6 = 1; - public value6min = 0; - public value6max = 20; + protected value1 = 90; + protected value2 = 9.5; + protected value3 = 5; + protected value4 = 1; + protected value5 = 1; + protected value6 = 1; + protected value6min = 0; + protected value6max = 20; - public numberForm: FormGroup; - public onInput1Change$ = new Subject(); + protected numberForm: FormGroup; + protected onInput1Change$ = new Subject(); private changeDetectorRef = inject(ChangeDetectorRef); private formBuilder = inject(FormBuilder); @@ -85,19 +85,19 @@ export class NumericStepperDemoComponent extends Destroy { }); } - public changeValue3(step: number): void { + protected changeValue3(step: number): void { this.numberForm.controls.numberValue3.setValue(+this.numberForm.controls.numberValue3.value + step); } - public changeValue4(step: number): void { + protected changeValue4(step: number): void { this.numberForm.controls.numberValue4.setValue(+this.numberForm.controls.numberValue4.value + step); } - public changeValue5(step: number): void { + protected changeValue5(step: number): void { this.numberForm.controls.numberValue5.setValue(+this.numberForm.controls.numberValue5.value + step); } - public changeValue6(step: number): void { + protected changeValue6(step: number): void { const value = Math.max(Math.min(+this.numberForm.controls.numberValue6.value + step, this.value6max), this.value6min); this.numberForm.controls.numberValue6.setValue(value); } diff --git a/projects/demo-app/src/app/overlay/overlay-demo.component.ts b/projects/demo-app/src/app/overlay/overlay-demo.component.ts index 8506dc0e..a0f135dc 100644 --- a/projects/demo-app/src/app/overlay/overlay-demo.component.ts +++ b/projects/demo-app/src/app/overlay/overlay-demo.component.ts @@ -31,21 +31,21 @@ export class OverlayDemoComponent { @ViewChild('contextMenu') private contextMenu?: OverlayComponent; - public selected = ''; - public items = [ + protected selected = ''; + protected items = [ { text: 'Refresh' }, { text: 'Settings' }, { text: 'Help', disabled: true }, { text: 'Sign Out' } ]; - public tabIndex = 1; + protected tabIndex = 1; - public select(text: string): void { + protected select(text: string): void { this.selected = text; } - public onContextMenu(event: MouseEvent): boolean { + protected onContextMenu(event: MouseEvent): boolean { const parent = event.currentTarget as HTMLElement; const parentRect = parent.getBoundingClientRect(); this.contextMenu?.show(event.pageX - parentRect.left, event.pageY - parentRect.top); diff --git a/projects/demo-app/src/app/snackbar/snackbar-demo.component.ts b/projects/demo-app/src/app/snackbar/snackbar-demo.component.ts index 6f1335d8..94270b0e 100644 --- a/projects/demo-app/src/app/snackbar/snackbar-demo.component.ts +++ b/projects/demo-app/src/app/snackbar/snackbar-demo.component.ts @@ -8,7 +8,7 @@ import { MatToolbarModule } from '@angular/material/toolbar'; import { MessageBoxComponent } from '@hug/ngx-message-box'; import { SnackbarComponent } from '@hug/ngx-snackbar'; import { StatusService, StatusType } from '@hug/ngx-status'; -import { defaultIfEmpty, filter, from, interval, map, Observable, scan, shareReplay } from 'rxjs'; +import { Observable, defaultIfEmpty, filter, from, interval, map, scan, shareReplay } from 'rxjs'; class Message { public constructor(public content = 'Some snackbar', public gate = true) { } @@ -34,21 +34,21 @@ class Message { ] }) export class SnackbarDemoComponent { - public tabIndex = 1; + protected tabIndex = 1; /* The example below demonstrate how you can dynamically add snackbars using *ngFor structural directive. Here the Observable simulate items being push from the server */ - public messages$: Observable; + protected messages$: Observable; - public dangers$: Observable; - public warnings$: Observable; - public successes$: Observable; - public infos$: Observable; + protected dangers$: Observable; + protected warnings$: Observable; + protected successes$: Observable; + protected infos$: Observable; - public push = new EventEmitter(); + protected push = new EventEmitter(); - public simpleGate = false; + protected simpleGate = false; private statusService = inject(StatusService); diff --git a/projects/demo-app/src/app/time-picker/time-picker-demo.component.html b/projects/demo-app/src/app/time-picker/time-picker-demo.component.html new file mode 100644 index 00000000..cc5c720d --- /dev/null +++ b/projects/demo-app/src/app/time-picker/time-picker-demo.component.html @@ -0,0 +1,101 @@ + + + + + + + + + +
+ + Basic Time Picker with ngModel and ngModelChange event + +
+
+

Without initial hours and minutes (null)

+
+ +
+

Selected : {{ date0 | date: 'HH:mm' }}

+
+
+

With initial hours and minutes (09:05)

+
+ +
+

Selected : {{ date1 | date: 'HH:mm' }}

+
+
+
+
+ + Time Picker modes + +
+
+

With hours disabled

+
+ +
+

Selected date : {{ date2 | date: 'HH:mm' }}

+
+
+

With minutes disabled

+
+ +
+

Selected date : {{ date3 | date: 'HH:mm' }}

+
+
+

With hours displayed only

+
+ +
+

Selected date : {{ date4 | date: 'HH:mm' }}

+
+
+

With minutes displayed only inline in a form

+
+ + + + +
+

Selected date : {{ date5 | date: 'HH:mm' }}

+
+
+
+
+ + Time Picker disable + +
+
+

Time Picker disabled

+
+ +
+

+ Disable time-picker +

+

Selected date : {{ date6 | date: 'HH:mm' }}

+
+
+
+
+ + Time Picker form control + +
+
+

Time Picker form control

+
+ +
+

Selected date : {{ dateForm.controls.date7.value | date: 'HH:mm' }}

+
+
+
+
+
diff --git a/projects/demo-app/src/app/time-picker/time-picker-demo.component.scss b/projects/demo-app/src/app/time-picker/time-picker-demo.component.scss new file mode 100644 index 00000000..341baf4f --- /dev/null +++ b/projects/demo-app/src/app/time-picker/time-picker-demo.component.scss @@ -0,0 +1,42 @@ +app-time-picker-demo { + .flex-layout { + display: flex; + flex-direction: row; + justify-content: space-between; + + > div, + > form { + flex: 1 1 auto; + } + } + + .flex-layout-center { + display: flex; + align-items: center; + } + + .time-picker-actions { + height: 100%; + display: flex; + flex-direction: column; + align-items: center; + justify-content: space-evenly; + } + + /* Override Material datepicker style */ + .mat-calendar-body-cell-content.mat-focus-indicator { + position: absolute !important; + } + + .mat-datepicker-content-container { + flex-direction: row !important; + } + + .mat-datepicker-actions { + margin-left: 64px !important; + } + + time-picker[inform] { + padding-right: 1rem; + } +} diff --git a/projects/demo-app/src/app/time-picker/time-picker-demo.component.ts b/projects/demo-app/src/app/time-picker/time-picker-demo.component.ts new file mode 100644 index 00000000..8601c2f1 --- /dev/null +++ b/projects/demo-app/src/app/time-picker/time-picker-demo.component.ts @@ -0,0 +1,136 @@ +/* + * @license + * Copyright Hôpitaux Universitaires de Genève. All Rights Reserved. + * + * Use of this source code is governed by an Apache-2.0 license that can be + * found in the LICENSE file at https://github.com/DSI-HUG/dejajs-components/blob/master/LICENSE + */ + +import { DatePipe, NgIf } from '@angular/common'; +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ViewEncapsulation } from '@angular/core'; +import { FormControl, FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { MatCardModule } from '@angular/material/card'; +import { MatCheckboxModule } from '@angular/material/checkbox'; +import { MAT_DATE_FORMATS } from '@angular/material/core'; +import { MatDatepickerInputEvent } from '@angular/material/datepicker'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatInputModule } from '@angular/material/input'; +import { MatTabsModule } from '@angular/material/tabs'; +import { MatToolbarModule } from '@angular/material/toolbar'; +import { TimePickerComponent } from '@hug/ngx-time-picker'; + +export const myFormats = { + parse: { + dateInput: 'DD/MM/YYYY HH:mm' + }, + display: { + dateInput: 'DD/MM/YYYY HH:mm', + monthYearLabel: 'MMM YYYY', + dateA11yLabel: 'DD/MM/YYYY HH:mm', + monthYearA11yLabel: 'MMMM YYYY' + } +}; + +interface DateFormControl { + date7: FormControl; +} + +@Component({ + changeDetection: ChangeDetectionStrategy.OnPush, + selector: 'app-time-picker-demo', + styleUrls: ['./time-picker-demo.component.scss'], + templateUrl: './time-picker-demo.component.html', + encapsulation: ViewEncapsulation.None, + standalone: true, + imports: [ + DatePipe, + FormsModule, + MatCardModule, + MatCheckboxModule, + MatInputModule, + MatFormFieldModule, + MatTabsModule, + MatToolbarModule, + ReactiveFormsModule, + TimePickerComponent, + NgIf + ], + providers: [ + { provide: MAT_DATE_FORMATS, useValue: myFormats } + ] +}) +export class TimePickerDemoComponent { + protected tabIndex = 1; + + protected date0: Date | null = null; + protected date1 = new Date(2021, 4, 6, 9, 5, 0); + protected date2 = new Date(); + protected date3 = new Date(); + protected date4 = new Date(); + protected date5 = new Date(); + protected date6 = new Date(); + protected date7 = new Date(2021, 4, 28, 12, 55, 0); + protected disable6 = true; + protected dateForm: FormGroup; + protected fakeInput = ''; + + public constructor(private changeDetectorRef: ChangeDetectorRef) { + this.dateForm = new FormGroup({ + date7: new FormControl(this.date7, { nonNullable: true }) + }); + } + + protected matDateChange(event: MatDatepickerInputEvent): void { + const date = event.value; + if (!date || !this.date0) { + return; + } + const clone = new Date(date); + clone.setHours(this.date0.getHours()); + clone.setMinutes(this.date0.getMinutes()); + this.date0 = clone; + this.changeDetectorRef.markForCheck(); + } + + protected date0Changed(date: Date): void { + const clone = date && new Date(date.getTime()); + this.date0 = clone; + this.changeDetectorRef.markForCheck(); + } + + protected date1Changed(date: Date): void { + const clone = date && new Date(date.getTime()); + this.date1 = clone; + this.changeDetectorRef.markForCheck(); + } + + protected date2Changed(date: Date): void { + const clone = date && new Date(date.getTime()); + this.date2 = clone; + this.changeDetectorRef.markForCheck(); + } + + protected date3Changed(date: Date): void { + const clone = date && new Date(date.getTime()); + this.date3 = clone; + this.changeDetectorRef.markForCheck(); + } + + protected date4Changed(date: Date): void { + const clone = date && new Date(date.getTime()); + this.date4 = clone; + this.changeDetectorRef.markForCheck(); + } + + protected date5Changed(date: Date): void { + const clone = date && new Date(date.getTime()); + this.date5 = clone; + this.changeDetectorRef.markForCheck(); + } + + protected date6Changed(date: Date): void { + const clone = date && new Date(date.getTime()); + this.date6 = clone; + this.changeDetectorRef.markForCheck(); + } +}