Add weekly layout to record calendar (#22819)
## Summary - Add a week layout to record calendar views and persist the selected layout. - Render `DATE` calendars as an all-day week and `DATE_TIME` calendars as an hourly week. - Add an optional end date field across calendar configuration, metadata, persistence, and complete-view upserts. - Use configured end values for ranged and multi-day events, with a one-hour fallback when a `DATE_TIME` end is absent or invalid. - Keep calendar cards consistent with the existing compact view, including checkbox selection and whole-card record opening. - Gate the weekly layout and end-date behavior behind the public Labs `IS_CALENDAR_WEEK_VIEW_ENABLED` workspace feature flag. ## Week interactions - Show overlapping timed events side by side and cap the visible records at two per day. - Display start and end times on timed cards, enforce a readable 30-minute minimum height, and keep today’s text contrast stronger. - Drag timed events between days and times with 30-minute snapping while preserving their duration, including zero-duration events. - Show a create button when hovering a 30-minute slot; keyboard users can focus a day, move the slot with the arrow keys, and reach the same contextual action. - Initialize new records with the selected slot time and a compatible writable end value one hour later. - Show the workspace time zone and current-time indicator in timed weeks; date-only weeks keep the all-day section without an hourly grid. ## Configuration and data loading - Only allow end fields that match the start field type, and prevent selecting the same field for both boundaries. - Load records whose ranges overlap the visible period so month and week layouts display the same relevant records. - Resolve and persist calendar end fields when updating existing views through `upsert_complete_view`. - Fall back to Month and ignore the configured end field while the flag is disabled, without overwriting either persisted setting, so re-enabling restores the previous configuration. - Expose the flag in Labs and keep it default-off for workspaces without a stored value; enable it in the development seeder. <img width="1285" height="808" alt="Screenshot 2026-07-15 at 15 50 17" src="https://github.com/user-attachments/assets/b7e3f7f1-ca77-492f-8cce-cca186ebca0b" />
This commit is contained in:
+5
@@ -114,6 +114,7 @@ describe('fromViewManifestToUniversalFlatView', () => {
|
||||
).toBeNull();
|
||||
expect(result.calendarLayout).toBeNull();
|
||||
expect(result.calendarFieldMetadataUniversalIdentifier).toBeNull();
|
||||
expect(result.calendarEndFieldMetadataUniversalIdentifier).toBeNull();
|
||||
expect(result.anyFieldFilterValue).toBeNull();
|
||||
});
|
||||
|
||||
@@ -126,6 +127,7 @@ describe('fromViewManifestToUniversalFlatView', () => {
|
||||
type: ViewType.CALENDAR,
|
||||
calendarLayout: ViewCalendarLayout.WEEK,
|
||||
calendarFieldMetadataUniversalIdentifier: 'field-uuid-date',
|
||||
calendarEndFieldMetadataUniversalIdentifier: 'field-uuid-end-date',
|
||||
},
|
||||
applicationUniversalIdentifier,
|
||||
now,
|
||||
@@ -135,6 +137,9 @@ describe('fromViewManifestToUniversalFlatView', () => {
|
||||
expect(result.calendarFieldMetadataUniversalIdentifier).toBe(
|
||||
'field-uuid-date',
|
||||
);
|
||||
expect(result.calendarEndFieldMetadataUniversalIdentifier).toBe(
|
||||
'field-uuid-end-date',
|
||||
);
|
||||
});
|
||||
|
||||
it('should preserve anyFieldFilterValue from the manifest', () => {
|
||||
|
||||
+1
@@ -112,6 +112,7 @@ export const fromFieldManifestToUniversalFlatFieldMetadata = ({
|
||||
fieldPermissionUniversalIdentifiers: [],
|
||||
kanbanAggregateOperationViewUniversalIdentifiers: [],
|
||||
calendarViewUniversalIdentifiers: [],
|
||||
calendarEndViewUniversalIdentifiers: [],
|
||||
mainGroupByFieldMetadataViewUniversalIdentifiers: [],
|
||||
viewSortUniversalIdentifiers: [],
|
||||
searchFieldMetadataUniversalIdentifiers: [],
|
||||
|
||||
+2
@@ -36,6 +36,8 @@ export const fromViewManifestToUniversalFlatView = ({
|
||||
calendarLayout: viewManifest.calendarLayout ?? null,
|
||||
calendarFieldMetadataUniversalIdentifier:
|
||||
viewManifest.calendarFieldMetadataUniversalIdentifier ?? null,
|
||||
calendarEndFieldMetadataUniversalIdentifier:
|
||||
viewManifest.calendarEndFieldMetadataUniversalIdentifier ?? null,
|
||||
mainGroupByFieldMetadataUniversalIdentifier:
|
||||
viewManifest.mainGroupByFieldMetadataUniversalIdentifier ?? null,
|
||||
shouldHideEmptyGroups: viewManifest.shouldHideEmptyGroups ?? false,
|
||||
|
||||
+8
@@ -12,6 +12,14 @@ export type PublicFeatureFlag = {
|
||||
};
|
||||
|
||||
export const PUBLIC_FEATURE_FLAGS: PublicFeatureFlag[] = [
|
||||
{
|
||||
key: FeatureFlagKey.IS_CALENDAR_WEEK_VIEW_ENABLED,
|
||||
metadata: {
|
||||
label: 'Calendar Week View',
|
||||
description:
|
||||
'Display calendar records in a weekly layout with optional end dates',
|
||||
},
|
||||
},
|
||||
{
|
||||
key: FeatureFlagKey.IS_JUNCTION_RELATIONS_ENABLED,
|
||||
metadata: {
|
||||
|
||||
Reference in New Issue
Block a user