Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New component: time span picker #2037

Merged
merged 54 commits into from
Mar 20, 2025
Merged
Changes from 1 commit
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
1229f62
TimeSpanPicker: initial
Cosmatevs Jan 28, 2025
76ec70b
TimeSpanPicker: adjust material themes, handle long labels
Cosmatevs Jan 28, 2025
1863bfc
TimeSpanPicker: fix value set, move invoking Change events for consis…
Cosmatevs Jan 29, 2025
48ed50c
Merge branch 'master' into timespan-picker
Cosmatevs Feb 2, 2025
a286789
TimeSpanPicker: fix preventKeyPress, adjust styles
Cosmatevs Feb 2, 2025
ceb4e94
TimeSpanPicker: adjust demos and add new
Cosmatevs Feb 2, 2025
f2e1102
PopupOrInline: handle Inline parameter change
Cosmatevs Feb 2, 2025
13efd9f
TimeSpanPicker: change icon and improve handling Disabled/ReadMe para…
Cosmatevs Feb 2, 2025
537970b
TimeSpanPicker: update demos
Cosmatevs Feb 2, 2025
033a178
TimeSpanPicker: add to the example panel
Cosmatevs Feb 2, 2025
e3af46b
DatePicker: add a tag and info about time picker
Cosmatevs Feb 2, 2025
2996731
Merge branch 'master' into timespan-picker
Cosmatevs Feb 3, 2025
139b67d
TimeSpanPicker: minor code cleanup, adjust styles, open popup on clic…
Cosmatevs Feb 3, 2025
82b339f
Merge branch 'master' into timespan-picker
Cosmatevs Feb 5, 2025
94eb3de
* TimeSpanPicker: minor style and code adjustments
Cosmatevs Feb 5, 2025
bdeb8e4
Merge branch 'master' into timespan-picker
Cosmatevs Feb 6, 2025
bd3a290
TimeSpanPicker: add to the index page
Cosmatevs Feb 6, 2025
843881a
TimeSpanPicker: adjust style code, use proper minus sign
Cosmatevs Feb 6, 2025
ec953b9
TimeSpanPicker:
Cosmatevs Feb 7, 2025
ef948d3
TimeSpanPicker: always refresh the displayed value on input change
Cosmatevs Feb 7, 2025
7833c51
TimeSpanPicker: add some tests (not finished yet)
Cosmatevs Feb 7, 2025
f79b736
Numeric: fix culture-dependent test fail
Cosmatevs Feb 7, 2025
6f1d999
TimeSpanPicker: reorganize parameters
Cosmatevs Feb 8, 2025
73bafe6
TimeSpanPicker tests: cover input parameters, add regions
Cosmatevs Feb 8, 2025
2e13b49
TimeSpanPicker: tweak regions of input and panel parameters
Cosmatevs Feb 8, 2025
550d611
TimeSpanPicker tests: reorganize regions, use more specific selectors
Cosmatevs Feb 8, 2025
979adfd
TimeSpanPicker: improve value change and popup toggle prevention
Cosmatevs Feb 9, 2025
29074c1
TimeSpanPicker:
Cosmatevs Feb 9, 2025
b1bfebf
Merge branch 'master' of https://github.com/Cosmatevs/radzen-blazor i…
Cosmatevs Feb 9, 2025
855e72f
FormField: add TimeSpanPicker in the demo
Cosmatevs Feb 11, 2025
677de1a
TimeSpanPicker: more tests
Cosmatevs Feb 12, 2025
a92e861
Merge branch 'master' into timespan-picker
Cosmatevs Feb 13, 2025
e1ccc17
revert unrelated and unintended changed
Cosmatevs Feb 13, 2025
8da7745
Merge branch 'master' into timespan-picker
Cosmatevs Feb 14, 2025
23d6d5d
TimeSpanPicker test: move theory data to properties, add step tests
Cosmatevs Feb 14, 2025
bcdf472
TimeSpanPicker test: minor code cleanup, add remaining label tests
Cosmatevs Feb 14, 2025
f13bf84
TimeSpanPicker test: use dictionary of unit element selectors
Cosmatevs Feb 14, 2025
9f84451
TimeSpanPicker test: create separate methods instead passing field ex…
Cosmatevs Feb 15, 2025
e64fa67
TimeSpanPicker: rename properties to match the convention and update …
Cosmatevs Feb 15, 2025
14c7087
Merge branch 'master' into timespan-picker
Cosmatevs Feb 15, 2025
8342e66
TimeSpanPicker: remove UnconfirmedValueChanged param
Cosmatevs Feb 15, 2025
8a00306
TimeSpanPicker: pass culture to numeric fields, add panel field rende…
Cosmatevs Feb 16, 2025
65b138e
TimeSpanPicker: unify unit fields under one RenderFragment function
Cosmatevs Feb 16, 2025
7947d44
TimeSpanPicker: fix missing microseconds picker, fix classes of input…
Cosmatevs Feb 16, 2025
85cfe27
TimeSpanPicker:
Cosmatevs Feb 16, 2025
445799f
Merge branch 'master' into timespan-picker
Cosmatevs Feb 18, 2025
c027425
revert unintended changes
Cosmatevs Feb 18, 2025
b0019c5
Merge branch 'master' into timespan-picker
Cosmatevs Feb 25, 2025
fa0ea13
Merge branch 'master' into timespan-picker
Cosmatevs Mar 7, 2025
9184cfa
TimeSpanPicker, DatePicker: fix icon positions in FormFields having f…
Cosmatevs Mar 7, 2025
597bac4
TimeSpanPicker: make AllowClear false by default, like in DatePicker
Cosmatevs Mar 13, 2025
7523057
Merge branch 'master' into timespan-picker
Cosmatevs Mar 13, 2025
7427fce
revert unintended change in demos project
Cosmatevs Mar 15, 2025
888c4c8
* remove PopupOrInline component
Cosmatevs Mar 17, 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
Prev Previous commit
Next Next commit
TimeSpanPicker: adjust demos and add new
Cosmatevs committed Feb 2, 2025
commit ceb4e94a620e7a967c7ad583ee8d2558418c0865
57 changes: 57 additions & 0 deletions RadzenBlazorDemos/Pages/TimeSpanPickerConfig.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<RadzenFieldset AllowCollapse="false" Text="Field config">
<RadzenStack Orientation="Orientation.Horizontal" Gap="1.5rem" Wrap="FlexWrap.Wrap">
<RadzenStack Orientation="Orientation.Horizontal" AlignItems="AlignItems.Center" Gap="0.5rem">
<RadzenCheckBox @bind-Value="@allowClear" Name="AllowClear" />
<RadzenLabel Text="Allow clear" Component="AllowClear" />
</RadzenStack>
<RadzenStack Orientation="Orientation.Horizontal" AlignItems="AlignItems.Center" Gap="0.5rem">
<RadzenCheckBox @bind-Value="@allowInput" Name="AllowInput" />
<RadzenLabel Text="Allow input" Component="AllowInput" />
</RadzenStack>
<RadzenStack Orientation="Orientation.Horizontal" AlignItems="AlignItems.Center" Gap="0.5rem">
<RadzenCheckBox @bind-Value="@readOnly" Name="ReadOnly" />
<RadzenLabel Text="Read only" Component="ReadOnly" />
</RadzenStack>
<RadzenStack Orientation="Orientation.Horizontal" AlignItems="AlignItems.Center" Gap="0.5rem">
<RadzenCheckBox @bind-Value="@disabled" Name="Disabled" />
<RadzenLabel Text="Disabled" Component="Disabled" />
</RadzenStack>
<RadzenStack Orientation="Orientation.Horizontal" AlignItems="AlignItems.Center" Gap="0.5rem">
<RadzenCheckBox @bind-Value="@showPopupButton" Name="ShowPopupButton" />
<RadzenLabel Text="Show popup button" Component="ShowPopupButton" />
</RadzenStack>
</RadzenStack>
</RadzenFieldset>
<RadzenFieldset AllowCollapse="false" Text="Panel config">
<RadzenStack Orientation="Orientation.Horizontal" Gap="1.5rem" Wrap="FlexWrap.Wrap">
<RadzenStack Orientation="Orientation.Horizontal" AlignItems="AlignItems.Center" Gap="0.5rem">
<RadzenLabel Text="Field precision" Component="FieldPrecision" />
<RadzenDropDown Name="FieldPrecision" @bind-Value="@fieldPrecision" Data="@(Enum.GetValues<TimeSpanUnit>())" Style="width: 9rem;" />
</RadzenStack>
<RadzenStack Orientation="Orientation.Horizontal" AlignItems="AlignItems.Center" Gap="0.5rem">
<RadzenCheckBox @bind-Value="@padTimeValues" Name="PadTimeValues" />
<RadzenLabel Text="Pad time values" Component="PadTimeValues" />
</RadzenStack>
<RadzenStack Orientation="Orientation.Horizontal" AlignItems="AlignItems.Center" Gap="0.5rem">
<RadzenCheckBox @bind-Value="@showConfirmationButton" Name="ShowConfirmationButton" />
<RadzenLabel Text="Show confirmation button" Component="ShowConfirmationButton" />
</RadzenStack>
</RadzenStack>
</RadzenFieldset>
<RadzenStack Orientation="Orientation.Horizontal" JustifyContent="JustifyContent.Center" AlignItems="AlignItems.Center" Gap="0.5rem" class="rz-p-12">
<RadzenLabel Text="Select Time Span" Component="RadzenTimeSpanPickerBoolConfig" />
<RadzenTimeSpanPicker Name="RadzenTimeSpanPickerBoolConfig" @bind-Value="@value" AllowClear="@allowClear" AllowInput="@allowInput" ReadOnly="@readOnly" Disabled="@disabled" ShowPopupButton="@showPopupButton" FieldPrecision="@fieldPrecision" PadTimeValues="@padTimeValues" ShowConfirmationButton="@showConfirmationButton" />
</RadzenStack>

@code {
TimeSpan? value;

bool allowClear = true;
bool allowInput = true;
bool readOnly = false;
bool disabled = false;
bool padTimeValues = false;
bool showPopupButton = false;
bool showConfirmationButton = false;
TimeSpanUnit fieldPrecision = TimeSpanUnit.Second;
}
3 changes: 2 additions & 1 deletion RadzenBlazorDemos/Pages/TimeSpanPickerFormat.razor
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
<RadzenStack Orientation="Orientation.Horizontal" JustifyContent="JustifyContent.Center" AlignItems="AlignItems.Center" Gap="0.5rem" class="rz-p-12">
<RadzenLabel Text="Select Time Span" Component="RadzenTimeSpanPickerFormat"/>
<RadzenTimeSpanPicker @bind-Value="@value" Name="RadzenTimeSpanPickerFormat" TimeSpanFormat="d'd 'h'h 'm'min 's's'" />
<RadzenTimeSpanPicker @bind-Value="@value" Name="RadzenTimeSpanPickerFormat" TimeSpanFormat="@timeSpanFormat" />
</RadzenStack>

@code {
string timeSpanFormat => (value < TimeSpan.Zero ? "'-'" : "") + "d'd 'h'h 'm'min 's's'";
TimeSpan? value = new TimeSpan(1, 12, 30, 0);
}
8 changes: 8 additions & 0 deletions RadzenBlazorDemos/Pages/TimeSpanPickerInline.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<RadzenStack Orientation="Orientation.Vertical" JustifyContent="JustifyContent.Center" AlignItems="AlignItems.Center" Gap="0.5rem" class="rz-p-12">
<RadzenTimeSpanPicker @bind-Value="@value" Inline />
<div>@value</div>
</RadzenStack>

@code {
TimeSpan? value;
}
28 changes: 27 additions & 1 deletion RadzenBlazorDemos/Pages/TimeSpanPickerPage.razor
Original file line number Diff line number Diff line change
@@ -35,13 +35,39 @@
<TimeSpanPickerFormat />
</RadzenExample>

<RadzenText Anchor="timespanpicker#min-max-dates" TextStyle="TextStyle.H5" TagName="TagName.H2" class="rz-pt-12 rz-mb-6">
<RadzenText Anchor="timespanpicker#min-max-values" TextStyle="TextStyle.H5" TagName="TagName.H2" class="rz-pt-12 rz-mb-6">
Set Min and Max values
</RadzenText>
<RadzenExample ComponentName="TimeSpanPicker" Example="TimeSpanPickerMinMax">
<TimeSpanPickerMinMax />
</RadzenExample>

<RadzenText Anchor="timespanpicker#inline" TextStyle="TextStyle.H5" TagName="TagName.H2" class="rz-pt-12 rz-mb-6">
Inline picker
</RadzenText>
<RadzenExample ComponentName="TimeSpanPicker" Example="TimeSpanPickerInline">
<TimeSpanPickerInline />
</RadzenExample>

<RadzenText Anchor="timespanpicker#various-config" TextStyle="TextStyle.H5" TagName="TagName.H2" class="rz-pt-12 rz-mb-6">
Various configurations
</RadzenText>
<RadzenExample ComponentName="TimeSpanPicker" Example="TimeSpanPickerConfig">
<TimeSpanPickerConfig />
</RadzenExample>

<RadzenText Anchor="timespanpicker#custom-input-parsing" TextStyle="TextStyle.H5" TagName="TagName.H2" class="rz-pt-12">
Define custom input parsing
</RadzenText>
<RadzenText TextStyle="TextStyle.Body1" class="rz-mb-8">
The parameter named <code>ParseInput</code> allows a fully custom input parsing method.<br />
This way you can accept inputs like '1d 20h 15min' or '-120s' or support more than one input format.<br />
If your method returns null, the default parser is be used instead.
</RadzenText>
<RadzenExample ComponentName="TimeSpanPicker" Example="TimeSpanPickerParseInput">
<TimeSpanPickerParseInput />
</RadzenExample>


<RadzenText Anchor="timespanpicker#keyboard-navigation" TextStyle="TextStyle.H5" TagName="TagName.H2" class="rz-pt-12">
Keyboard Navigation
56 changes: 56 additions & 0 deletions RadzenBlazorDemos/Pages/TimeSpanPickerParseInput.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
@using System.Text.RegularExpressions
<RadzenStack Orientation="Orientation.Horizontal" JustifyContent="JustifyContent.Center" AlignItems="AlignItems.Center" Gap="0.5rem" class="rz-p-12">
<RadzenLabel Text="Select Time Span" Component="RadzenTimeSpanPickerParseInput"/>
<RadzenTimeSpanPicker @bind-Value="@value" Name="RadzenTimeSpanPickerParseInput" ParseInput="@ParseTimeSpan" />
</RadzenStack>

@code {
TimeSpan? value;

string[] standardFormats = { "c", "g", "G" };
Regex customTimeSpanRegex = new Regex(@"(?:(?<days>-?\d+)\w?d)|(?:(?<hours>-?\d+)\w?h)|(?:(?<minutes>-?\d+)\w?min)|(?:(?<seconds>-?\d+)\w?s)");

public TimeSpan? ParseTimeSpan(string input)
{
foreach (var format in standardFormats)
{
if (TimeSpan.TryParseExact(input, format, null, System.Globalization.TimeSpanStyles.None, out var standardResult))
{
return standardResult;
}
}

var regexGroups = customTimeSpanRegex.Matches(input.Trim())
.Where(x => x.Success)
.SelectMany(x => x.Groups.Cast<System.Text.RegularExpressions.Group>())
.Where(x => x.Success)
.ToArray();

if (regexGroups.Length == 0)
{
return null;
}

var timeUnitToValue = new Dictionary<string, int>() {
{"days", 0},
{"hours", 0},
{"minutes", 0},
{"seconds", 0}
};

foreach (var timeUnitWithValue in timeUnitToValue)
{
var unit = timeUnitWithValue.Key;
var valueString = regexGroups.FirstOrDefault(x => x.Name == unit)?.Value ?? "0";

if (Int32.TryParse(valueString, out int value))
{
timeUnitToValue[unit] = value;
}
}

var result = new TimeSpan(timeUnitToValue["days"], timeUnitToValue["hours"], timeUnitToValue["minutes"], timeUnitToValue["seconds"]);

return result;
}
}