Skip to content

Commit abd4d00

Browse files
committed
feat(edit-content): add system timezone support to calendar field component
This commit introduces a new interface and integrates timezone handling into the . Key changes include: - Added property to the interface. - Updated the calendar field component to display the system timezone label when applicable. - Enhanced the calendar field's HTML and TypeScript to support timezone adjustments for date inputs. - Refactored related utility functions to accommodate timezone logic. These updates improve the user experience by ensuring accurate date and time representation based on the configured system timezone.
1 parent 387fb27 commit abd4d00

File tree

12 files changed

+290
-31
lines changed

12 files changed

+290
-31
lines changed

core-web/.cursor/rules/nx-rules.mdc

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
---
2+
description:
3+
globs:
4+
alwaysApply: true
5+
---
6+
7+
// This file is automatically generated by Nx Console
8+
9+
You are in an nx workspace using Nx 19.6.5 and yarn as the package manager.
10+
11+
You have access to the Nx MCP server and the tools it provides. Use them. Follow these guidelines in order to best help the user:
12+
13+
# General Guidelines
14+
- When answering questions, use the nx_workspace tool first to gain an understanding of the workspace architecture
15+
- For questions around nx configuration, best practices or if you're unsure, use the nx_docs tool to get relevant, up-to-date docs!! Always use this instead of assuming things about nx configuration
16+
- If the user needs help with an Nx configuration or project graph error, use the 'nx_workspace' tool to get any errors
17+
- To help answer questions about the workspace structure or simply help with demonstrating how tasks depend on each other, use the 'nx_visualize_graph' tool
18+
19+
# Generation Guidelines
20+
If the user wants to generate something, use the following flow:
21+
22+
- learn about the nx workspace and any specifics the user needs by using the 'nx_workspace' tool and the 'nx_project_details' tool if applicable
23+
- get the available generators using the 'nx_generators' tool
24+
- decide which generator to use. If no generators seem relevant, check the 'nx_available_plugins' tool to see if the user could install a plugin to help them
25+
- get generator details using the 'nx_generator_schema' tool
26+
- you may use the 'nx_docs' tool to learn more about a specific generator or technology if you're unsure
27+
- decide which options to provide in order to best complete the user's request. Don't make any assumptions and keep the options minimalistic
28+
- open the generator UI using the 'nx_open_generate_ui' tool
29+
- wait for the user to finish the generator
30+
- read the generator log file using the 'nx_read_generator_log' tool
31+
- use the information provided in the log file to answer the user's question or continue with what they were doing
32+
33+
34+

core-web/libs/dotcms-js/src/lib/core/dotcms-config.service.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ export interface DotUiColors {
2727
background: string;
2828
}
2929

30+
export interface SystemTimezone {
31+
id: string;
32+
label: string;
33+
offset: string;
34+
}
35+
3036
export interface ConfigParams {
3137
colors: DotUiColors;
3238
emailRegex: string;
@@ -48,6 +54,7 @@ export interface ConfigParams {
4854
version: string;
4955
};
5056
websocket: WebSocketConfigParams;
57+
systemTimezone: SystemTimezone;
5158
}
5259

5360
export interface WebSocketConfigParams {
@@ -61,7 +68,9 @@ export interface DotTimeZone {
6168
offset: string;
6269
}
6370

64-
@Injectable()
71+
@Injectable({
72+
providedIn: 'root'
73+
})
6574
export class DotcmsConfigService {
6675
private configParamsSubject: BehaviorSubject<ConfigParams> = new BehaviorSubject(null);
6776
private configUrl: string;
@@ -112,7 +121,8 @@ export class DotcmsConfigService {
112121
websocketReconnectTime:
113122
res.config.websocket[DOTCMS_WEBSOCKET_RECONNECT_TIME],
114123
disabledWebsockets: res.config.websocket[DOTCMS_DISABLE_WEBSOCKET_PROTOCOL]
115-
}
124+
},
125+
systemTimezone: res.config.systemTimezone
116126
};
117127

118128
this.configParamsSubject.next(configParams);

core-web/libs/edit-content/src/lib/components/dot-edit-content-field/dot-edit-content-field.component.html

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ <h3 class="m-0 text-gray-700">{{ field.name }}</h3>
7272
@defer (on immediate) {
7373
<ng-container [ngTemplateOutlet]="labelTemplate" />
7474
<dot-edit-content-calendar-field
75+
[utcTimezone]="$systemTimezone()"
7576
[field]="field"
7677
[attr.data-testId]="'field-' + field.variable" />
7778
}
@@ -184,6 +185,10 @@ <h3 class="m-0 text-gray-700">{{ field.name }}</h3>
184185
}
185186
}
186187
}
187-
@if (field.hint && field.fieldType !== fieldTypes.RELATIONSHIP) {
188+
@if (
189+
field.hint &&
190+
field.fieldType !== fieldTypes.RELATIONSHIP &&
191+
!calendarTypes.includes(field.fieldType)
192+
) {
188193
<small [attr.data-testId]="'hint-' + field.variable">{{ field.hint }}</small>
189194
}

core-web/libs/edit-content/src/lib/components/dot-edit-content-field/dot-edit-content-field.component.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@ import {
77
inject,
88
input
99
} from '@angular/core';
10+
import { toSignal } from '@angular/core/rxjs-interop';
1011
import { ControlContainer, ReactiveFormsModule } from '@angular/forms';
1112

1213
import { DividerModule } from 'primeng/divider';
1314

1415
import { BlockEditorModule } from '@dotcms/block-editor';
16+
import { DotcmsConfigService } from '@dotcms/dotcms-js';
1517
import { DotCMSContentlet, DotCMSContentTypeField } from '@dotcms/dotcms-models';
1618
import { DotEditContentBinaryFieldComponent } from '@dotcms/edit-content/fields/dot-edit-content-binary-field/dot-edit-content-binary-field.component';
1719
import { DotEditContentCalendarFieldComponent } from '@dotcms/edit-content/fields/dot-edit-content-calendar-field/dot-edit-content-calendar-field.component';
@@ -71,9 +73,13 @@ import { FIELD_TYPES } from '../../models/dot-edit-content-field.enum';
7173
DotEditContentRelationshipFieldComponent,
7274
DividerModule,
7375
NgTemplateOutlet
74-
]
76+
],
77+
providers: [DotcmsConfigService]
7578
})
7679
export class DotEditContentFieldComponent {
80+
readonly #dotcmsConfigService = inject(DotcmsConfigService);
81+
#globalSystemConfig = toSignal(this.#dotcmsConfigService.getConfig());
82+
7783
@HostBinding('class') class = 'field';
7884

7985
/**
@@ -91,7 +97,19 @@ export class DotEditContentFieldComponent {
9197
*/
9298
$contentType = input<string>(null, { alias: 'contentType' });
9399

100+
/**
101+
* The system timezone.
102+
*/
103+
$systemTimezone = computed(() => this.#globalSystemConfig()?.systemTimezone);
104+
105+
/**
106+
* The field types.
107+
*/
94108
readonly fieldTypes = FIELD_TYPES;
109+
110+
/**
111+
* The calendar types.
112+
*/
95113
readonly calendarTypes = CALENDAR_FIELD_TYPES as string[];
96114

97115
/**

core-web/libs/edit-content/src/lib/components/dot-edit-content-form/dot-edit-content-form.component.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010
OnInit,
1111
output
1212
} from '@angular/core';
13-
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
13+
import { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';
1414
import {
1515
FormBuilder,
1616
FormGroup,
@@ -33,6 +33,7 @@ import {
3333
DotWizardService,
3434
DotWorkflowEventHandlerService
3535
} from '@dotcms/data-access';
36+
import { DotcmsConfigService } from '@dotcms/dotcms-js';
3637
import {
3738
DotCMSContentlet,
3839
DotCMSContentTypeField,
@@ -118,6 +119,9 @@ export class DotEditContentFormComponent implements OnInit {
118119
readonly #dotWorkflowEventHandlerService = inject(DotWorkflowEventHandlerService);
119120
readonly #dotWizardService = inject(DotWizardService);
120121
readonly #dotMessageService = inject(DotMessageService);
122+
readonly #dotcmsConfigService = inject(DotcmsConfigService);
123+
#globalSystemConfig = toSignal(this.#dotcmsConfigService.getConfig());
124+
121125
/**
122126
* Output event emitter that informs when the form has changed.
123127
* Emits an object of type Record<string, string> containing the updated form values.
@@ -173,6 +177,11 @@ export class DotEditContentFormComponent implements OnInit {
173177
*/
174178
$tabs = this.$store.tabs;
175179

180+
/**
181+
* The system timezone.
182+
*/
183+
$systemTimezone = computed(() => this.#globalSystemConfig()?.systemTimezone);
184+
176185
ngOnInit(): void {
177186
if (this.$store.tabs().length) {
178187
this.initializeForm();
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,43 @@
1-
<p-calendar
2-
[formControlName]="field.variable"
3-
[timeOnly]="calendarOptions[field.fieldType].timeOnly"
4-
[showTime]="calendarOptions[field.fieldType].showTime"
5-
[id]="'calendar-id-' + field.variable"
6-
[inputId]="field.variable"
7-
[attr.data-testId]="field.variable"
8-
[showIcon]="true"
9-
[icon]="calendarOptions[field.fieldType].icon" />
1+
@let field = $field();
2+
@let fieldTypeConfig = $fieldTypeConfig();
3+
@let systemTimezone = $systemTimezone();
4+
@let defaultDate = $defaultDate();
5+
@let showHints = systemTimezone || $showSystemTimezoneLabel();
6+
7+
<div class="calendar-field">
8+
<p-calendar
9+
class="calendar-field__input"
10+
[formControlName]="field.variable"
11+
[timeOnly]="fieldTypeConfig.timeOnly"
12+
[showTime]="fieldTypeConfig.showTime"
13+
[id]="'calendar-id-' + field.variable"
14+
[inputId]="field.variable"
15+
[attr.data-testId]="field.variable"
16+
[showIcon]="true"
17+
[icon]="fieldTypeConfig.icon"
18+
[showButtonBar]="true"
19+
[dataType]="'string'"
20+
[defaultDate]="defaultDate"
21+
[attr.aria-label]="field.name"
22+
[attr.aria-describedby]="field.hint ? 'hint-' + field.variable : null" />
23+
24+
@if (showHints) {
25+
<div class="calendar-field__hints flex" data-testId="hint-container">
26+
<div class="flex-grow-1">
27+
@if (field.hint) {
28+
<small
29+
id="hint-{{ field.variable }}"
30+
class="calendar-field__hint"
31+
[attr.data-testId]="'hint-' + field.variable">
32+
{{ field.hint }}
33+
</small>
34+
}
35+
</div>
36+
@if (systemTimezone && $showSystemTimezoneLabel()) {
37+
<small class="calendar-field__timezone" data-testId="hint-timezone-label">
38+
{{ systemTimezone.label }}
39+
</small>
40+
}
41+
</div>
42+
}
43+
</div>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
@use "variables" as *;
2+
3+
.calendar-field {
4+
display: flex;
5+
flex-direction: column;
6+
gap: $spacing-0;
7+
}

0 commit comments

Comments
 (0)