Skip to content

Commit fe3a8e3

Browse files
authored
Date picker update (#163)
* Replace ngxMatDatetimePicker with MatDatepicker and MatTimepicker * data binding * update translation
1 parent 46fc55d commit fe3a8e3

File tree

15 files changed

+666
-244
lines changed

15 files changed

+666
-244
lines changed

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
},
1616
"private": true,
1717
"dependencies": {
18-
"@angular-material-components/datetime-picker": "^16.0.1",
1918
"@angular/animations": "19.2.4",
2019
"@angular/cdk": "19.2.7",
2120
"@angular/common": "19.2.4",

src/app/pages/editor/editor.css

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,8 @@ h1 {
4646
min-height: 88px;
4747
padding: 1em;
4848
}
49+
50+
.footer {
51+
display: flex;
52+
justify-content: space-between;
53+
}

src/app/pages/editor/editor.html

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<!-- <h1>Write your thoughts</h1> -->
33

44
<div class="note-type">
5-
<mat-button-toggle-group name="fontStyle" (change)="noteTypeChanged()" [(ngModel)]="eventType" aria-label="Font Style" #group="matButtonToggleGroup">
5+
<mat-button-toggle-group name="fontStyle" (change)="noteTypeChanged()" [formControl]="eventType" aria-label="Font Style" #group="matButtonToggleGroup">
66
<mat-button-toggle value="text">Note</mat-button-toggle>
77
<mat-button-toggle value="article">Article</mat-button-toggle>
88
</mat-button-toggle-group>
@@ -30,12 +30,12 @@
3030

3131
<mat-form-field class="input-full-width">
3232
<mat-label>Long form text that supports markdown formatting</mat-label>
33-
<textarea #articleContent appAutoInputHeight class="note-input" matInput type="text" [(ngModel)]="note" formControlName="content" rows="2"></textarea>
33+
<textarea #articleContent appAutoInputHeight class="note-input" matInput type="text" formControlName="content" rows="2"></textarea>
3434
</mat-form-field>
3535

3636
<mat-form-field class="input-full-width">
3737
<mat-label>Summary (optional)</mat-label>
38-
<textarea class="note-input" appAutoInputHeight matInput type="text" [(ngModel)]="summary" formControlName="summary" rows="2"></textarea>
38+
<textarea class="note-input" appAutoInputHeight matInput type="text" formControlName="summary" rows="2"></textarea>
3939
</mat-form-field>
4040

4141
<mat-form-field class="input-full-width">
@@ -50,19 +50,19 @@
5050

5151
<input type="hidden" formControlName="published_at" />
5252

53-
<emoji-mart class="picker" *ngIf="isEmojiPickerVisible" emoji="point_up" [isNative]="true" [showPreview]="false" (emojiSelect)="addEmojiArticle($event)" title="Choose your emoji"></emoji-mart>
54-
<mat-icon class="toolbar-icon margin-right" (click)="isEmojiPickerVisible = !isEmojiPickerVisible;" matTooltip="Insert emoji">sentiment_satisfied</mat-icon>
55-
<!-- <mat-icon class="toolbar-icon margin-right" matTooltip="Upload file">attach_file</mat-icon> -->
56-
57-
<!-- <mat-form-field>
58-
<input matInput [ngxMatDatetimePicker]="picker" placeholder="Choose a timeout" [formControl]="dateControl" [min]="minDate" />
59-
<mat-datepicker-toggle matSuffix [for]="$any(picker)"></mat-datepicker-toggle>
60-
<ngx-mat-datetime-picker #picker [showSpinners]="true" [showSeconds]="false" [stepHour]="1" [stepMinute]="1" [stepSecond]="1" [touchUi]="false" [enableMeridian]="false" [disableMinute]="false" [hideTime]="false">
61-
<ng-template>
62-
<span>Set timeout</span>
63-
</ng-template>
64-
</ngx-mat-datetime-picker>
65-
</mat-form-field> -->
53+
<div class="footer">
54+
<emoji-mart class="picker" *ngIf="isEmojiPickerVisible" emoji="point_up" [isNative]="true" [showPreview]="false" (emojiSelect)="addEmojiArticle($event)" title="Choose your emoji"></emoji-mart>
55+
<mat-icon class="toolbar-icon margin-right" (click)="isEmojiPickerVisible = !isEmojiPickerVisible;" matTooltip="Insert emoji">sentiment_satisfied</mat-icon>
56+
<!-- <mat-icon class="toolbar-icon margin-right" matTooltip="Upload file">attach_file</mat-icon> -->
57+
<app-date-time
58+
(dateTimeChanged)="handleArticleDateTimeChange($event)"
59+
[initialDateTime]="ArticleDateTimeValue"
60+
[minDate]="minArticleDateValue"
61+
[CustomLabel]="ArticleLabel | translate"
62+
[CustomDateLabel]="DateLabel | translate"
63+
[CustomTimeLabel]="TimeLabel | translate"
64+
></app-date-time>
65+
</div>
6666
</div>
6767
<div mat-dialog-actions class="mat-dialog-actions" align="end">
6868
<button mat-button type="button" (click)="onCancel()">Cancel</button>&nbsp;
@@ -78,6 +78,8 @@
7878
<textarea appContentEditor appAutoInputHeight #noteContent class="note-input noscrollbars" matInput type="text" formControlName="content" rows="2" [mention]="followingUsers"></textarea>
7979
</mat-form-field>
8080

81+
<input type="hidden" formControlName="expiration" />
82+
8183
<!-- <mat-autocomplete #auto="matAutocomplete">
8284
<mat-option *ngFor="let profile of profileService.following$ | async" [value]="profile.pubkey">
8385
<div class="autocomplete-option">
@@ -90,27 +92,25 @@
9092

9193
<!-- <div appContentEditor autocomplete="off" contenteditable="true" class="form-control" class="text-editor"></div>
9294
<div [mention]="profileService.following" [mentionConfig]="{labelKey:'name'}" autocomplete="off" contenteditable="true" class="form-control" class="text-editor"></div> -->
93-
94-
<emoji-mart class="picker" *ngIf="isEmojiPickerVisible" emoji="point_up" [isNative]="true" [showPreview]="false" (emojiSelect)="addEmojiNote($event)" title="Choose your emoji"></emoji-mart>
95-
<mat-icon class="toolbar-icon margin-right" (click)="isEmojiPickerVisible = !isEmojiPickerVisible;" matTooltip="Insert emoji">sentiment_satisfied</mat-icon>
96-
<!-- <mat-icon class="toolbar-icon margin-right" matTooltip="Upload file">attach_file</mat-icon> -->
97-
98-
<!-- <mat-form-field>
99-
<input matInput [ngxMatDatetimePicker]="picker" placeholder="Choose a timeout" [formControl]="dateControl" [min]="minDate" />
100-
<mat-datepicker-toggle matSuffix [for]="$any(picker)"></mat-datepicker-toggle>
101-
<ngx-mat-datetime-picker #picker [showSpinners]="true" [showSeconds]="false" [stepHour]="1" [stepMinute]="1" [stepSecond]="1" [touchUi]="false" [enableMeridian]="false" [disableMinute]="false" [hideTime]="false">
102-
<ng-template>
103-
<span>Set timeout</span>
104-
</ng-template>
105-
</ngx-mat-datetime-picker>
106-
</mat-form-field> -->
95+
<div class="footer">
96+
<emoji-mart class="picker" *ngIf="isEmojiPickerVisible" emoji="point_up" [isNative]="true" [showPreview]="false" (emojiSelect)="addEmojiNote($event)" title="Choose your emoji"></emoji-mart>
97+
<mat-icon class="toolbar-icon margin-right" (click)="isEmojiPickerVisible = !isEmojiPickerVisible;" matTooltip="Insert emoji">sentiment_satisfied</mat-icon>
98+
<!-- <mat-icon class="toolbar-icon margin-right" matTooltip="Upload file">attach_file</mat-icon> -->
99+
<app-date-time
100+
(dateTimeChanged)="handleNoteDateTimeChange($event)"
101+
[initialDateTime]="NoteDateTimeValue"
102+
[minDate]="minNoteDateValue"
103+
[CustomLabel]="NoteLabel | translate"
104+
[CustomDateLabel]="DateLabel | translate"
105+
[CustomTimeLabel]="TimeLabel | translate"
106+
></app-date-time>
107+
</div>
107108
</div>
108109
<div mat-dialog-actions class="mat-dialog-actions" align="end">
109110
<button mat-button type="button" (click)="onCancel()">Cancel</button>&nbsp;
110111
<!-- <button mat-stroked-button type="button" disabled="disabled">Save Draft</button>&nbsp; -->
111112
<button mat-flat-button [disabled]="!noteForm.valid" type="submit">Publish Note</button>
112113
</div>
113-
114114
</form>
115115

116116
<div *ngIf="event">

src/app/pages/editor/editor.ts

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1-
import { Component, ViewChild } from '@angular/core';
2-
import { FormBuilder, FormControl, FormsModule, UntypedFormGroup, Validators } from '@angular/forms';
1+
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ViewChild } from '@angular/core';
2+
import { FormBuilder, FormControl, FormsModule, Validators } from '@angular/forms';
33
import { NavigationService } from '../../services/navigation';
44
import { Location, CommonModule } from '@angular/common';
55
import { ApplicationState } from '../../services/applicationstate';
66
import { BlogEvent, NostrEvent } from '../../services/interfaces';
7-
import { Event, kinds } from 'nostr-tools';
7+
import { kinds } from 'nostr-tools';
88
import { Subscription } from 'rxjs';
99
import { now, Utilities } from '../../services/utilities';
10+
import { TranslateModule } from '@ngx-translate/core';
1011
import { QueueService } from '../../services/queue.service';
1112
import { ArticleService } from '../../services/article';
1213
import { MatSnackBar, MatSnackBarModule } from '@angular/material/snack-bar';
@@ -23,6 +24,7 @@ import { ContentEditorDirective } from '../../shared/content-input-directive/con
2324
import { MentionModule } from 'angular-mentions';
2425
import { MatInputModule } from '@angular/material/input';
2526
import { MatButtonModule } from '@angular/material/button';
27+
import { DateTimeComponent } from "../../shared/date-time/date-time.component";
2628

2729
export interface NoteDialogData {
2830
note: string;
@@ -32,23 +34,39 @@ export interface NoteDialogData {
3234
selector: 'app-editor',
3335
standalone: true,
3436
imports: [
37+
TranslateModule,
3538
MentionModule,
3639
MatButtonModule,
37-
CommonModule, MatSnackBarModule, PickerModule, EventComponent, ContentEditorDirective, ReactiveFormsModule, FormsModule, MatButtonToggleModule, MatFormFieldModule, MatInputModule, MatSelectModule, MatIconModule],
40+
CommonModule, MatSnackBarModule, PickerModule, EventComponent, ContentEditorDirective, ReactiveFormsModule, FormsModule, MatButtonToggleModule, MatFormFieldModule, MatInputModule, MatSelectModule, MatIconModule,
41+
DateTimeComponent
42+
],
3843
templateUrl: 'editor.html',
3944
styleUrls: ['editor.css'],
45+
changeDetection: ChangeDetectionStrategy.OnPush,
4046
})
4147
export class EditorComponent {
42-
@ViewChild('picker') picker: unknown;
4348
@ViewChild('noteContent') noteContent?: FormControl;
4449
@ViewChild('articleContent') articleContent?: FormControl;
4550

46-
isEmojiPickerVisible: boolean | undefined;
51+
eventType = new FormControl('text');
52+
53+
isEmojiPickerVisible: boolean = false;
54+
isArticleEmojiPickerVisible: boolean = false;
55+
56+
ArticleDateTimeValue: Date = new Date();
57+
NoteDateTimeValue: Date = new Date();
58+
59+
minNoteDateValue: Date = new Date();
60+
minArticleDateValue: Date = new Date();
61+
62+
ArticleLabel: string = 'DateTimeComponent.Label.Article';
63+
NoteLabel: string = 'DateTimeComponent.Label.Note';
64+
DateLabel: string = 'DateTimeComponent.DateLabel';
65+
TimeLabel: string = 'DateTimeComponent.TimeLabel';
4766

4867
noteForm = this.fb.group({
4968
content: ['', Validators.required],
5069
expiration: [''],
51-
dateControl: [],
5270
});
5371

5472
articleForm = this.fb.group({
@@ -71,14 +89,10 @@ export class EditorComponent {
7189

7290
minDate?: number;
7391

74-
eventType: string = 'text';
75-
76-
public dateControl = new FormControl(null);
92+
followingUsers : string [] = this.profileService.following.map(follower => follower.name);
7793

7894
subscriptions: Subscription[] = [];
7995

80-
followingUsers : string [] = this.profileService.following.map(follower => follower.name);
81-
8296
constructor(
8397
private snackBar: MatSnackBar,
8498
public articleService: ArticleService,
@@ -89,7 +103,8 @@ export class EditorComponent {
89103
private fb: FormBuilder,
90104
public navigation: NavigationService,
91105
public profileService: ProfileService,
92-
private eventService: EventService
106+
private eventService: EventService,
107+
private cdr: ChangeDetectorRef
93108
) {}
94109

95110
ngOnInit() {
@@ -115,6 +130,16 @@ export class EditorComponent {
115130
);
116131
}
117132

133+
handleNoteDateTimeChange(dateTime: Date | null): void {
134+
this.noteForm.patchValue({ expiration: dateTime?.toDateString() });
135+
this.cdr.detectChanges();
136+
}
137+
138+
handleArticleDateTimeChange(dateTime: Date | null): void {
139+
this.articleForm.patchValue({ published_at: dateTime?.toDateString() });
140+
this.cdr.detectChanges();
141+
}
142+
118143
updateEvent(content: string | null) {
119144
if (!content) {
120145
this.event = undefined;
@@ -177,7 +202,7 @@ export class EditorComponent {
177202

178203
noteTypeChanged() {
179204
// Load all articles for the user when toggling.
180-
if (this.eventType == 'article') {
205+
if (this.eventType.value == 'article') {
181206
this.queueService.enque(this.appState.getPublicKey(), 'Article');
182207
}
183208
}

src/app/shared/create-note-dialog/create-note-dialog.html

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,9 @@ <h1 mat-dialog-title>Write Your Note</h1>
1111
<mat-label>Note</mat-label>
1212
<textarea class="note-input" matInput type="text" [(ngModel)]="data.note" formControlName="note" rows="6"></textarea>
1313
</mat-form-field>
14-
15-
<!-- <mat-form-field>
16-
<input matInput [ngxMatDatetimePicker]="picker" placeholder="Choose a timeout" [formControl]="dateControl" [min]="minDate" />
17-
<mat-datepicker-toggle matSuffix [for]="$any(picker)"></mat-datepicker-toggle>
18-
<ngx-mat-datetime-picker #picker [showSpinners]="true" [showSeconds]="false" [stepHour]="1" [stepMinute]="1" [stepSecond]="1" [touchUi]="false" [enableMeridian]="false" [disableMinute]="false" [hideTime]="false">
19-
<ng-template>
20-
<span>Set timeout</span>
21-
</ng-template>
22-
</ngx-mat-datetime-picker>
23-
</mat-form-field> -->
14+
<div class="footer">
15+
<app-date-time></app-date-time>
16+
</div>
2417
</div>
2518
<div mat-dialog-actions class="mat-dialog-actions" align="end">
2619
<mat-icon (click)="toggleSize()" class="hide-small maximize-button" matTooltip="Maximize the window">zoom_out_map</mat-icon>

src/app/shared/create-note-dialog/create-note-dialog.scss

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,8 @@
4040
position: fixed;
4141
z-index: 3;
4242
}
43+
44+
.footer {
45+
display: flex;
46+
justify-content: space-between;
47+
}

src/app/shared/create-note-dialog/create-note-dialog.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { MatFormFieldModule } from '@angular/material/form-field';
66
import { MatIconModule } from '@angular/material/icon';
77
import { MatInputModule } from '@angular/material/input';
88
import { PickerModule } from '@ctrl/ngx-emoji-mart';
9+
import { DateTimeComponent } from "../date-time/date-time.component";
910

1011
export interface NoteDialogData {
1112
note: string;
@@ -15,9 +16,9 @@ export interface NoteDialogData {
1516
selector: 'create-note-dialog',
1617
templateUrl: 'create-note-dialog.html',
1718
styleUrls: ['create-note-dialog.scss'],
18-
imports: [FormsModule,
19+
imports: [FormsModule,
1920
MatDialogModule,
20-
CommonModule, ReactiveFormsModule, MatIconModule, MatFormFieldModule, MatInputModule, PickerModule],
21+
CommonModule, ReactiveFormsModule, MatIconModule, MatFormFieldModule, MatInputModule, PickerModule, DateTimeComponent],
2122
})
2223
export class NoteDialog {
2324
@ViewChild('picker') picker: unknown;
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<mat-label>{{ CustomLabel }}</mat-label>
2+
3+
<form [formGroup]="dateTimeForm">
4+
<mat-form-field>
5+
<mat-label>{{ CustomDateLabel }}</mat-label>
6+
<input matInput [min]="minDate" [max]="maxDate" [matDatepicker]="datepicker" formControlName="dateControl" />
7+
<mat-hint>{{ CustomDateHint }}</mat-hint>
8+
<mat-datepicker-toggle matIconSuffix [for]="datepicker"></mat-datepicker-toggle>
9+
<mat-datepicker #datepicker></mat-datepicker>
10+
</mat-form-field>
11+
12+
<mat-form-field>
13+
<mat-label>{{ CustomTimeLabel }}</mat-label>
14+
<input matInput [matTimepicker]="timepicker" formControlName="timeControl" />
15+
<mat-hint>{{ CustomHoursHint }}</mat-hint>
16+
<mat-timepicker-toggle matIconSuffix [for]="timepicker"></mat-timepicker-toggle>
17+
<mat-timepicker #timepicker></mat-timepicker>
18+
</mat-form-field>
19+
</form>
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
:host, form {
2+
display: flex;
3+
align-items: baseline;
4+
justify-content: center;
5+
gap: 5px;
6+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { ComponentFixture, TestBed } from '@angular/core/testing';
2+
3+
import { DateTimeComponent } from './date-time.component';
4+
5+
describe('DateTimeComponent', () => {
6+
let component: DateTimeComponent;
7+
let fixture: ComponentFixture<DateTimeComponent>;
8+
9+
beforeEach(async () => {
10+
await TestBed.configureTestingModule({
11+
declarations: [ DateTimeComponent ]
12+
})
13+
.compileComponents();
14+
});
15+
16+
beforeEach(() => {
17+
fixture = TestBed.createComponent(DateTimeComponent);
18+
component = fixture.componentInstance;
19+
fixture.detectChanges();
20+
});
21+
22+
it('should create', () => {
23+
expect(component).toBeTruthy();
24+
});
25+
});

0 commit comments

Comments
 (0)