Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
97 commits
Select commit Hold shift + click to select a range
a766a7b
Started the implementation of the new date time property editor
lauraneto Jul 17, 2025
110ea33
Display picked time in local and UTC
lauraneto Jul 22, 2025
a7871a2
Adjustments to the way the timezones are displayed and the picker is …
lauraneto Jul 23, 2025
8a93901
Filter out `Etc/` (offset) timezones from the list
lauraneto Jul 24, 2025
efc2063
Additional adjustments
lauraneto Jul 31, 2025
c57817e
Introduced date format and time zone options (all, local or custom)
lauraneto Aug 1, 2025
bc84109
Adjustments to the property editor configuration and value converter
lauraneto Aug 1, 2025
534e93c
Use UUICombobox instead of UUISelect for displaying time zone options…
lauraneto Aug 4, 2025
515d457
Allow searching by offset
lauraneto Aug 4, 2025
58d11b7
Ignore case when searching for time zone
lauraneto Aug 5, 2025
3706a2f
Store dates consistently (always same format)
lauraneto Aug 5, 2025
e5514fb
Add custom PropertyIndexValueFactory for the new property editor
lauraneto Aug 5, 2025
ffe554c
Adjustments when switching between time zone modes
lauraneto Aug 5, 2025
34e8fcd
Small fixes and cleanup
lauraneto Aug 6, 2025
3a505d7
Merge branch 'v17/dev' into v17/feature/new-datetime-with-timezone-pr…
lauraneto Aug 6, 2025
a3ed7a8
Started improving time zone config selection
lauraneto Aug 11, 2025
b870430
Merge branch 'v17/dev' into v17/feature/new-datetime-with-timezone-pr…
lauraneto Aug 11, 2025
7a60ca8
Small adjustments
lauraneto Aug 11, 2025
e34dae5
Remove selected time zones from the list + display label instead of v…
lauraneto Aug 11, 2025
225cb03
Localizing labels
lauraneto Aug 11, 2025
b20186d
Remove unwanted character
lauraneto Aug 11, 2025
598ac5c
Fix incorrect order of custom time zones list
lauraneto Aug 11, 2025
630e507
Small fixes (mostly validation)
lauraneto Aug 12, 2025
7eb3960
Rename input time zone component
lauraneto Aug 12, 2025
10ad08b
Small adjustments
lauraneto Aug 12, 2025
8f0f897
Using model for stored value
lauraneto Aug 12, 2025
26fb5ad
Save examine value as ISO format
lauraneto Aug 12, 2025
d6b4c6c
Adjusting class names for consistency
lauraneto Aug 12, 2025
03f250c
Small fixes
lauraneto Aug 12, 2025
916b2dc
Add default data type configuration
lauraneto Aug 12, 2025
b7d399a
Rename `TimeZone` to `UmbTimeZone`
lauraneto Aug 14, 2025
ad37544
Fix failing tests
lauraneto Aug 14, 2025
5d891db
Started adding unit tests for DateWithTimeZonePropertyEditor
lauraneto Aug 20, 2025
efa0b58
Additional tests
lauraneto Aug 20, 2025
d51243c
Additional tests
lauraneto Aug 20, 2025
5302867
Additional tests
lauraneto Aug 21, 2025
00bc2f2
Fixed searches with regex special characters throwing errors
lauraneto Aug 21, 2025
e900a36
Remove offset from generic UmbTimeZone type and added new type specif…
lauraneto Aug 21, 2025
1a68c1b
Adjust property editor to show error when selected time zone is no lo…
lauraneto Aug 21, 2025
a458efd
Do not preselect a time zone if a date is stored without time zone
lauraneto Aug 21, 2025
e2a7018
Fix failing backoffice build
lauraneto Aug 21, 2025
2390115
Added tests for DateTimeWithTimeZonePropertyIndexValueFactory
lauraneto Aug 21, 2025
6f85cc3
Improved picker validation
lauraneto Aug 22, 2025
2fce47d
Remove unused code
lauraneto Aug 22, 2025
e3eeffe
Move models to their corresponding places
lauraneto Aug 22, 2025
22dc6ca
Renaming `DateTimeWithTimeZone` to `DateTime2`
lauraneto Aug 26, 2025
f041223
Fix data type count tests
lauraneto Aug 26, 2025
36876a5
Simplifying code + adjusting value converter to support old picker value
lauraneto Aug 27, 2025
935977a
Merge branch 'v17/dev' into v17/feature/new-datetime-with-timezone-pr…
lauraneto Aug 27, 2025
7eabf4d
Adjustments to property editor unit tests
lauraneto Aug 27, 2025
4e6d33e
Fix validation issue
lauraneto Sep 1, 2025
25ece93
Fix default configuration for 'Date Time (Unspecified)'
lauraneto Sep 1, 2025
1f03cb0
Rename validator
lauraneto Sep 3, 2025
2d2d405
Fix comment
lauraneto Sep 3, 2025
e3d54f6
Adjust database creator default DateTime2 data types
lauraneto Sep 5, 2025
87b4575
Update tests after adjusting default data types
lauraneto Sep 5, 2025
cbed45a
Add integration test for DateTime2 returned value type
lauraneto Sep 5, 2025
b4759c9
Apply suggestions from code review
lauraneto Sep 5, 2025
f6800e9
Aligning DateTime2Validator with other JSON validators. Added new mod…
lauraneto Sep 5, 2025
1a597b1
Merge branch 'v17/dev' into v17/feature/new-datetime-with-timezone-pr…
lauraneto Sep 5, 2025
4747e0a
Removed unused code and updated tests
lauraneto Sep 5, 2025
29a5760
Fix validation error message
lauraneto Sep 5, 2025
9ce41e2
Apply suggestions from code review
lauraneto Sep 15, 2025
4df5f8c
Merge branch 'v17/dev' into v17/feature/new-datetime-with-timezone-pr…
lauraneto Sep 16, 2025
555df58
Splitting the new date time editor into multiple (per output type)
lauraneto Sep 17, 2025
1cae4c5
Adjust tests in DateTime2PropertyIndexValueFactoryTest
lauraneto Sep 18, 2025
0995313
Update value converter tests
lauraneto Sep 18, 2025
21abd8a
Group the new date time tests
lauraneto Sep 18, 2025
0dbeb69
Adjust new property editor tests
lauraneto Sep 18, 2025
e4eeb3d
Adjust property editor integration tests
lauraneto Sep 18, 2025
dd3570c
Update data editor count tests
lauraneto Sep 18, 2025
81919f3
Merge branch 'v17/dev' into v17/feature/new-datetime-with-timezone-pr…
lauraneto Sep 18, 2025
6c2f781
Naming adjustments
lauraneto Sep 18, 2025
5ad368c
Small fixes
lauraneto Sep 18, 2025
a6d64c8
Cleanup
lauraneto Sep 18, 2025
fdad0a9
Update luxon depedencies
lauraneto Sep 18, 2025
94b6195
Move GetValueFromSource to the value converter
lauraneto Sep 19, 2025
1335b2b
Add new property editor examples to mock data
lauraneto Sep 19, 2025
0fe0e31
Merge branch 'v17/dev' into v17/feature/new-datetime-with-timezone-pr…
nielslyngsoe Sep 21, 2025
6ddefa1
Re-organizing the code
lauraneto Sep 22, 2025
2b67904
Adjustments from code review
lauraneto Sep 22, 2025
92c116a
Place the date time property index value factories in their own files
lauraneto Sep 22, 2025
3e61cb6
Small adjustments for code consistency
lauraneto Sep 22, 2025
69f57bd
Merge branch 'v17/dev' into v17/feature/new-datetime-with-timezone-pr…
lauraneto Sep 22, 2025
5749053
Small adjustments
lauraneto Sep 22, 2025
4eb7c54
Minor adjustment
lauraneto Sep 22, 2025
8aac597
Small fix from copilot review
lauraneto Sep 22, 2025
d9f2834
Completed the set of XML header comments.
AndyButland Sep 23, 2025
a8717fb
use already existing query property
nielslyngsoe Sep 23, 2025
72d80d2
fail is form control element is null or undefined
nielslyngsoe Sep 23, 2025
337651d
Merge branch 'v17/dev' into v17/feature/new-datetime-with-timezone-pr…
nielslyngsoe Sep 23, 2025
43b4a0b
using lit ref for querying and form control registration
nielslyngsoe Sep 23, 2025
3d017f0
state for timeZonePickerValue and remove _disableAddButton
nielslyngsoe Sep 24, 2025
f28e742
Adjustments to form control registration
lauraneto Sep 24, 2025
eaf5f37
Remove unused declaration
lauraneto Sep 24, 2025
ad91a14
Merge branch 'v17/dev' into v17/feature/new-datetime-with-timezone-pr…
lauraneto Sep 25, 2025
61a29b2
Merge branch 'v17/dev' into v17/feature/new-datetime-with-timezone-pr…
lauraneto Sep 30, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/Umbraco.Core/Constants-DataTypes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,11 @@ public static class Guids
/// </summary>
public const string DatePickerWithTime = "e4d66c0f-b935-4200-81f0-025f7256b89a";

/// <summary>
/// Guid for Date Time Picker (with Timezone) as string
/// </summary>
public const string DateTimePickerWithTimeZone = "88E8A052-30EE-4D44-A507-59F2CDFC769C";

/// <summary>
/// Guid for Approved Color as string
/// </summary>
Expand Down Expand Up @@ -296,6 +301,11 @@ public static class Guids
/// </summary>
public static readonly Guid DatePickerWithTimeGuid = new(DatePickerWithTime);

/// <summary>
/// Guid for Date Time Picker (with Timezone).
/// </summary>
public static readonly Guid DateTimePickerWithTimeZoneGuid = new(DateTimePickerWithTimeZone);

/// <summary>
/// Guid for Approved Color
/// </summary>
Expand Down
20 changes: 20 additions & 0 deletions src/Umbraco.Core/Constants-PropertyEditors.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,26 @@ public static class Aliases
/// </summary>
public const string DateTime = "Umbraco.DateTime";

/// <summary>
/// Date Time (unspecified).
/// </summary>
public const string DateTimeUnspecified = "Umbraco.DateTimeUnspecified";

/// <summary>
/// Date Time (with time zone).
/// </summary>
public const string DateTimeWithTimeZone = "Umbraco.DateTimeWithTimeZone";

/// <summary>
/// Date Only.
/// </summary>
public const string DateOnly = "Umbraco.DateOnly";

/// <summary>
/// Time Only.
/// </summary>
public const string TimeOnly = "Umbraco.TimeOnly";

/// <summary>
/// DropDown List.
/// </summary>
Expand Down
1 change: 1 addition & 0 deletions src/Umbraco.Core/EmbeddedResources/Lang/en.xml
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,7 @@
<key alias="invalidNull">Value cannot be null</key>
<key alias="invalidEmpty">Value cannot be empty</key>
<key alias="invalidPattern">Value is invalid, it does not match the correct pattern</key>
<key alias="invalidDate">Invalid date</key>
<key alias="entriesShort"><![CDATA[Minimum %0% entries, requires <strong>%1%</strong> more.]]></key>
<key alias="entriesExceed"><![CDATA[Maximum %0% entries, you have entered <strong>%1%</strong> too many.]]></key>
<key alias="stringLengthExceeded">The string length exceeds the maximum length of %0% characters, %1% too many.</key>
Expand Down
49 changes: 49 additions & 0 deletions src/Umbraco.Core/PropertyEditors/DateTimeConfiguration.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright (c) Umbraco.
// See LICENSE for more details.

using System.Text.Json.Serialization;

namespace Umbraco.Cms.Core.PropertyEditors;

public class DateTimeConfiguration
{
/// <summary>
/// Gets or sets the time zones configuration.
/// </summary>
[ConfigurationField("timeZones")]
public TimeZonesConfiguration? TimeZones { get; set; }

public class TimeZonesConfiguration
{
/// <summary>
/// The mode for time zones.
/// </summary>
public TimeZoneMode Mode { get; set; }

/// <summary>
/// A list of time zones to use when the mode is set to Custom.
/// </summary>
public List<string> TimeZones { get; set; } = [];
}

public enum TimeZoneMode
{
/// <summary>
/// Display all time zones.
/// </summary>
[JsonStringEnumMemberName("all")]
All,

/// <summary>
/// Display only the local time zone of the user.
/// </summary>
[JsonStringEnumMemberName("local")]
Local,

/// <summary>
/// Display a custom list of time zones defined in the configuration.
/// </summary>
[JsonStringEnumMemberName("custom")]
Custom,
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace Umbraco.Cms.Core.PropertyEditors;

/// <summary>
/// Factory for creating index values for Date Only properties.
/// </summary>
public interface IDateOnlyPropertyIndexValueFactory : IPropertyIndexValueFactory;
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace Umbraco.Cms.Core.PropertyEditors;

/// <summary>
/// Factory for creating index values for Date Time Unspecified properties.
/// </summary>
public interface IDateTimeUnspecifiedPropertyIndexValueFactory : IPropertyIndexValueFactory;
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace Umbraco.Cms.Core.PropertyEditors;

/// <summary>
/// Factory for creating index values for Date Time with Time Zone properties.
/// </summary>
public interface IDateTimeWithTimeZonePropertyIndexValueFactory : IPropertyIndexValueFactory;
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace Umbraco.Cms.Core.PropertyEditors;

/// <summary>
/// Factory for creating index values for Time Only properties.
/// </summary>
public interface ITimeOnlyPropertyIndexValueFactory : IPropertyIndexValueFactory;
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,10 @@ public static IUmbracoBuilder AddPropertyIndexValueFactories(this IUmbracoBuilde
builder.Services.AddSingleton<IBlockValuePropertyIndexValueFactory, BlockValuePropertyIndexValueFactory>();
builder.Services.AddSingleton<ITagPropertyIndexValueFactory, TagPropertyIndexValueFactory>();
builder.Services.AddSingleton<IRichTextPropertyIndexValueFactory, RichTextPropertyIndexValueFactory>();
builder.Services.AddSingleton<IDateOnlyPropertyIndexValueFactory, DateOnlyPropertyIndexValueFactory>();
builder.Services.AddSingleton<ITimeOnlyPropertyIndexValueFactory, TimeOnlyPropertyIndexValueFactory>();
builder.Services.AddSingleton<IDateTimeUnspecifiedPropertyIndexValueFactory, DateTimeUnspecifiedPropertyIndexValueFactory>();
builder.Services.AddSingleton<IDateTimeWithTimeZonePropertyIndexValueFactory, DateTimeWithTimeZonePropertyIndexValueFactory>();

return builder;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -863,6 +863,25 @@
},
Constants.DatabaseSchema.Tables.Node,
"id");
ConditionalInsert(
Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes,
Constants.DataTypes.Guids.DateTimePickerWithTimeZone,
new NodeDto
{
NodeId = 1055,
Trashed = false,
ParentId = -1,
UserId = -1,
Level = 1,
Path = "-1,1055",
SortOrder = 2,
UniqueId = Constants.DataTypes.Guids.DateTimePickerWithTimeZoneGuid,
Text = "Date Time Picker (with time zone)",
NodeObjectType = Constants.ObjectTypes.DataType,
CreateDate = DateTime.UtcNow,
},
Constants.DatabaseSchema.Tables.Node,
"id");
}

private void CreateNodeDataForMediaTypes()
Expand Down Expand Up @@ -2302,6 +2321,22 @@
"\", \"multiple\": true}",
});
}

if (_database.Exists<NodeDto>(1055))
{
_database.Insert(
Constants.DatabaseSchema.Tables.DataType,
"pk",
false,
new DataTypeDto
{
NodeId = 1055,
EditorAlias = Constants.PropertyEditors.Aliases.DateTimeWithTimeZone,
EditorUiAlias = "Umb.PropertyEditorUi.DateTimeWithTimeZonePicker",
DbType = "Ntext",
Configuration = "{\"timeFormat\": \"HH:mm\", \"timeZones\": {\"mode\": \"all\"}}",
});
}

Check warning on line 2339 in src/Umbraco.Infrastructure/Migrations/Install/DatabaseDataCreator.cs

View check run for this annotation

CodeScene Delta Analysis / CodeScene Code Health Review (v17/dev)

❌ Getting worse: Complex Method

CreateDataTypeData increases in cyclomatic complexity from 28 to 29, threshold = 9. This function has many conditional statements (e.g. if, for, while), leading to lower code health. Avoid adding more conditionals and code to it without refactoring.
}

private void CreateRelationTypeData()
Expand Down
13 changes: 13 additions & 0 deletions src/Umbraco.Infrastructure/Models/DateTimeEditorValue.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System.Runtime.Serialization;

namespace Umbraco.Cms.Infrastructure.Models;

[DataContract]
public class DateTimeEditorValue
{
[DataMember(Name = "date")]
public string? Date { get; set; }

[DataMember(Name = "timeZone")]
public string? TimeZone { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Copyright (c) Umbraco.
// See LICENSE for more details.

using System.Globalization;
using Umbraco.Cms.Core.IO;
using Umbraco.Cms.Core.PropertyEditors.ValueConverters;

namespace Umbraco.Cms.Core.PropertyEditors;

/// <summary>
/// Represents a property editor for editing date-only values.
/// </summary>
/// <remarks>
/// This is one of four property editors derived from <see cref="DateTimePropertyEditorBase"/> and storing their value as JSON with timezone information.
/// </remarks>
[DataEditor(
Constants.PropertyEditors.Aliases.DateOnly,
ValueType = ValueTypes.Json,
ValueEditorIsReusable = true)]
public sealed class DateOnlyPropertyEditor : DateTimePropertyEditorBase
{
/// <summary>
/// Initializes a new instance of the <see cref="DateOnlyPropertyEditor"/> class.
/// </summary>
public DateOnlyPropertyEditor(
IDataValueEditorFactory dataValueEditorFactory,
IIOHelper ioHelper,
IDateOnlyPropertyIndexValueFactory propertyIndexValueFactory)
: base(dataValueEditorFactory, ioHelper, propertyIndexValueFactory)
{
}

/// <inheritdoc />
protected override string MapDateToEditorFormat(DateTimeValueConverterBase.DateTimeDto dateTimeDto)
=> dateTimeDto.Date.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using Microsoft.Extensions.Logging;
using Umbraco.Cms.Core.Serialization;

namespace Umbraco.Cms.Core.PropertyEditors;

/// <summary>
/// Provides a factory for creating property index values for date only datetimes.
/// </summary>
/// <remarks>
/// This is one of four property index value factories derived from <see cref="DateTimePropertyIndexValueFactory"/> and storing their
/// value as JSON with timezone information.
/// </remarks>
internal class DateOnlyPropertyIndexValueFactory : DateTimePropertyIndexValueFactory, IDateOnlyPropertyIndexValueFactory
{
/// <summary>
/// Initializes a new instance of the <see cref="DateOnlyPropertyIndexValueFactory"/> class.
/// </summary>
public DateOnlyPropertyIndexValueFactory(
IJsonSerializer jsonSerializer,
ILogger<DateOnlyPropertyIndexValueFactory> logger)
: base(jsonSerializer, logger)
{
}

/// <inheritdoc/>
protected override string MapDateToIndexValueFormat(DateTimeOffset date)
=> date.UtcDateTime.ToString("yyyy-MM-dd");
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright (c) Umbraco.
// See LICENSE for more details.

using Umbraco.Cms.Core.IO;

namespace Umbraco.Cms.Core.PropertyEditors;

internal class DateTimeConfigurationEditor : ConfigurationEditor<DateTimeConfiguration>
{
public DateTimeConfigurationEditor(IIOHelper ioHelper)
: base(ioHelper)
{
}
}
Loading
Loading