mirror of
https://github.com/radzenhq/radzen-blazor.git
synced 2026-02-04 05:35:44 +00:00
Compare commits
374 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
45a1ce4b55 | ||
|
|
3e5cb2e30b | ||
|
|
d0a4c6aaf1 | ||
|
|
be4bcb7390 | ||
|
|
a63c3aa4c2 | ||
|
|
e8e43d97f2 | ||
|
|
9939ff4452 | ||
|
|
b69bbc899e | ||
|
|
f0cba24cc7 | ||
|
|
fd5fa0e798 | ||
|
|
1ba1d53884 | ||
|
|
00a118b901 | ||
|
|
ba2ea55884 | ||
|
|
70b4c3dd0f | ||
|
|
412e19252c | ||
|
|
73e1974583 | ||
|
|
25c57d645b | ||
|
|
a6c6021923 | ||
|
|
2886ac9d7c | ||
|
|
c121414767 | ||
|
|
35f02ef7a9 | ||
|
|
ffeb972a82 | ||
|
|
f20a74674f | ||
|
|
03396fbbe2 | ||
|
|
54a5c0805e | ||
|
|
486cb66b6c | ||
|
|
e5d7a344c7 | ||
|
|
60fe0ed25f | ||
|
|
04741c702a | ||
|
|
6e190fe903 | ||
|
|
5bb3e65eb9 | ||
|
|
c3b29ffcd1 | ||
|
|
a889c3e97b | ||
|
|
bd578ca7cd | ||
|
|
2a9a115c31 | ||
|
|
4d1848a5e1 | ||
|
|
4bd8f777e0 | ||
|
|
4654a9011b | ||
|
|
22a5dc148a | ||
|
|
88dc4c0607 | ||
|
|
0a7c47fa70 | ||
|
|
e6f311ebba | ||
|
|
88d09f0fef | ||
|
|
7467d87e36 | ||
|
|
b50e793a9c | ||
|
|
1147390576 | ||
|
|
539785f079 | ||
|
|
b99b516346 | ||
|
|
c0dc4f4236 | ||
|
|
5b8f664530 | ||
|
|
cc490692ad | ||
|
|
5ef415c87d | ||
|
|
ff3c67409d | ||
|
|
582a9bae31 | ||
|
|
95f51ed935 | ||
|
|
0dca22c219 | ||
|
|
eaf67e197b | ||
|
|
b8db918348 | ||
|
|
c865073605 | ||
|
|
192ccbec25 | ||
|
|
b8b3b29d01 | ||
|
|
00ea9a4393 | ||
|
|
267392d0b7 | ||
|
|
e5f041208f | ||
|
|
82010353c6 | ||
|
|
7daf4d1f58 | ||
|
|
ebb940ee0e | ||
|
|
1ce8c98837 | ||
|
|
257948cbe1 | ||
|
|
8971e0aa1a | ||
|
|
2209b050b0 | ||
|
|
b5a876a93e | ||
|
|
4c64ee24d5 | ||
|
|
1a3376374f | ||
|
|
ee88560090 | ||
|
|
aae7eba068 | ||
|
|
6715bc34d8 | ||
|
|
55d0ea5e22 | ||
|
|
11c692b146 | ||
|
|
ab47bd2e7b | ||
|
|
6dd9933d55 | ||
|
|
d08d398b47 | ||
|
|
aa3903d8f0 | ||
|
|
26f9030cef | ||
|
|
0500a10671 | ||
|
|
c3ae2d3eda | ||
|
|
e502c51886 | ||
|
|
063c1aa6c0 | ||
|
|
5e5db9193e | ||
|
|
26a38fc56c | ||
|
|
aad0558a9c | ||
|
|
a911f975da | ||
|
|
a99c8fbc88 | ||
|
|
79525227a9 | ||
|
|
66b8eb72bf | ||
|
|
1eff269b80 | ||
|
|
2dc01b528c | ||
|
|
30e200896d | ||
|
|
7d2e827e6f | ||
|
|
94e6b3086b | ||
|
|
0849e90574 | ||
|
|
d3eef33371 | ||
|
|
1cee0d10e5 | ||
|
|
3f044b407a | ||
|
|
b25ce3760b | ||
|
|
6e810761f8 | ||
|
|
6dea80e13e | ||
|
|
a715616a6a | ||
|
|
e87db432d5 | ||
|
|
0b4b89dcbd | ||
|
|
0e980051e3 | ||
|
|
4bd489a530 | ||
|
|
ed02c0dbc1 | ||
|
|
81e2432426 | ||
|
|
3a14099831 | ||
|
|
84712967b0 | ||
|
|
1fc70b7591 | ||
|
|
b9f8345964 | ||
|
|
fcd9e674d5 | ||
|
|
2cf2dfaea5 | ||
|
|
797be4e57c | ||
|
|
2478f1478f | ||
|
|
58cd508be4 | ||
|
|
9ca094f4f8 | ||
|
|
9ed9878193 | ||
|
|
c878a47f92 | ||
|
|
42d7a8860a | ||
|
|
718824f359 | ||
|
|
3b5b649530 | ||
|
|
8702af0c42 | ||
|
|
b038157f2f | ||
|
|
0033bdd570 | ||
|
|
99b40cac43 | ||
|
|
7fa91f98c6 | ||
|
|
a6e3f48044 | ||
|
|
d25921f6c8 | ||
|
|
e1986dc8eb | ||
|
|
ebba5b860f | ||
|
|
4beff8932e | ||
|
|
e26bd9adfb | ||
|
|
2eadc7b5ea | ||
|
|
a15aeade6a | ||
|
|
1990b7fad5 | ||
|
|
d81d5a37f8 | ||
|
|
1c1da0b080 | ||
|
|
4063bce178 | ||
|
|
b4d33c6472 | ||
|
|
44005c607d | ||
|
|
c17852a583 | ||
|
|
f94b22666b | ||
|
|
3c8c690a79 | ||
|
|
6f416ffe79 | ||
|
|
e4f8fe9ea2 | ||
|
|
003738149e | ||
|
|
6f39223787 | ||
|
|
06649c2207 | ||
|
|
18f51becd8 | ||
|
|
916792abea | ||
|
|
c8f8e019f6 | ||
|
|
7b6c6bb930 | ||
|
|
b826993a0d | ||
|
|
00385c8e15 | ||
|
|
5b982766fb | ||
|
|
be27dfd918 | ||
|
|
a82089aff3 | ||
|
|
215ba8bfbf | ||
|
|
7b1e9185f7 | ||
|
|
8c756e99c1 | ||
|
|
d2384e74cd | ||
|
|
b2ff2852bd | ||
|
|
3b4505af27 | ||
|
|
87eee126e5 | ||
|
|
6234f04457 | ||
|
|
c8e808082f | ||
|
|
b2f2642c82 | ||
|
|
0f77730011 | ||
|
|
b062d56928 | ||
|
|
a3f8552b80 | ||
|
|
8faf5a81ca | ||
|
|
7d7c0ae320 | ||
|
|
2bd8b71927 | ||
|
|
19a323ec77 | ||
|
|
29ee95165e | ||
|
|
c618a31e44 | ||
|
|
f972de507f | ||
|
|
51a0be31d5 | ||
|
|
d986c12564 | ||
|
|
1ae17b121e | ||
|
|
afb294f170 | ||
|
|
2b63fa343a | ||
|
|
35121f1141 | ||
|
|
9d0f26fede | ||
|
|
f0289b73b8 | ||
|
|
1009619ecd | ||
|
|
f30b1b1e08 | ||
|
|
d151f39a22 | ||
|
|
be6d4accff | ||
|
|
69e71202ee | ||
|
|
fece284aee | ||
|
|
4bcb44bcb2 | ||
|
|
0891dbf5a8 | ||
|
|
b5b5a86025 | ||
|
|
3fcbe831d7 | ||
|
|
d253151296 | ||
|
|
4e9beb86b0 | ||
|
|
7f85b49f3f | ||
|
|
1ea8c56631 | ||
|
|
5d76cbee26 | ||
|
|
682e4af619 | ||
|
|
c446476fbc | ||
|
|
e18a05001e | ||
|
|
0685f8b9c0 | ||
|
|
bdd1d4e8c1 | ||
|
|
bf6923f909 | ||
|
|
faa37c3322 | ||
|
|
1fe5b07f86 | ||
|
|
7a9ad3933b | ||
|
|
df2e447362 | ||
|
|
b2033f3dcd | ||
|
|
186bce852d | ||
|
|
e1494441b0 | ||
|
|
1b67c130c7 | ||
|
|
628b980655 | ||
|
|
0e04a17380 | ||
|
|
cee1a14ebd | ||
|
|
3862205053 | ||
|
|
9696f044a0 | ||
|
|
b61a0f2c94 | ||
|
|
afb2e3a8a2 | ||
|
|
65cc0a0ed5 | ||
|
|
dba6f2ec6a | ||
|
|
b39ea03ba6 | ||
|
|
528483b905 | ||
|
|
fb7434f1b4 | ||
|
|
a239e6405b | ||
|
|
d5c00b81d7 | ||
|
|
590f6c8c8b | ||
|
|
edf2495a9f | ||
|
|
ed0a034414 | ||
|
|
3e33e0d0e1 | ||
|
|
c9e1c2711e | ||
|
|
1f0420dc1f | ||
|
|
f0320c6ff9 | ||
|
|
904eb1364c | ||
|
|
e5ef184515 | ||
|
|
2a4111643c | ||
|
|
53ffe057b2 | ||
|
|
b2632e1727 | ||
|
|
84554d6dea | ||
|
|
6fd8f8380b | ||
|
|
5330929efd | ||
|
|
c67bc9938c | ||
|
|
f41f0e94be | ||
|
|
74b1c6f4ed | ||
|
|
54d7e20baa | ||
|
|
221d88c52c | ||
|
|
eb3c8050fe | ||
|
|
fdab854799 | ||
|
|
ba32761a0c | ||
|
|
6d002838a5 | ||
|
|
d8f53db387 | ||
|
|
f15db1637e | ||
|
|
5f98e2fdc5 | ||
|
|
603dc9f9c6 | ||
|
|
0692079384 | ||
|
|
e046cdce45 | ||
|
|
595419df77 | ||
|
|
1a641afaa8 | ||
|
|
29c73ae90f | ||
|
|
e055f99f63 | ||
|
|
888d4797d0 | ||
|
|
b95d63e974 | ||
|
|
195abb59ff | ||
|
|
306ceba474 | ||
|
|
2be1476130 | ||
|
|
ca80356c27 | ||
|
|
eed34d9b7d | ||
|
|
1144ab32b7 | ||
|
|
0061e609d4 | ||
|
|
680b64c98f | ||
|
|
325048efcb | ||
|
|
aedb293d50 | ||
|
|
6cdc1943fb | ||
|
|
9ff40875c2 | ||
|
|
3a851d59fe | ||
|
|
64de7abada | ||
|
|
6d9feebedd | ||
|
|
441658eb7a | ||
|
|
01a441a99c | ||
|
|
1d10141c1d | ||
|
|
952313acee | ||
|
|
d537b742dc | ||
|
|
f3b706bcc2 | ||
|
|
2a57af944f | ||
|
|
3f42b93300 | ||
|
|
59a58eb886 | ||
|
|
d91d5bcd9b | ||
|
|
c6a08c79e1 | ||
|
|
d550b65bc7 | ||
|
|
42418ef393 | ||
|
|
12f4156ae0 | ||
|
|
ff58873fcb | ||
|
|
925c72f6aa | ||
|
|
345d853e2d | ||
|
|
10b064dc40 | ||
|
|
75a7187a87 | ||
|
|
6182e00c31 | ||
|
|
e3ba93a6b8 | ||
|
|
109d8cacbc | ||
|
|
3bcc18f035 | ||
|
|
92baa1affb | ||
|
|
32a9457de3 | ||
|
|
32c147fa16 | ||
|
|
d61d75f8bb | ||
|
|
eae6cd5396 | ||
|
|
6f16f230d1 | ||
|
|
f458a057e8 | ||
|
|
d013300fa3 | ||
|
|
d6b8394044 | ||
|
|
c1fa630602 | ||
|
|
28a03dadaf | ||
|
|
29cfc2ea6b | ||
|
|
f4c776f10e | ||
|
|
04be6bc38b | ||
|
|
4f0bbeeab0 | ||
|
|
5a356a8d75 | ||
|
|
7f35f46eaa | ||
|
|
ea7be67d83 | ||
|
|
8f0d65766d | ||
|
|
a140f318a2 | ||
|
|
d0a2d1644f | ||
|
|
e69b153e1c | ||
|
|
d19d383738 | ||
|
|
253f288323 | ||
|
|
d6ce0536ca | ||
|
|
0168c01915 | ||
|
|
7329fec67a | ||
|
|
5fea22294e | ||
|
|
669124a6b3 | ||
|
|
c44d141c07 | ||
|
|
0b30e00b8c | ||
|
|
1e7bd1bf48 | ||
|
|
c2c4d6aa02 | ||
|
|
7e0c64191c | ||
|
|
323e4e971a | ||
|
|
99b4f8f8fc | ||
|
|
7c1cf76c5c | ||
|
|
305e1b7af6 | ||
|
|
6880a70227 | ||
|
|
0482969755 | ||
|
|
4c9b429dae | ||
|
|
60b8400e29 | ||
|
|
7260be98d6 | ||
|
|
be94094de7 | ||
|
|
645077f39b | ||
|
|
b42940441d | ||
|
|
fc7071c04e | ||
|
|
de887a4e3f | ||
|
|
7f629309c7 | ||
|
|
fa45e209d5 | ||
|
|
40aec6cd0d | ||
|
|
969ae7aeca | ||
|
|
a64bbd34f3 | ||
|
|
79acf83d6f | ||
|
|
786e8d0be1 | ||
|
|
2757850f28 | ||
|
|
7c6f39f3b5 | ||
|
|
70723d0437 | ||
|
|
bd9b0f798b | ||
|
|
0c406b2ad8 | ||
|
|
822891541c | ||
|
|
bf064fd4e3 | ||
|
|
6c9e055d42 | ||
|
|
7455d1bfb2 |
74
Radzen.Blazor.Tests/AutoCompleteTests.cs
Normal file
74
Radzen.Blazor.Tests/AutoCompleteTests.cs
Normal file
@@ -0,0 +1,74 @@
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class AutoCompleteTests
|
||||
{
|
||||
[Fact]
|
||||
public void AutoComplete_Enum_Converts_To_Attr_Value()
|
||||
{
|
||||
// Options
|
||||
Assert.Equal("off", AutoCompleteType.Off.GetAutoCompleteValue());
|
||||
Assert.Equal("on", AutoCompleteType.On.GetAutoCompleteValue());
|
||||
Assert.Equal("name", AutoCompleteType.Name.GetAutoCompleteValue());
|
||||
Assert.Equal("honorific-prefix", AutoCompleteType.HonorificPrefix.GetAutoCompleteValue());
|
||||
Assert.Equal("given-name", AutoCompleteType.GivenName.GetAutoCompleteValue());
|
||||
Assert.Equal("additional-name", AutoCompleteType.AdditionalName.GetAutoCompleteValue());
|
||||
Assert.Equal("family-name", AutoCompleteType.FamilyName.GetAutoCompleteValue());
|
||||
Assert.Equal("honorific-suffix", AutoCompleteType.HonorificSuffix.GetAutoCompleteValue());
|
||||
Assert.Equal("nickname", AutoCompleteType.Nickname.GetAutoCompleteValue());
|
||||
Assert.Equal("email", AutoCompleteType.Email.GetAutoCompleteValue());
|
||||
Assert.Equal("username", AutoCompleteType.Username.GetAutoCompleteValue());
|
||||
Assert.Equal("new-password", AutoCompleteType.NewPassword.GetAutoCompleteValue());
|
||||
Assert.Equal("current-password", AutoCompleteType.CurrentPassword.GetAutoCompleteValue());
|
||||
Assert.Equal("one-time-code", AutoCompleteType.OneTimeCode.GetAutoCompleteValue());
|
||||
Assert.Equal("organization-title", AutoCompleteType.OrganizationTitle.GetAutoCompleteValue());
|
||||
Assert.Equal("organization", AutoCompleteType.Organization.GetAutoCompleteValue());
|
||||
Assert.Equal("street-address", AutoCompleteType.StreetAddress.GetAutoCompleteValue());
|
||||
Assert.Equal("address-line1", AutoCompleteType.AddressLine1.GetAutoCompleteValue());
|
||||
Assert.Equal("address-line2", AutoCompleteType.AddressLine2.GetAutoCompleteValue());
|
||||
Assert.Equal("address-line3", AutoCompleteType.AddressLine3.GetAutoCompleteValue());
|
||||
Assert.Equal("address-level1", AutoCompleteType.AddressLevel1.GetAutoCompleteValue());
|
||||
Assert.Equal("address-level2", AutoCompleteType.AddressLevel2.GetAutoCompleteValue());
|
||||
Assert.Equal("address-level3", AutoCompleteType.AddressLevel3.GetAutoCompleteValue());
|
||||
Assert.Equal("address-level4", AutoCompleteType.AddressLevel4.GetAutoCompleteValue());
|
||||
Assert.Equal("country", AutoCompleteType.Country.GetAutoCompleteValue());
|
||||
Assert.Equal("country-name", AutoCompleteType.CountryName.GetAutoCompleteValue());
|
||||
Assert.Equal("postal-code", AutoCompleteType.PostalCode.GetAutoCompleteValue());
|
||||
Assert.Equal("cc-name", AutoCompleteType.CcName.GetAutoCompleteValue());
|
||||
Assert.Equal("cc-given-name", AutoCompleteType.CcGivenName.GetAutoCompleteValue());
|
||||
Assert.Equal("cc-additional-name", AutoCompleteType.CcAdditionalName.GetAutoCompleteValue());
|
||||
Assert.Equal("cc-family-name", AutoCompleteType.CcFamilyName.GetAutoCompleteValue());
|
||||
Assert.Equal("cc-number", AutoCompleteType.CcNumber.GetAutoCompleteValue());
|
||||
Assert.Equal("cc-exp", AutoCompleteType.CcExp.GetAutoCompleteValue());
|
||||
Assert.Equal("cc-exp-month", AutoCompleteType.CcExpMonth.GetAutoCompleteValue());
|
||||
Assert.Equal("cc-exp-year", AutoCompleteType.CcExpYear.GetAutoCompleteValue());
|
||||
Assert.Equal("cc-csc", AutoCompleteType.CcCsc.GetAutoCompleteValue());
|
||||
Assert.Equal("cc-type", AutoCompleteType.CcType.GetAutoCompleteValue());
|
||||
Assert.Equal("transaction-currency", AutoCompleteType.TransactionCurrency.GetAutoCompleteValue());
|
||||
Assert.Equal("transaction-amount", AutoCompleteType.TransactionAmount.GetAutoCompleteValue());
|
||||
Assert.Equal("language", AutoCompleteType.Language.GetAutoCompleteValue());
|
||||
Assert.Equal("bday", AutoCompleteType.Bday.GetAutoCompleteValue());
|
||||
Assert.Equal("bday-day", AutoCompleteType.BdayDay.GetAutoCompleteValue());
|
||||
Assert.Equal("bday-month", AutoCompleteType.BdayMonth.GetAutoCompleteValue());
|
||||
Assert.Equal("bday-year", AutoCompleteType.BdayYear.GetAutoCompleteValue());
|
||||
Assert.Equal("sex", AutoCompleteType.Sex.GetAutoCompleteValue());
|
||||
Assert.Equal("tel", AutoCompleteType.Tel.GetAutoCompleteValue());
|
||||
Assert.Equal("tel-country-code", AutoCompleteType.TelCountryCode.GetAutoCompleteValue());
|
||||
Assert.Equal("tel-national", AutoCompleteType.TelNational.GetAutoCompleteValue());
|
||||
Assert.Equal("tel-area-code", AutoCompleteType.TelAreaCode.GetAutoCompleteValue());
|
||||
Assert.Equal("tel-local", AutoCompleteType.TelLocal.GetAutoCompleteValue());
|
||||
Assert.Equal("tel-extension", AutoCompleteType.TelExtension.GetAutoCompleteValue());
|
||||
Assert.Equal("impp", AutoCompleteType.Impp.GetAutoCompleteValue());
|
||||
Assert.Equal("url", AutoCompleteType.Url.GetAutoCompleteValue());
|
||||
Assert.Equal("photo", AutoCompleteType.Photo.GetAutoCompleteValue());
|
||||
// Synonyms
|
||||
Assert.Equal("address-level1", AutoCompleteType.State.GetAutoCompleteValue());
|
||||
Assert.Equal("address-level1", AutoCompleteType.Province.GetAutoCompleteValue());
|
||||
Assert.Equal("postal-code", AutoCompleteType.ZipCode.GetAutoCompleteValue());
|
||||
Assert.Equal("given-name", AutoCompleteType.FirstName.GetAutoCompleteValue());
|
||||
Assert.Equal("additional-name", AutoCompleteType.MiddleName.GetAutoCompleteValue());
|
||||
Assert.Equal("family-name", AutoCompleteType.LastName.GetAutoCompleteValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -128,6 +128,34 @@ namespace Radzen.Blazor.Tests
|
||||
Assert.Contains(@$"autocomplete=""on""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Mask_Renders_TypedAutoCompleteParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenMask>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, false));
|
||||
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.On));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""off""", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, true));
|
||||
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.Off));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""off""", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, true));
|
||||
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.AdditionalName));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""{AutoCompleteType.AdditionalName.GetAutoCompleteValue()}""", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, true));
|
||||
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.Email));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""{AutoCompleteType.Email.GetAutoCompleteValue()}""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Mask_Renders_MaxLengthParameter()
|
||||
{
|
||||
|
||||
@@ -193,6 +193,34 @@ namespace Radzen.Blazor.Tests
|
||||
Assert.Contains(@$"autocomplete=""on""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Numeric_Renders_TypedAutoCompleteParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenNumeric<double>>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, false));
|
||||
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.On));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""off""", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, true));
|
||||
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.Off));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""off""", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, true));
|
||||
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.BdayMonth));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""{AutoCompleteType.BdayMonth.GetAutoCompleteValue()}""", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, true));
|
||||
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.BdayYear));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""{AutoCompleteType.BdayYear.GetAutoCompleteValue()}""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Numeric_Raises_ChangedEvent()
|
||||
{
|
||||
|
||||
@@ -128,6 +128,34 @@ namespace Radzen.Blazor.Tests
|
||||
Assert.Contains(@$"autocomplete=""on""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Password_Renders_TypedAutoCompleteParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenPassword>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, false));
|
||||
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.On));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""new-password""", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, true));
|
||||
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.Off));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""off""", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, true));
|
||||
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.CurrentPassword));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""{AutoCompleteType.CurrentPassword.GetAutoCompleteValue()}""", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, true));
|
||||
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.NewPassword));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""{AutoCompleteType.NewPassword.GetAutoCompleteValue()}""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Password_Renders_UnmatchedParameter()
|
||||
{
|
||||
|
||||
@@ -128,6 +128,34 @@ namespace Radzen.Blazor.Tests
|
||||
Assert.Contains(@$"autocomplete=""on""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TextBox_Renders_TypedAutoCompleteParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenTextBox>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, false));
|
||||
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.On));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""off""", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, true));
|
||||
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.Off));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""off""", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, true));
|
||||
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.AdditionalName));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""{AutoCompleteType.AdditionalName.GetAutoCompleteValue()}""", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AutoComplete, true));
|
||||
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.FamilyName));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""{AutoCompleteType.FamilyName.GetAutoCompleteValue()}""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TextBox_Renders_MaxLengthParameter()
|
||||
{
|
||||
|
||||
81
Radzen.Blazor/AutoCompleteType.cs
Normal file
81
Radzen.Blazor/AutoCompleteType.cs
Normal file
@@ -0,0 +1,81 @@
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// The <c>AutomCompleteType</c> is a string-associated enum of
|
||||
/// browser-supported autocomplete attribute values.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This class lists the autocomplete attirbute options allowing
|
||||
/// developers to provide the browser with guidance on how to pre-populate
|
||||
/// the form fields. It is a class rather than a simpler enum to associate
|
||||
/// each option with the string the browser expects. For more information
|
||||
/// please review the list of options (https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete)
|
||||
/// and the spec (https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofill).
|
||||
/// </remarks>
|
||||
public enum AutoCompleteType
|
||||
{
|
||||
// Options
|
||||
Off,
|
||||
On,
|
||||
Name,
|
||||
HonorificPrefix,
|
||||
GivenName,
|
||||
AdditionalName,
|
||||
FamilyName,
|
||||
HonorificSuffix,
|
||||
Nickname,
|
||||
Email,
|
||||
Username,
|
||||
NewPassword,
|
||||
CurrentPassword,
|
||||
OneTimeCode,
|
||||
OrganizationTitle,
|
||||
Organization,
|
||||
StreetAddress,
|
||||
AddressLine1,
|
||||
AddressLine2,
|
||||
AddressLine3,
|
||||
AddressLevel1,
|
||||
AddressLevel2,
|
||||
AddressLevel3,
|
||||
AddressLevel4,
|
||||
Country,
|
||||
CountryName,
|
||||
PostalCode,
|
||||
CcName,
|
||||
CcGivenName,
|
||||
CcAdditionalName,
|
||||
CcFamilyName,
|
||||
CcNumber,
|
||||
CcExp,
|
||||
CcExpMonth,
|
||||
CcExpYear,
|
||||
CcCsc,
|
||||
CcType,
|
||||
TransactionCurrency,
|
||||
TransactionAmount,
|
||||
Language,
|
||||
Bday,
|
||||
BdayDay,
|
||||
BdayMonth,
|
||||
BdayYear,
|
||||
Sex,
|
||||
Tel,
|
||||
TelCountryCode,
|
||||
TelNational,
|
||||
TelAreaCode,
|
||||
TelLocal,
|
||||
TelExtension,
|
||||
Impp,
|
||||
Url,
|
||||
Photo,
|
||||
|
||||
// Synonyms
|
||||
State,
|
||||
Province,
|
||||
ZipCode,
|
||||
FirstName,
|
||||
MiddleName,
|
||||
LastName,
|
||||
}
|
||||
}
|
||||
@@ -687,7 +687,7 @@ namespace Radzen.Blazor
|
||||
public virtual IEnumerable<ChartDataLabel> GetDataLabels(double offsetX, double offsetY)
|
||||
{
|
||||
var list = new List<ChartDataLabel>();
|
||||
|
||||
|
||||
foreach (var d in Data)
|
||||
{
|
||||
list.Add(new ChartDataLabel
|
||||
|
||||
@@ -17,6 +17,22 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace Radzen
|
||||
{
|
||||
/// <summary>
|
||||
/// Html editor mode (Rendered or Raw). Also used for toolbar buttons to enable/disable according to mode.
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum HtmlEditorMode
|
||||
{
|
||||
/// <summary>
|
||||
/// The editor is in Design mode.
|
||||
/// </summary>
|
||||
Design = 1,
|
||||
/// <summary>
|
||||
/// The editor is in Source mode.
|
||||
/// </summary>
|
||||
Source = 2,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// DataGrid settings class used to Save/Load settings.
|
||||
/// </summary>
|
||||
|
||||
@@ -323,7 +323,7 @@ namespace Radzen
|
||||
var i = 0;
|
||||
b.OpenElement(i++, "p");
|
||||
b.AddAttribute(i++, "class", "rz-dialog-confirm-message");
|
||||
b.AddContent(i++, message);
|
||||
b.AddContent(i++, (MarkupString)message);
|
||||
b.CloseElement();
|
||||
|
||||
b.OpenElement(i++, "div");
|
||||
@@ -381,7 +381,7 @@ namespace Radzen
|
||||
var i = 0;
|
||||
b.OpenElement(i++, "p");
|
||||
b.AddAttribute(i++, "class", "rz-dialog-alert-message");
|
||||
b.AddContent(i++, message);
|
||||
b.AddContent(i++, (MarkupString)message);
|
||||
b.CloseElement();
|
||||
|
||||
b.OpenElement(i++, "div");
|
||||
|
||||
@@ -17,6 +17,12 @@ namespace Radzen
|
||||
public class DropDownBase<T> : DataBoundFormComponent<T>
|
||||
{
|
||||
#if NET5_0_OR_GREATER
|
||||
/// <summary>
|
||||
/// Gets or sets a value that determines how many additional items will be rendered before and after the visible region. This help to reduce the frequency of rendering during scrolling. However, higher values mean that more elements will be present in the page.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public int VirtualizationOverscanCount { get; set; }
|
||||
|
||||
internal Microsoft.AspNetCore.Components.Web.Virtualization.Virtualize<object> virtualize;
|
||||
|
||||
/// <summary>
|
||||
@@ -85,6 +91,15 @@ namespace Radzen
|
||||
#endif
|
||||
}
|
||||
|
||||
internal int GetVirtualizationOverscanCount()
|
||||
{
|
||||
#if NET5_0_OR_GREATER
|
||||
return VirtualizationOverscanCount;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renders the items.
|
||||
/// </summary>
|
||||
@@ -106,6 +121,11 @@ namespace Radzen
|
||||
});
|
||||
}));
|
||||
|
||||
if(VirtualizationOverscanCount != default(int))
|
||||
{
|
||||
builder.AddAttribute(3, "OverscanCount", VirtualizationOverscanCount);
|
||||
}
|
||||
|
||||
builder.AddComponentReferenceCapture(7, c => { virtualize = (Microsoft.AspNetCore.Components.Web.Virtualization.Virtualize<object>)c; });
|
||||
|
||||
builder.CloseComponent();
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
@@ -30,6 +34,36 @@ namespace Radzen.Blazor
|
||||
return Enum.GetValues(enumType).Cast<Enum>().Distinct().Select(val => new { Value = Convert.ToInt32(val), Text = val.GetDisplayDescription() });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the autocomplete type enum value to the expected
|
||||
/// autocomplete attribute value.
|
||||
/// </summary>
|
||||
/// <returns>The autocomplete attribute string value.</returns>
|
||||
public static string GetAutoCompleteValue(this AutoCompleteType typeValue)
|
||||
{
|
||||
// Handle synonyms.
|
||||
switch (typeValue)
|
||||
{
|
||||
case AutoCompleteType.FirstName:
|
||||
return "given-name";
|
||||
case AutoCompleteType.LastName:
|
||||
return "family-name";
|
||||
case AutoCompleteType.MiddleName:
|
||||
return "additional-name";
|
||||
case AutoCompleteType.ZipCode:
|
||||
return "postal-code";
|
||||
case AutoCompleteType.Province:
|
||||
return "address-level1";
|
||||
case AutoCompleteType.State:
|
||||
return "address-level1";
|
||||
}
|
||||
|
||||
// Handle standard values.
|
||||
var value = typeValue.ToString();
|
||||
value = Regex.Replace(value, "([^A-Z])([A-Z])", "$1-$2");
|
||||
return Regex.Replace(value, "([A-Z]+)([A-Z][^A-Z$])", "$1-$2")
|
||||
.Trim().ToLower();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
13
Radzen.Blazor/IChartStackedBarSeries.cs
Normal file
13
Radzen.Blazor/IChartStackedBarSeries.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// Marker interface for <see cref="RadzenStackedBarSeries{TItem}" />.
|
||||
/// </summary>
|
||||
public interface IChartStackedBarSeries : IChartBarSeries
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the value at the specified index.
|
||||
/// </summary>
|
||||
double ValueAt(int index);
|
||||
}
|
||||
}
|
||||
19
Radzen.Blazor/IChartStackedColumnSeries.cs
Normal file
19
Radzen.Blazor/IChartStackedColumnSeries.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// Marker interface for <see cref="RadzenStackedColumnSeries{TItem}" />.
|
||||
/// </summary>
|
||||
public interface IChartStackedColumnSeries
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the count.
|
||||
/// </summary>
|
||||
/// <value>The count.</value>
|
||||
int Count { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value at the specified index.
|
||||
/// </summary>
|
||||
double ValueAt(int index);
|
||||
}
|
||||
}
|
||||
@@ -1048,7 +1048,7 @@ namespace Radzen
|
||||
|| c.FilterOperator == FilterOperator.IsEmpty || c.FilterOperator == FilterOperator.IsNotEmpty)
|
||||
&& c.Property != null;
|
||||
|
||||
if (dataFilter.Filters.Where(canFilter).Any())
|
||||
if (dataFilter.Filters.Concat(dataFilter.Filters.SelectManyRecursive(i => i.Filters ?? Enumerable.Empty<CompositeFilterDescriptor>())).Where(canFilter).Any())
|
||||
{
|
||||
var index = 0;
|
||||
var filterExpressions = new List<string>();
|
||||
@@ -1158,13 +1158,151 @@ namespace Radzen
|
||||
}
|
||||
else if (!(IsEnumerable(column.FilterPropertyType) && column.FilterPropertyType != typeof(string)))
|
||||
{
|
||||
var value = filter.FilterValue;
|
||||
|
||||
if (column.FilterPropertyType == typeof(DateTimeOffset) || column.FilterPropertyType == typeof(DateTimeOffset?))
|
||||
{
|
||||
value = filter.FilterValue != null ? (object)(new DateTimeOffset((DateTime)filter.FilterValue, TimeSpan.Zero)) : null;
|
||||
}
|
||||
|
||||
filterExpressions.Add($@"{property}{filterCaseSensitivityOperator} {comparison} @{index}{filterCaseSensitivityOperator}");
|
||||
filterValues.Add(new object[] { filter.FilterValue });
|
||||
filterValues.Add(new object[] { value });
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Converts to OData filter expression.
|
||||
/// </summary>
|
||||
/// <param name="dataFilter">The DataFilter.</param>
|
||||
/// <returns>System.String.</returns>
|
||||
public static string ToODataFilterString<T>(this RadzenDataFilter<T> dataFilter)
|
||||
{
|
||||
Func<CompositeFilterDescriptor, bool> canFilter = (c) => dataFilter.properties.Where(col => col.Property == c.Property).FirstOrDefault()?.FilterPropertyType != null &&
|
||||
(!(c.FilterValue == null || c.FilterValue as string == string.Empty)
|
||||
|| c.FilterOperator == FilterOperator.IsNotNull || c.FilterOperator == FilterOperator.IsNull
|
||||
|| c.FilterOperator == FilterOperator.IsEmpty || c.FilterOperator == FilterOperator.IsNotEmpty)
|
||||
&& c.Property != null;
|
||||
|
||||
if (dataFilter.Filters.Concat(dataFilter.Filters.SelectManyRecursive(i => i.Filters ?? Enumerable.Empty<CompositeFilterDescriptor>())).Where(canFilter).Any())
|
||||
{
|
||||
var filterExpressions = new List<string>();
|
||||
|
||||
foreach (var filter in dataFilter.Filters)
|
||||
{
|
||||
AddODataExpression(canFilter, filter, ref filterExpressions, dataFilter);
|
||||
}
|
||||
|
||||
return filterExpressions.Any() ?
|
||||
string.Join($" {dataFilter.LogicalFilterOperator.ToString().ToLower()} ", filterExpressions)
|
||||
: "";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private static void AddODataExpression<T>(Func<CompositeFilterDescriptor, bool> canFilter, CompositeFilterDescriptor filter, ref List<string> filterExpressions, RadzenDataFilter<T> dataFilter)
|
||||
{
|
||||
if (filter.Filters != null)
|
||||
{
|
||||
var innerFilterExpressions = new List<string>();
|
||||
|
||||
foreach (var f in filter.Filters)
|
||||
{
|
||||
AddODataExpression(canFilter, f, ref innerFilterExpressions, dataFilter);
|
||||
}
|
||||
|
||||
if (innerFilterExpressions.Any())
|
||||
{
|
||||
filterExpressions.Add("(" + string.Join($" {filter.LogicalFilterOperator.ToString().ToLower()} ", innerFilterExpressions) + ")");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (filter.Property == null || (filter.FilterValue == null &&
|
||||
filter.FilterOperator != FilterOperator.IsNull && filter.FilterOperator != FilterOperator.IsNotNull))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var property = filter.Property.Replace('.', '/');
|
||||
|
||||
var column = dataFilter.properties.Where(c => c.Property == filter.Property).FirstOrDefault();
|
||||
if (column == null) return;
|
||||
|
||||
if (dataFilter.FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive && column.FilterPropertyType == typeof(string))
|
||||
{
|
||||
property = $"tolower({property})";
|
||||
}
|
||||
|
||||
if (filter.FilterOperator == FilterOperator.StartsWith || filter.FilterOperator == FilterOperator.EndsWith
|
||||
|| filter.FilterOperator == FilterOperator.Contains || filter.FilterOperator == FilterOperator.DoesNotContain)
|
||||
{
|
||||
if (IsEnumerable(column.FilterPropertyType) && column.FilterPropertyType != typeof(string) &&
|
||||
(filter.FilterOperator == FilterOperator.Contains || filter.FilterOperator == FilterOperator.DoesNotContain))
|
||||
{
|
||||
var enumerableValue = ((IEnumerable)(filter.FilterValue != null ? filter.FilterValue : Enumerable.Empty<object>())).AsQueryable();
|
||||
|
||||
var enumerableValueAsString = "(" + String.Join(",",
|
||||
(enumerableValue.ElementType == typeof(string) ? enumerableValue.Cast<string>().Select(i => $@"'{i}'").Cast<object>() : enumerableValue.Cast<object>())) + ")";
|
||||
|
||||
if (enumerableValue.Any() && filter.FilterOperator == FilterOperator.Contains)
|
||||
{
|
||||
filterExpressions.Add($"{property} in {enumerableValueAsString}");
|
||||
}
|
||||
else if (enumerableValue.Any() && filter.FilterOperator == FilterOperator.DoesNotContain)
|
||||
{
|
||||
filterExpressions.Add($"not({property} in {enumerableValueAsString})");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var expression = dataFilter.FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ?
|
||||
$"{ODataFilterOperators[filter.FilterOperator]}({property}, tolower('{filter.FilterValue}'))" :
|
||||
$"{ODataFilterOperators[filter.FilterOperator]}({property}, '{filter.FilterValue}')";
|
||||
|
||||
if (filter.FilterOperator == FilterOperator.DoesNotContain)
|
||||
{
|
||||
expression = $"not({expression})";
|
||||
}
|
||||
|
||||
filterExpressions.Add(expression);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IsEnumerable(column.FilterPropertyType) && column.FilterPropertyType != typeof(string))
|
||||
return;
|
||||
|
||||
var value = $"{filter.FilterValue}";
|
||||
|
||||
if (filter.FilterOperator == FilterOperator.IsNull || filter.FilterOperator == FilterOperator.IsNotNull)
|
||||
{
|
||||
value = $"null";
|
||||
}
|
||||
else if (filter.FilterOperator == FilterOperator.IsEmpty || filter.FilterOperator == FilterOperator.IsNotEmpty)
|
||||
{
|
||||
value = $"''";
|
||||
}
|
||||
else if (column.FilterPropertyType == typeof(string))
|
||||
{
|
||||
value = $"'{value}'";
|
||||
}
|
||||
else if (column.FilterPropertyType == typeof(DateTime) || column.FilterPropertyType == typeof(DateTime?))
|
||||
{
|
||||
value = $"{DateTime.Parse(value, null, System.Globalization.DateTimeStyles.RoundtripKind).ToString("yyyy-MM-ddTHH:mm:ss.fffZ")}";
|
||||
}
|
||||
else if (column.FilterPropertyType == typeof(bool) || column.FilterPropertyType == typeof(bool?))
|
||||
{
|
||||
value = $"{value?.ToLower()}";
|
||||
}
|
||||
|
||||
filterExpressions.Add($@"{property} {ODataFilterOperators[filter.FilterOperator]} {value}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ases the o data enumerable.
|
||||
/// </summary>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<IsPackable>true</IsPackable>
|
||||
<PackageId>Radzen.Blazor</PackageId>
|
||||
<Product>Radzen.Blazor</Product>
|
||||
<Version>4.6.2</Version>
|
||||
<Version>4.7.8</Version>
|
||||
<Copyright>Radzen Ltd.</Copyright>
|
||||
<Authors>Radzen Ltd.</Authors>
|
||||
<Description>Radzen Blazor is a set of 70+ free native Blazor UI controls packed with DataGrid, Scheduler, Charts and robust theming including Material design and Fluent UI.</Description>
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
}
|
||||
@if (!string.IsNullOrEmpty(item.Text))
|
||||
{
|
||||
<span>@item.Text</span>
|
||||
<span>@((MarkupString)item.Text)</span>
|
||||
}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
var pathGenerator = GetPathGenerator();
|
||||
|
||||
var data = Items.Select(item =>
|
||||
var data = Items.Select(item =>
|
||||
{
|
||||
var x = category(item);
|
||||
var y = value(item);
|
||||
@@ -26,7 +26,7 @@
|
||||
var index = Chart.Series.IndexOf(this);
|
||||
var className = $"rz-area-series rz-series-{index}";
|
||||
|
||||
return
|
||||
return
|
||||
@<g class="@className">
|
||||
@if (Items.Any())
|
||||
{
|
||||
@@ -43,7 +43,7 @@
|
||||
<path @key="@area" style="@style" d="@area" fill="@Fill" stroke="none"></path>
|
||||
<Path @key="@line" D="@line" Stroke="@Stroke" StrokeWidth="@StrokeWidth" LineType="@LineType" Style="@style" Fill="none" />
|
||||
}
|
||||
<Markers Data="@Items" Category="@category" Value="@value" MarkerType="@MarkerType" Stroke="@Markers.Stroke" Fill="@(Markers.Fill ?? Stroke)" StrokeWidth="@Markers.StrokeWidth" Size="@Markers.Size" />
|
||||
<Markers Series="@this" Data="@Items" Category="@category" Value="@value" MarkerType="@MarkerType" Stroke="@Markers.Stroke" Fill="@(Markers.Fill ?? Stroke)" StrokeWidth="@Markers.StrokeWidth" Size="@Markers.Size" />
|
||||
</g>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,13 +42,13 @@ namespace Radzen.Blazor
|
||||
public ColorScheme ColorScheme { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A callback that will be invoked when the user clicks on a series.
|
||||
/// A callback that will be invoked when the user clicks on a series.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public EventCallback<SeriesClickEventArgs> SeriesClick { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A callback that will be invoked when the user clicks on a legend.
|
||||
/// A callback that will be invoked when the user clicks on a legend.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public EventCallback<LegendClickEventArgs> LegendClick { get; set; }
|
||||
@@ -311,7 +311,7 @@ namespace Radzen.Blazor
|
||||
tooltip = overlay.RenderTooltip(mouseX, mouseY, MarginLeft, MarginTop);
|
||||
chartTooltipContainer.Refresh();
|
||||
await Task.Yield();
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ namespace Radzen.Blazor
|
||||
|
||||
if (value == true)
|
||||
{
|
||||
Value = items.Select(i => i.Value);
|
||||
Value = allItems.Select(i => i.Value);
|
||||
}
|
||||
else if (value == false)
|
||||
{
|
||||
@@ -100,8 +100,8 @@ namespace Radzen.Blazor
|
||||
bool? IsAllSelected()
|
||||
{
|
||||
Func<RadzenCheckBoxListItem<TValue>, bool> predicate = i => Value != null && Value.Contains(i.Value);
|
||||
var all = items.All(predicate);
|
||||
var any = items.Any(predicate);
|
||||
var all = allItems.All(predicate);
|
||||
var any = allItems.Any(predicate);
|
||||
|
||||
if (all)
|
||||
{
|
||||
|
||||
@@ -349,7 +349,7 @@ namespace Radzen.Blazor
|
||||
|
||||
if (Disabled)
|
||||
{
|
||||
classList.Add("rz-disabled");
|
||||
classList.Add("rz-state-disabled");
|
||||
}
|
||||
|
||||
return string.Join(" ", classList);
|
||||
|
||||
@@ -42,7 +42,7 @@ else
|
||||
@if (property.FilterTemplate != null)
|
||||
{
|
||||
<div class="rz-datafilter-editor" style="display:flex">
|
||||
@property.FilterTemplate(property)
|
||||
@property.FilterTemplate(Filter)
|
||||
</div>
|
||||
}
|
||||
else if (PropertyAccess.IsNullableEnum(property.FilterPropertyType) || PropertyAccess.IsEnum(property.FilterPropertyType))
|
||||
@@ -250,15 +250,7 @@ else
|
||||
{
|
||||
if (property != null && !string.IsNullOrEmpty(property.FormatString))
|
||||
{
|
||||
var formats = property.FormatString.Split(new char[] { '{', '}' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
if (formats.Length > 0)
|
||||
{
|
||||
var format = formats[0].Trim().Split(':');
|
||||
if (format.Length > 1)
|
||||
{
|
||||
return format[1].Trim();
|
||||
}
|
||||
}
|
||||
return property.FormatString.Replace("{0:", "").Replace("}", "");
|
||||
}
|
||||
|
||||
return DataFilter.FilterDateFormat;
|
||||
|
||||
@@ -130,7 +130,7 @@ namespace Radzen.Blazor
|
||||
/// </summary>
|
||||
/// <value>The filter template.</value>
|
||||
[Parameter]
|
||||
public RenderFragment<RadzenDataFilterProperty<TItem>> FilterTemplate { get; set; }
|
||||
public RenderFragment<CompositeFilterDescriptor> FilterTemplate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the data type.
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
|
||||
@if (AllowPaging && (PagerPosition == PagerPosition.Top || PagerPosition == PagerPosition.TopAndBottom))
|
||||
{
|
||||
<RadzenPager HorizontalAlign="@PagerHorizontalAlign" AlwaysVisible="@PagerAlwaysVisible" @ref="topPager" Count="@Count" PageSize="@PageSize" PageNumbersCount="@PageNumbersCount" PageChanged="@ChangePage" PageSizeChanged="@OnPageSizeChanged" PageSizeOptions="@PageSizeOptions" ShowPagingSummary="@ShowPagingSummary" PagingSummaryFormat="@PagingSummaryFormat" PageSizeText="@PageSizeText" />
|
||||
<RadzenPager HorizontalAlign="@PagerHorizontalAlign" AlwaysVisible="@PagerAlwaysVisible" @ref="topPager" Count="@Count" PageSize="@PageSize" PageNumbersCount="@PageNumbersCount" PageChanged="@ChangePage" PageSizeChanged="@OnPageSizeChanged" PageSizeOptions="@PageSizeOptions" ShowPagingSummary="@ShowPagingSummary" PagingSummaryFormat="@PagingSummaryFormat" PageSizeText="@PageSizeText" Density="@Density" />
|
||||
}
|
||||
|
||||
<div class="rz-data-grid-data">
|
||||
@@ -231,7 +231,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<RadzenDatePicker TValue="@object"
|
||||
<RadzenDatePicker TValue="@object" AllowInput=@(AllowFilterDateInput)
|
||||
ShowTime="@column.ShowTimeForDateTimeFilter()" ShowTimeOkButton="false" Inline="true" DateFormat="@getFilterDateFormat(column)"
|
||||
Value="@column.GetFilterValue()" Change="@(args => { column.SetFilterValue(args.Value); SaveSettings(); })" />
|
||||
|
||||
@@ -251,7 +251,7 @@
|
||||
else
|
||||
{
|
||||
<RadzenDataGridFilterMenu Grid="@this" Column="@column" />
|
||||
<RadzenDatePicker Disabled=@column.CanSetFilterValue() TValue="@object" Style="width:100%" AllowInput="false" AllowClear="true"
|
||||
<RadzenDatePicker Disabled=@column.CanSetFilterValue() TValue="@object" Style="width:100%" AllowInput=@(AllowFilterDateInput) AllowClear="true"
|
||||
ShowTime="false" ShowTimeOkButton="false" DateFormat="@getFilterDateFormat(column)"
|
||||
Value="@column.GetFilterValue()" Change="@(args => { if(!args.HasValue) { ClearFilter(column, true); } else {column.SetFilterValue(args.Value); ApplyFilter(column, true);} })" />
|
||||
}
|
||||
@@ -378,7 +378,7 @@
|
||||
|
||||
@if (AllowPaging && (PagerPosition == PagerPosition.Bottom || PagerPosition == PagerPosition.TopAndBottom))
|
||||
{
|
||||
<RadzenPager HorizontalAlign="@PagerHorizontalAlign" AlwaysVisible="@PagerAlwaysVisible" @ref="bottomPager" Count="@Count" PageSize="@PageSize" PageNumbersCount="@PageNumbersCount" PageChanged="@ChangePage" PageSizeChanged="@OnPageSizeChanged" PageSizeOptions="@PageSizeOptions" ShowPagingSummary="@ShowPagingSummary" PagingSummaryFormat="@PagingSummaryFormat" PageSizeText="@PageSizeText" />
|
||||
<RadzenPager HorizontalAlign="@PagerHorizontalAlign" AlwaysVisible="@PagerAlwaysVisible" @ref="bottomPager" Count="@Count" PageSize="@PageSize" PageNumbersCount="@PageNumbersCount" PageChanged="@ChangePage" PageSizeChanged="@OnPageSizeChanged" PageSizeOptions="@PageSizeOptions" ShowPagingSummary="@ShowPagingSummary" PagingSummaryFormat="@PagingSummaryFormat" PageSizeText="@PageSizeText" Density="@Density" />
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -31,6 +31,19 @@ namespace Radzen.Blazor
|
||||
public partial class RadzenDataGrid<TItem> : PagedDataBoundComponent<TItem>
|
||||
{
|
||||
#if NET5_0_OR_GREATER
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance is virtualized.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance is virtualized; otherwise, <c>false</c>.</value>
|
||||
[Parameter]
|
||||
public bool AllowVirtualization { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value that determines how many additional items will be rendered before and after the visible region. This help to reduce the frequency of rendering during scrolling. However, higher values mean that more elements will be present in the page.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public int VirtualizationOverscanCount { get; set; }
|
||||
|
||||
internal void SetAllowVirtualization(bool allowVirtualization)
|
||||
{
|
||||
AllowVirtualization = allowVirtualization;
|
||||
@@ -134,7 +147,7 @@ namespace Radzen.Blazor
|
||||
b.AddAttribute(8, "InEditMode", IsRowInEditMode(context));
|
||||
b.AddAttribute(9, "Index", virtualDataItems.IndexOf(context));
|
||||
|
||||
if (editContexts.ContainsKey(context))
|
||||
if (editContexts.Keys.Any(i => ItemEquals(i, context)))
|
||||
{
|
||||
b.AddAttribute(10, nameof(RadzenDataGridRow<TItem>.EditContext), editContexts[context]);
|
||||
}
|
||||
@@ -144,6 +157,11 @@ namespace Radzen.Blazor
|
||||
});
|
||||
}));
|
||||
|
||||
if(VirtualizationOverscanCount != default(int))
|
||||
{
|
||||
builder.AddAttribute(1, "OverscanCount", VirtualizationOverscanCount);
|
||||
}
|
||||
|
||||
builder.AddComponentReferenceCapture(8, c => { virtualize = (Microsoft.AspNetCore.Components.Web.Virtualization.Virtualize<TItem>)c; });
|
||||
|
||||
}
|
||||
@@ -484,15 +502,7 @@ namespace Radzen.Blazor
|
||||
{
|
||||
if (column != null && !string.IsNullOrEmpty(column.FormatString))
|
||||
{
|
||||
var formats = column.FormatString.Split(new char[] { '{', '}' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
if (formats.Length > 0)
|
||||
{
|
||||
var format = formats[0].Trim().Split(':');
|
||||
if (format.Length > 1)
|
||||
{
|
||||
return format[1].Trim();
|
||||
}
|
||||
}
|
||||
return column.FormatString.Replace("{0:", "").Replace("}", "");
|
||||
}
|
||||
|
||||
return FilterDateFormat;
|
||||
@@ -665,6 +675,13 @@ namespace Radzen.Blazor
|
||||
[Parameter]
|
||||
public EventCallback<DataGridColumnFilterEventArgs<TItem>> FilterCleared { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the render mode.
|
||||
/// </summary>
|
||||
/// <value>The render mode.</value>
|
||||
[Parameter]
|
||||
public PopupRenderMode FilterPopupRenderMode { get; set; } = PopupRenderMode.Initial;
|
||||
|
||||
internal async Task ClearFilter(RadzenDataGridColumn<TItem> column, bool closePopup = false)
|
||||
{
|
||||
if (closePopup)
|
||||
@@ -964,6 +981,13 @@ namespace Radzen.Blazor
|
||||
[Parameter]
|
||||
public string FilterDateFormat { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether input is allowed in filter DatePicker.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if input is allowed in filter DatePicker; otherwise, <c>false</c>.</value>
|
||||
[Parameter]
|
||||
public bool AllowFilterDateInput { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the width of all columns.
|
||||
/// </summary>
|
||||
@@ -995,14 +1019,7 @@ namespace Radzen.Blazor
|
||||
/// <value>The empty template.</value>
|
||||
[Parameter]
|
||||
public RenderFragment EmptyTemplate { get; set; }
|
||||
#if NET5_0_OR_GREATER
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance is virtualized.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance is virtualized; otherwise, <c>false</c>.</value>
|
||||
[Parameter]
|
||||
public bool AllowVirtualization { get; set; }
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance loading indicator is shown.
|
||||
/// </summary>
|
||||
@@ -1511,6 +1528,11 @@ namespace Radzen.Blazor
|
||||
/// </summary>
|
||||
protected override void OnDataChanged()
|
||||
{
|
||||
if (!string.IsNullOrEmpty(KeyProperty) && keyPropertyGetter == null)
|
||||
{
|
||||
keyPropertyGetter = PropertyAccess.Getter<TItem, object>(KeyProperty);
|
||||
}
|
||||
|
||||
Reset(!IsOData() && !LoadData.HasDelegate);
|
||||
|
||||
if (!IsOData() && !LoadData.HasDelegate && !Page.HasDelegate)
|
||||
@@ -1551,7 +1573,10 @@ namespace Radzen.Blazor
|
||||
sorts.Clear();
|
||||
}
|
||||
|
||||
SaveSettings();
|
||||
if (!LoadData.HasDelegate)
|
||||
{
|
||||
SaveSettings();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1704,6 +1729,19 @@ namespace Radzen.Blazor
|
||||
[Parameter]
|
||||
public EventCallback<bool?> AllGroupsExpandedChanged { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the key property.
|
||||
/// </summary>
|
||||
/// <value>The key property.</value>
|
||||
[Parameter]
|
||||
public string KeyProperty { get; set; }
|
||||
|
||||
internal Func<TItem, object> keyPropertyGetter;
|
||||
bool ItemEquals(TItem item, TItem otherItem)
|
||||
{
|
||||
return keyPropertyGetter != null ? keyPropertyGetter(item).Equals(keyPropertyGetter(otherItem)) : item.Equals(otherItem);
|
||||
}
|
||||
|
||||
internal bool? allGroupsExpanded;
|
||||
|
||||
internal async System.Threading.Tasks.Task ExpandGroupItem(RadzenDataGridGroupRow<TItem> item, bool? expandedOnLoad)
|
||||
@@ -1732,7 +1770,7 @@ namespace Radzen.Blazor
|
||||
|
||||
internal string ExpandedItemStyle(TItem item)
|
||||
{
|
||||
return expandedItems.Keys.Contains(item) ? "rz-row-toggler rzi-chevron-circle-down" : "rz-row-toggler rzi-chevron-circle-right";
|
||||
return expandedItems.Keys.Any(i => ItemEquals(i, item)) ? "rz-row-toggler rzi-chevron-circle-down" : "rz-row-toggler rzi-chevron-circle-right";
|
||||
}
|
||||
|
||||
internal Dictionary<TItem, bool> selectedItems = new Dictionary<TItem, bool>();
|
||||
@@ -1741,7 +1779,7 @@ namespace Radzen.Blazor
|
||||
{
|
||||
var isInEditMode = IsRowInEditMode(item) ? "rz-datatable-edit" : "";
|
||||
|
||||
return (RowSelect.HasDelegate || ValueChanged.HasDelegate || SelectionMode == DataGridSelectionMode.Multiple) && selectedItems.Keys.Contains(item) ? $"rz-state-highlight rz-data-row {isInEditMode} " : $"rz-data-row {isInEditMode} ";
|
||||
return (RowSelect.HasDelegate || ValueChanged.HasDelegate || SelectionMode == DataGridSelectionMode.Multiple) && selectedItems.Keys.Any(i => ItemEquals(i, item)) ? $"rz-state-highlight rz-data-row {isInEditMode} " : $"rz-data-row {isInEditMode} ";
|
||||
}
|
||||
|
||||
internal Tuple<Radzen.RowRenderEventArgs<TItem>, IReadOnlyDictionary<string, object>> RowAttributes(TItem item)
|
||||
@@ -1875,6 +1913,61 @@ namespace Radzen.Blazor
|
||||
await ExpandItem(item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Expands a range of rows.
|
||||
/// </summary>
|
||||
/// <param name="items">The range of rows.</param>
|
||||
public async System.Threading.Tasks.Task ExpandRows(IEnumerable<TItem> items)
|
||||
{
|
||||
// Only allow the functionality when multiple row expand is allowed
|
||||
if (this.ExpandMode != DataGridExpandMode.Multiple) return;
|
||||
|
||||
foreach (TItem item in items)
|
||||
{
|
||||
if (!expandedItems.Keys.Any(i => ItemEquals(i, item)))
|
||||
{
|
||||
expandedItems.Add(item, true);
|
||||
await RowExpand.InvokeAsync(item);
|
||||
|
||||
var args = new DataGridLoadChildDataEventArgs<TItem>() { Item = item };
|
||||
await LoadChildData.InvokeAsync(args);
|
||||
|
||||
if (args.Data != null && !childData.ContainsKey(item))
|
||||
{
|
||||
childData.Add(item, new DataGridChildData<TItem>() { Data = args.Data, ParentChildData = childData.Where(c => c.Value.Data.Contains(item)).Select(c => c.Value).FirstOrDefault() });
|
||||
_view = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Collapse a range of rows.
|
||||
/// </summary>
|
||||
/// <param name="items">The range of rows.</param>
|
||||
public async System.Threading.Tasks.Task CollapseRows(IEnumerable<TItem> items)
|
||||
{
|
||||
// Only allow the functionality when multiple row expand is allowed
|
||||
if (this.ExpandMode != DataGridExpandMode.Multiple) return;
|
||||
|
||||
foreach (TItem item in items)
|
||||
{
|
||||
if (expandedItems.Keys.Any(i => ItemEquals(i, item)))
|
||||
{
|
||||
expandedItems.Remove(item);
|
||||
await RowCollapse.InvokeAsync(item);
|
||||
|
||||
if (childData.ContainsKey(item))
|
||||
{
|
||||
childData.Remove(item);
|
||||
_view = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
|
||||
internal async System.Threading.Tasks.Task ExpandItem(TItem item)
|
||||
{
|
||||
if (ExpandMode == DataGridExpandMode.Single && expandedItems.Keys.Any() && !LoadChildData.HasDelegate)
|
||||
@@ -1893,7 +1986,7 @@ namespace Radzen.Blazor
|
||||
}
|
||||
}
|
||||
|
||||
if (!expandedItems.Keys.Contains(item))
|
||||
if (!expandedItems.Keys.Any(i => ItemEquals(i, item)))
|
||||
{
|
||||
expandedItems.Add(item, true);
|
||||
await RowExpand.InvokeAsync(item);
|
||||
@@ -1996,9 +2089,9 @@ namespace Radzen.Blazor
|
||||
}
|
||||
}
|
||||
|
||||
internal async System.Threading.Tasks.Task OnRowSelect(object item, bool raiseChange = true)
|
||||
internal async System.Threading.Tasks.Task OnRowSelect(TItem item, bool raiseChange = true)
|
||||
{
|
||||
if (SelectionMode == DataGridSelectionMode.Single && item != null && selectedItems.Keys.Contains((TItem)item))
|
||||
if (SelectionMode == DataGridSelectionMode.Single && item != null && selectedItems.Keys.Any(i => ItemEquals(i, item)))
|
||||
{
|
||||
// Legacy RowSelect raise
|
||||
if (raiseChange)
|
||||
@@ -2020,7 +2113,7 @@ namespace Radzen.Blazor
|
||||
|
||||
if (item != null)
|
||||
{
|
||||
if (!selectedItems.Keys.Contains((TItem)item))
|
||||
if (!selectedItems.Keys.Any(i => ItemEquals(i, item)))
|
||||
{
|
||||
selectedItems.Add((TItem)item, true);
|
||||
if (raiseChange)
|
||||
@@ -2118,7 +2211,7 @@ namespace Radzen.Blazor
|
||||
}
|
||||
}
|
||||
|
||||
if (!editedItems.Keys.Contains(item))
|
||||
if (!editedItems.Keys.Any(i => ItemEquals(i, item)))
|
||||
{
|
||||
editedItems.Add(item, true);
|
||||
|
||||
@@ -2131,13 +2224,37 @@ namespace Radzen.Blazor
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Edits a range of rows.
|
||||
/// </summary>
|
||||
/// <param name="items">The range of rows.</param>
|
||||
public async System.Threading.Tasks.Task EditRows(IEnumerable<TItem> items)
|
||||
{
|
||||
// Only allow the functionality when multiple row edits is allowed
|
||||
if (this.EditMode != DataGridEditMode.Multiple) return;
|
||||
|
||||
foreach (TItem item in items)
|
||||
{
|
||||
if (!editedItems.Keys.Any(i => ItemEquals(i, item)))
|
||||
{
|
||||
editedItems.Add(item, true);
|
||||
|
||||
var editContext = new EditContext(item);
|
||||
editContexts.Add(item, editContext);
|
||||
|
||||
await RowEdit.InvokeAsync(item);
|
||||
}
|
||||
}
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the row.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
public async System.Threading.Tasks.Task UpdateRow(TItem item)
|
||||
{
|
||||
if (editedItems.Keys.Contains(item))
|
||||
if (editedItems.Keys.Any(i => ItemEquals(i, item)))
|
||||
{
|
||||
var editContext = editContexts[item];
|
||||
|
||||
@@ -2198,7 +2315,7 @@ namespace Radzen.Blazor
|
||||
{
|
||||
int hash = item.GetHashCode();
|
||||
|
||||
if (editedItems.Keys.Contains(item))
|
||||
if (editedItems.Keys.Any(i => ItemEquals(i, item)))
|
||||
{
|
||||
editedItems.Remove(item);
|
||||
editContexts.Remove(item);
|
||||
@@ -2208,6 +2325,23 @@ namespace Radzen.Blazor
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cancels the edit of a range of rows.
|
||||
/// </summary>
|
||||
/// <param name="items">The range of rows.</param>
|
||||
public void CancelEditRows(IEnumerable<TItem> items)
|
||||
{
|
||||
foreach (TItem item in items)
|
||||
{
|
||||
if (editedItems.Keys.Any(i => ItemEquals(i, item)))
|
||||
{
|
||||
editedItems.Remove(item);
|
||||
editContexts.Remove(item);
|
||||
}
|
||||
}
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether row in edit mode.
|
||||
/// </summary>
|
||||
@@ -2215,7 +2349,7 @@ namespace Radzen.Blazor
|
||||
/// <returns><c>true</c> if row in edit mode; otherwise, <c>false</c>.</returns>
|
||||
public bool IsRowInEditMode(TItem item)
|
||||
{
|
||||
return editedItems.Keys.Contains(item);
|
||||
return editedItems.Keys.Any(i => ItemEquals(i, item));
|
||||
}
|
||||
|
||||
TItem itemToInsert;
|
||||
|
||||
@@ -169,7 +169,7 @@ namespace Radzen.Blazor
|
||||
if (visible != value)
|
||||
{
|
||||
visible = value;
|
||||
|
||||
_visible = visible;
|
||||
if (Grid != null)
|
||||
{
|
||||
Grid.UpdatePickableColumn(this, visible);
|
||||
@@ -707,6 +707,32 @@ namespace Radzen.Blazor
|
||||
}
|
||||
}
|
||||
|
||||
if (parameters.DidParameterChange(nameof(SecondFilterValue), SecondFilterValue))
|
||||
{
|
||||
secondFilterValue = parameters.GetValueOrDefault<object>(nameof(SecondFilterValue));
|
||||
|
||||
if (FilterTemplate != null)
|
||||
{
|
||||
SecondFilterValue = secondFilterValue;
|
||||
Grid.SaveSettings();
|
||||
if (Grid.IsVirtualizationAllowed())
|
||||
{
|
||||
#if NET5_0_OR_GREATER
|
||||
if (Grid.virtualize != null)
|
||||
{
|
||||
await Grid.virtualize.RefreshDataAsync();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
await Grid.Reload();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (parameters.DidParameterChange(nameof(FilterOperator), FilterOperator))
|
||||
{
|
||||
filterOperator = parameters.GetValueOrDefault<FilterOperator>(nameof(FilterOperator));
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
@typeparam TItem
|
||||
@using Radzen.Blazor.Rendering
|
||||
@if (RowIndex == Column.GetLevel())
|
||||
{
|
||||
<th rowspan="@(Column.GetRowSpan())" colspan="@(Column.GetColSpan())" @attributes="@Attributes" class="@CssClass" scope="col" style="@Column.GetStyle(true, true)" @onmouseup=@(args => Grid.EndColumnReorder(args, ColumnIndex)) >
|
||||
@@ -53,18 +54,19 @@
|
||||
}
|
||||
@if (Grid.AllowFiltering && Column.Filterable && Grid.FilterMode == FilterMode.Advanced)
|
||||
{
|
||||
<i @onclick:stopPropagation="true" onclick="@($"Radzen.togglePopup(this, '{getColumnPopupID()}')")"
|
||||
class="@getFilterIconCss(Column)" />
|
||||
<i @ref=@filterButton @onclick:stopPropagation="true" @onmousedown=@ToggleFilter
|
||||
class="@getFilterIconCss(Column)" onclick=@getFilterOpen() />
|
||||
|
||||
<div id="@($"{getColumnPopupID()}")" class="rz-overlaypanel"
|
||||
<Popup Lazy=@(Grid.FilterPopupRenderMode == PopupRenderMode.OnDemand) @ref=popup id="@($"{getColumnPopupID()}")" class="rz-overlaypanel"
|
||||
style="display:none;min-width:250px;" tabindex="0">
|
||||
<div class="rz-grid-filter rz-overlaypanel-content">
|
||||
<div class="rz-overlaypanel-content">
|
||||
@if (Column.FilterTemplate != null)
|
||||
{
|
||||
@Column.FilterTemplate(Column)
|
||||
}
|
||||
else
|
||||
{
|
||||
<form id="@($"{getColumnPopupID()}-form")" @onsubmit="@(args => ApplyFilter())" class="rz-grid-filter">
|
||||
<RadzenLabel Text="@Grid.FilterText" class="rz-grid-filter-label" />
|
||||
<RadzenDropDown @onclick:preventDefault="true" Data="@(Column.GetFilterOperators().Select(t => new { Value = Column.GetFilterOperatorText(t), Key = t }))" TextProperty="Value" ValueProperty="Key" TValue="FilterOperator" Value="@Column.GetFilterOperator()" Change="@(args => Column.SetFilterOperator((FilterOperator)args))" />
|
||||
@if (PropertyAccess.IsNullableEnum(Column.FilterPropertyType) || PropertyAccess.IsEnum(Column.FilterPropertyType))
|
||||
@@ -80,7 +82,7 @@
|
||||
else if (PropertyAccess.IsDate(Column.FilterPropertyType))
|
||||
{
|
||||
<RadzenDatePicker TValue="@object" ShowTime="true" ShowTimeOkButton="true" DateFormat="@Grid.getFilterDateFormat(Column)"
|
||||
Value="@Column.GetFilterValue()" Change="@(args => Column.SetFilterValue(args.Value))" />
|
||||
Value="@Column.GetFilterValue()" Change="@(args => Column.SetFilterValue(args.Value))" AllowInput=@(Grid.AllowFilterDateInput) />
|
||||
|
||||
}
|
||||
else if (Column.FilterPropertyType == typeof(bool) || Column.FilterPropertyType == typeof(bool?))
|
||||
@@ -110,27 +112,28 @@
|
||||
{
|
||||
<RadzenDatePicker TValue="@object"
|
||||
ShowTime="@Column.ShowTimeForDateTimeFilter()" ShowTimeOkButton="true" DateFormat="@Grid.getFilterDateFormat(Column)"
|
||||
Value="@Column.GetSecondFilterValue()" Change="@(args => Column.SetFilterValue(args.Value, false))" />
|
||||
Value="@Column.GetSecondFilterValue()" Change="@(args => Column.SetFilterValue(args.Value, false))" AllowInput=@(Grid.AllowFilterDateInput) />
|
||||
|
||||
}
|
||||
else if (Column.FilterPropertyType == typeof(bool) || Column.FilterPropertyType == typeof(bool?))
|
||||
{
|
||||
<RadzenCheckBox TriState="true" TValue="@object" Value="@Column.GetSecondFilterValue()" Change="@(args => { Column.SetFilterValue(args, false); Grid.SaveSettings(); })" />
|
||||
<RadzenCheckBox TriState="true" TValue="@object" Value="@Column.GetSecondFilterValue()" Change="@(args => { Column.SetFilterValue(args, false); Grid.SaveSettings(); })" />
|
||||
}
|
||||
else
|
||||
{
|
||||
<RadzenTextBox Value="@($"{Column.GetSecondFilterValue()}")" Change="@(args => Column.SetFilterValue(args, false))" />
|
||||
}
|
||||
</form>
|
||||
}
|
||||
</div>
|
||||
@if (Column.FilterTemplate == null)
|
||||
{
|
||||
<div class="rz-grid-filter-buttons">
|
||||
<RadzenButton ButtonStyle="ButtonStyle.Secondary" Text=@Grid.ClearFilterText Click="@((args) => Grid.ClearFilter(Column, true))" />
|
||||
<RadzenButton ButtonStyle="ButtonStyle.Primary" Text=@Grid.ApplyFilterText Click="@((args) => Grid.ApplyFilter(Column, true))" />
|
||||
<RadzenButton ButtonStyle="ButtonStyle.Secondary" Text=@Grid.ClearFilterText Click="@ClearFilter" />
|
||||
<RadzenButton form="@($"{getColumnPopupID()}-form")" ButtonType="ButtonType.Submit" ButtonStyle="ButtonStyle.Primary" Text=@Grid.ApplyFilterText Click="@ApplyFilter" />
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</Popup>
|
||||
}
|
||||
</div>
|
||||
</th>
|
||||
@@ -144,6 +147,40 @@ else
|
||||
}
|
||||
}
|
||||
@code {
|
||||
Radzen.Blazor.Rendering.Popup popup;
|
||||
ElementReference filterButton;
|
||||
|
||||
string getFilterOpen()
|
||||
{
|
||||
return Grid.FilterPopupRenderMode == PopupRenderMode.Initial ? $"Radzen.togglePopup(this, '{getColumnPopupID()}')" : "";
|
||||
}
|
||||
|
||||
async Task ToggleFilter()
|
||||
{
|
||||
if (Grid.FilterPopupRenderMode == PopupRenderMode.OnDemand)
|
||||
{
|
||||
await popup.ToggleAsync(filterButton);
|
||||
}
|
||||
}
|
||||
|
||||
async Task ClearFilter()
|
||||
{
|
||||
if (Grid.FilterPopupRenderMode == PopupRenderMode.OnDemand)
|
||||
{
|
||||
await popup.CloseAsync();
|
||||
}
|
||||
await Grid.ClearFilter(Column, true);
|
||||
}
|
||||
|
||||
async Task ApplyFilter()
|
||||
{
|
||||
if (Grid.FilterPopupRenderMode == PopupRenderMode.OnDemand)
|
||||
{
|
||||
await popup.CloseAsync();
|
||||
}
|
||||
await Grid.ApplyFilter(Column, true);
|
||||
}
|
||||
|
||||
[Parameter(CaptureUnmatchedValues = true)]
|
||||
public IReadOnlyDictionary<string, object> Attributes { get; set; }
|
||||
|
||||
|
||||
@@ -547,6 +547,10 @@ namespace Radzen.Blazor
|
||||
DateTimeOffset? offset = DateTime.SpecifyKind((DateTime)Value, Kind);
|
||||
await ValueChanged.InvokeAsync((TValue)(object)offset);
|
||||
}
|
||||
else if ((typeof(TValue) == typeof(DateTime) || typeof(TValue) == typeof(DateTime?)) && Value != null)
|
||||
{
|
||||
await ValueChanged.InvokeAsync((TValue)(object)DateTime.SpecifyKind((DateTime)Value, Kind));
|
||||
}
|
||||
else
|
||||
{
|
||||
await ValueChanged.InvokeAsync((TValue)Value);
|
||||
|
||||
@@ -25,26 +25,27 @@
|
||||
|
||||
return @<div style="position: absolute;left: @(left)px;top: @(top)px;width: @(width.ToInvariantString())px; height: @(height.ToInvariantString())px;">
|
||||
@TitleTemplate
|
||||
</div>;
|
||||
}
|
||||
</div>
|
||||
;
|
||||
}
|
||||
|
||||
public override RenderFragment Render(ScaleBase categoryScale, ScaleBase valueScale)
|
||||
{
|
||||
public override RenderFragment Render(ScaleBase categoryScale, ScaleBase valueScale)
|
||||
{
|
||||
var className = $"rz-donut-series rz-series-{Chart.Series.IndexOf(this)}";
|
||||
var x = CenterX;
|
||||
var y = CenterY;
|
||||
var radius = CurrentRadius;
|
||||
var innerRadius = InnerRadius ?? radius / 2;
|
||||
|
||||
return
|
||||
return
|
||||
@<g>
|
||||
<g class="@className">
|
||||
@if (Items.Any())
|
||||
@if (PositiveItems.Any())
|
||||
{
|
||||
var sum = Items.Sum(Value);
|
||||
var sum = PositiveItems.Sum(Value);
|
||||
double startAngle = -90;
|
||||
|
||||
@foreach(var data in Items)
|
||||
@foreach (var data in PositiveItems)
|
||||
{
|
||||
var value = Value(data);
|
||||
var angle = (value / sum) * 360;
|
||||
@@ -53,7 +54,7 @@
|
||||
var d = Segment(x, y, radius, innerRadius, startAngle, endAngle);
|
||||
|
||||
startAngle = endAngle;
|
||||
|
||||
|
||||
var index = Items.IndexOf(data);
|
||||
var arcClassName = $"rz-series-item-{index}";
|
||||
var fill = PickColor(index, Fills);
|
||||
@@ -64,8 +65,18 @@
|
||||
</g>
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var arcClassName = $"rz-series-item-0";
|
||||
var d = Segment(x, y, radius, radius - 1, -90, 270);
|
||||
var fill = PickColor(0, Fills);
|
||||
var stroke = PickColor(0, Strokes);
|
||||
<g class="@arcClassName">
|
||||
<Path D="@d" Fill="@fill" StrokeWidth="@StrokeWidth" Stroke="@stroke" />
|
||||
</g>
|
||||
}
|
||||
</g>
|
||||
|
||||
|
||||
@if (!string.IsNullOrEmpty(Title) && TitleTemplate == null)
|
||||
{
|
||||
<g class="rz-donut-title">
|
||||
|
||||
@@ -42,7 +42,14 @@
|
||||
{
|
||||
<div class="rz-chip">
|
||||
<span class="rz-chip-text">
|
||||
@GetItemOrValueFromProperty(item, TextProperty)
|
||||
@if(Template != null)
|
||||
{
|
||||
@Template(item)
|
||||
}
|
||||
else
|
||||
{
|
||||
@GetItemOrValueFromProperty(item, TextProperty)
|
||||
}
|
||||
</span>
|
||||
<button type=button class="rz-button rz-button-sm rz-button-icon-only rz-light @(Disabled ?"rz-state-disabled":"")" @onclick:preventDefault @onclick:stopPropagation @onclick="() => OnChipRemove(item)"><RadzenIcon Icon="close" /></button>
|
||||
</div>
|
||||
|
||||
@@ -46,7 +46,14 @@
|
||||
{
|
||||
<div class="rz-chip">
|
||||
<span class="rz-chip-text">
|
||||
@PropertyAccess.GetItemOrValueFromProperty(item, TextProperty)
|
||||
@if (Template != null)
|
||||
{
|
||||
@Template(item)
|
||||
}
|
||||
else
|
||||
{
|
||||
@PropertyAccess.GetItemOrValueFromProperty(item, TextProperty)
|
||||
}
|
||||
</span>
|
||||
<button type="button" class="rz-button rz-button-sm rz-button-icon-only rz-light @(Disabled ?"rz-state-disabled":"")" @onclick:preventDefault @onclick:stopPropagation @onclick="() => OnChipRemove(item)"><RadzenIcon Icon="close" /></button>
|
||||
</div>
|
||||
@@ -118,8 +125,8 @@
|
||||
}
|
||||
@if (Template != null)
|
||||
{
|
||||
<RadzenDataGrid AllowRowSelectOnRowClick="@AllowRowSelectOnRowClick" PagerHorizontalAlign="@PagerHorizontalAlign" PagerAlwaysVisible="@PagerAlwaysVisible" Responsive="@Responsive" AllowColumnResize="@AllowColumnResize" ColumnWidth="@ColumnWidth" @ref="grid" Data="@(LoadData.HasDelegate ? (Data != null ? Data.Cast<object>() : Enumerable.Empty<object>()) : pagedData)" Count="@(LoadData.HasDelegate ? Count : count)" LoadData="@OnLoadData"
|
||||
TItem="object" CellRender="@OnCellRender" RowRender="@OnRowRender" ShowPagingSummary="@ShowPagingSummary" PagingSummaryFormat="@PagingSummaryFormat" PageSize="@PageSize" PageNumbersCount="@PageNumbersCount" AllowPaging="@(!IsVirtualizationAllowed())" AllowSorting="@AllowSorting" RowSelect="@OnRowSelect" Style="@(IsVirtualizationAllowed() ? "height:285px" : "")">
|
||||
<RadzenDataGrid VirtualizationOverscanCount="@GetVirtualizationOverscanCount()" AllowRowSelectOnRowClick="@AllowRowSelectOnRowClick" PagerHorizontalAlign="@PagerHorizontalAlign" PagerAlwaysVisible="@PagerAlwaysVisible" Responsive="@Responsive" AllowColumnResize="@AllowColumnResize" ColumnWidth="@ColumnWidth" @ref="grid" Data="@(LoadData.HasDelegate ? (Data != null ? Data.Cast<object>() : Enumerable.Empty<object>()) : pagedData)" Count="@(LoadData.HasDelegate ? Count : count)" LoadData="@OnLoadData"
|
||||
TItem="object" CellRender="@OnCellRender" RowRender="@OnRowRender" ShowPagingSummary="@ShowPagingSummary" PagingSummaryFormat="@PagingSummaryFormat" PageSize="@PageSize" PageNumbersCount="@PageNumbersCount" AllowPaging="@(!IsVirtualizationAllowed())" AllowSorting="@AllowSorting" RowSelect="@OnRowSelect" Style="@(IsVirtualizationAllowed() ? "height:285px" : "")" Density="@Density">
|
||||
<Columns>
|
||||
<RadzenDataGridColumn TItem="object" Property="@TextProperty" Title="@TextProperty" Type="typeof(string)">
|
||||
<Template>
|
||||
@@ -136,8 +143,8 @@
|
||||
{
|
||||
if (!string.IsNullOrEmpty(TextProperty) || Columns != null)
|
||||
{
|
||||
<RadzenDataGrid AllowRowSelectOnRowClick="@AllowRowSelectOnRowClick" PagerHorizontalAlign="@PagerHorizontalAlign" PagerAlwaysVisible="@PagerAlwaysVisible" Responsive="@Responsive" AllowColumnResize="@AllowColumnResize" ColumnWidth="@ColumnWidth" EmptyText="@EmptyText" @ref="grid" Data="@(LoadData.HasDelegate ? (Data != null ? Data.Cast<object>() : Enumerable.Empty<object>()) : pagedData)" Count="@(LoadData.HasDelegate ? Count : count)" LoadData="@OnLoadData"
|
||||
TItem="object" CellRender="@OnCellRender" RowRender="@OnRowRender" ShowPagingSummary="@ShowPagingSummary" PagingSummaryFormat="@PagingSummaryFormat" PageSize="@PageSize" PageNumbersCount="@PageNumbersCount" AllowPaging="@(!IsVirtualizationAllowed())" AllowSorting="@AllowSorting" RowSelect="@OnRowSelect" Style="@(IsVirtualizationAllowed() ? "height:285px" : "")">
|
||||
<RadzenDataGrid VirtualizationOverscanCount="@GetVirtualizationOverscanCount()" AllowRowSelectOnRowClick="@AllowRowSelectOnRowClick" PagerHorizontalAlign="@PagerHorizontalAlign" PagerAlwaysVisible="@PagerAlwaysVisible" Responsive="@Responsive" AllowColumnResize="@AllowColumnResize" ColumnWidth="@ColumnWidth" EmptyText="@EmptyText" @ref="grid" Data="@(LoadData.HasDelegate ? (Data != null ? Data.Cast<object>() : Enumerable.Empty<object>()) : pagedData)" Count="@(LoadData.HasDelegate ? Count : count)" LoadData="@OnLoadData"
|
||||
TItem="object" CellRender="@OnCellRender" RowRender="@OnRowRender" ShowPagingSummary="@ShowPagingSummary" PagingSummaryFormat="@PagingSummaryFormat" PageSize="@PageSize" PageNumbersCount="@PageNumbersCount" AllowPaging="@(!IsVirtualizationAllowed())" AllowSorting="@AllowSorting" RowSelect="@OnRowSelect" Style="@(IsVirtualizationAllowed() ? "height:285px" : "")" Density="@Density">
|
||||
<Columns>
|
||||
@if (Columns != null)
|
||||
{
|
||||
@@ -155,8 +162,8 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
<RadzenDataGrid AllowRowSelectOnRowClick="@AllowRowSelectOnRowClick" PagerHorizontalAlign="@PagerHorizontalAlign" PagerAlwaysVisible="@PagerAlwaysVisible" Responsive="@Responsive" AllowColumnResize="@AllowColumnResize" ColumnWidth="@ColumnWidth" EmptyText="@EmptyText" @ref="grid" Data="@(LoadData.HasDelegate ? (Data != null ? Data.Cast<object>() : Enumerable.Empty<object>()) : pagedData)" Count="@(LoadData.HasDelegate ? Count : count)" LoadData="@OnLoadData"
|
||||
TItem="object" CellRender="@OnCellRender" RowRender="@OnRowRender" ShowPagingSummary="@ShowPagingSummary" PagingSummaryFormat="@PagingSummaryFormat" PageSize="@PageSize" PageNumbersCount="@PageNumbersCount" AllowPaging="@(!IsVirtualizationAllowed())" AllowSorting="@AllowSorting" RowSelect="@OnRowSelect" Style="@(IsVirtualizationAllowed() ? "height:285px" : "")">
|
||||
<RadzenDataGrid VirtualizationOverscanCount="@GetVirtualizationOverscanCount()" AllowRowSelectOnRowClick="@AllowRowSelectOnRowClick" PagerHorizontalAlign="@PagerHorizontalAlign" PagerAlwaysVisible="@PagerAlwaysVisible" Responsive="@Responsive" AllowColumnResize="@AllowColumnResize" ColumnWidth="@ColumnWidth" EmptyText="@EmptyText" @ref="grid" Data="@(LoadData.HasDelegate ? (Data != null ? Data.Cast<object>() : Enumerable.Empty<object>()) : pagedData)" Count="@(LoadData.HasDelegate ? Count : count)" LoadData="@OnLoadData"
|
||||
TItem="object" CellRender="@OnCellRender" RowRender="@OnRowRender" ShowPagingSummary="@ShowPagingSummary" PagingSummaryFormat="@PagingSummaryFormat" PageSize="@PageSize" PageNumbersCount="@PageNumbersCount" AllowPaging="@(!IsVirtualizationAllowed())" AllowSorting="@AllowSorting" RowSelect="@OnRowSelect" Style="@(IsVirtualizationAllowed() ? "height:285px" : "")" Density="@Density">
|
||||
<Columns>
|
||||
<RadzenDataGridColumn TItem="object" Property="it" Title="Item" Type="typeof(string)">
|
||||
<Template>
|
||||
|
||||
@@ -97,7 +97,11 @@ namespace Radzen.Blazor
|
||||
return;
|
||||
|
||||
await JSRuntime.InvokeVoidAsync(OpenOnFocus ? "Radzen.openPopup" : "Radzen.togglePopup", Element, PopupID, true);
|
||||
await JSRuntime.InvokeVoidAsync("Radzen.focusElement", isFilter ? UniqueID : SearchID);
|
||||
|
||||
if (FocusFilterOnPopup)
|
||||
{
|
||||
await JSRuntime.InvokeVoidAsync("Radzen.focusElement", isFilter ? UniqueID : SearchID);
|
||||
}
|
||||
|
||||
if (list != null)
|
||||
{
|
||||
@@ -110,7 +114,13 @@ namespace Radzen.Blazor
|
||||
/// </summary>
|
||||
/// <value>The value template.</value>
|
||||
[Parameter]
|
||||
public RenderFragment<dynamic> ValueTemplate { get; set; }
|
||||
public RenderFragment<dynamic> ValueTemplate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating DataGrid density.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public Density Density { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the empty template shown when Data is empty collection.
|
||||
@@ -244,6 +254,13 @@ namespace Radzen.Blazor
|
||||
[Parameter]
|
||||
public string SelectedItemsText { get; set; } = "items selected";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets whether popup automatically focuses on filter input.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if filter input should auto focus when opened; otherwise, <c>false</c>.</value>
|
||||
[Parameter]
|
||||
public bool FocusFilterOnPopup { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets popup element reference.
|
||||
/// </summary>
|
||||
|
||||
@@ -497,15 +497,7 @@
|
||||
{
|
||||
if (column != null && !string.IsNullOrEmpty(column.FormatString))
|
||||
{
|
||||
var formats = column.FormatString.Split(new char[] { '{', '}' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
if (formats.Length > 0)
|
||||
{
|
||||
var format = formats[0].Trim().Split(':');
|
||||
if (format.Length > 1)
|
||||
{
|
||||
return format[1].Trim();
|
||||
}
|
||||
}
|
||||
return column.FormatString.Replace("{0:", "").Replace("}", "");
|
||||
}
|
||||
|
||||
return FilterDateFormat;
|
||||
|
||||
@@ -46,9 +46,12 @@
|
||||
<RadzenHtmlEditorFontName />
|
||||
<RadzenHtmlEditorFontSize />
|
||||
<RadzenHtmlEditorFormatBlock />
|
||||
<RadzenHtmlEditorSeparator />
|
||||
<RadzenHtmlEditorSource />
|
||||
}
|
||||
</CascadingValue>
|
||||
</div>
|
||||
<div @ref=@ContentEditable class="rz-html-editor-content" contenteditable=@(!Disabled) @onfocus=@OnFocus @onblur=@OnBlur></div>
|
||||
<RadzenTextArea spellcheck="false" Visible=@(mode == HtmlEditorMode.Source) class="rz-html-editor-source" Value=@Html Change=@SourceChanged />
|
||||
<div hidden="@(mode != HtmlEditorMode.Design)" @ref=@ContentEditable class="rz-html-editor-content" contenteditable=@(!Disabled) @onfocus=@OnFocus @onblur=@OnBlur></div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -12,12 +12,18 @@ namespace Radzen.Blazor
|
||||
/// <code>
|
||||
/// <RadzenHtmlEditor @bind-Value=@html />
|
||||
/// @code {
|
||||
/// string html = "@lt;strong>Hello</strong> world!";
|
||||
/// string html = "@lt;strong>Hello</strong> world!";
|
||||
/// }
|
||||
/// </code>
|
||||
/// </example>
|
||||
public partial class RadzenHtmlEditor : FormComponent<string>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the mode of the editor.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public HtmlEditorMode Mode { get; set; } = HtmlEditorMode.Design;
|
||||
private HtmlEditorMode mode { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the child content.
|
||||
/// </summary>
|
||||
@@ -38,7 +44,7 @@ namespace Radzen.Blazor
|
||||
/// <code>
|
||||
/// <RadzenHtmlEditor @bind-Value=@html Paste=@OnPaste />
|
||||
/// @code {
|
||||
/// string html = "@lt;strong>Hello</strong> world!";
|
||||
/// string html = "@lt;strong>Hello</strong> world!";
|
||||
/// void OnPaste(HtmlEditorPasteEventArgs args)
|
||||
/// {
|
||||
/// // Set args.Html to filter unwanted tags.
|
||||
@@ -58,7 +64,7 @@ namespace Radzen.Blazor
|
||||
/// <RadzenHtmlEditorCustomTool CommandName="InsertToday" Icon="today" Title="Insert today" />
|
||||
/// </RadzenHtmlEditor>
|
||||
/// @code {
|
||||
/// string html = "@lt;strong>Hello</strong> world!";
|
||||
/// string html = "@lt;strong>Hello</strong> world!";
|
||||
/// async Task OnExecute(HtmlEditorExecuteEventArgs args)
|
||||
/// {
|
||||
/// if (args.CommandName == "InsertToday")
|
||||
@@ -117,6 +123,14 @@ namespace Radzen.Blazor
|
||||
await OnChange();
|
||||
}
|
||||
|
||||
private async Task SourceChanged(string html)
|
||||
{
|
||||
Html = html;
|
||||
await JSRuntime.InvokeVoidAsync("Radzen.innerHTML", ContentEditable, Html);
|
||||
await OnChange();
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
async Task OnChange()
|
||||
{
|
||||
await Change.InvokeAsync(Html);
|
||||
@@ -191,12 +205,28 @@ namespace Radzen.Blazor
|
||||
}
|
||||
}
|
||||
|
||||
internal void SetMode(HtmlEditorMode value)
|
||||
{
|
||||
mode = value;
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the current mode of the editor.
|
||||
/// </summary>
|
||||
public HtmlEditorMode GetMode()
|
||||
{
|
||||
return mode;
|
||||
}
|
||||
|
||||
string Html { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
Html = Value;
|
||||
mode = Mode;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -233,6 +263,11 @@ namespace Radzen.Blazor
|
||||
valueChanged = Html != parameters.GetValueOrDefault<string>(nameof(Value));
|
||||
}
|
||||
|
||||
if (parameters.DidParameterChange(nameof(Mode), Mode))
|
||||
{
|
||||
mode = Mode;
|
||||
}
|
||||
|
||||
visibleChanged = parameters.DidParameterChange(nameof(Visible), Visible);
|
||||
|
||||
await base.SetParametersAsync(parameters);
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
{
|
||||
@if (Template == null)
|
||||
{
|
||||
<EditorButton Title=@Title Click=@OnClick Icon=@Icon Selected=@Selected Disabled=@Disabled />
|
||||
<EditorButton Title=@Title Click=@OnClick Icon=@Icon Selected=@Selected Disabled=@Disabled EnabledModes="@EnabledModes"/>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="rz-html-editor-custom-tool">@Template(Editor)</div>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,12 @@ namespace Radzen.Blazor
|
||||
[Parameter]
|
||||
public string Icon { get; set; } = "settings";
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the modes that this tool will be enabled in.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public HtmlEditorMode EnabledModes { get; set; } = HtmlEditorMode.Design;
|
||||
|
||||
/// <summary>
|
||||
/// The template of the tool. Use to render a custom tool.
|
||||
/// </summary>
|
||||
|
||||
@@ -2,25 +2,25 @@
|
||||
|
||||
<EditorDropDown Title=@Title Value=@Editor.State.FormatBlock Change=@OnChange Placeholder="@Placeholder"
|
||||
PopupStyle="width: 200px; max-height: 200px; overflow: auto;">
|
||||
<EditorDropDownItem Text="Normal" Value="p">
|
||||
<EditorDropDownItem Text=@NormalText Value="p">
|
||||
<p style="margin:0">@context.Text</p>
|
||||
</EditorDropDownItem>
|
||||
<EditorDropDownItem Text="Heading 1" Value="h1">
|
||||
<EditorDropDownItem Text=@Heading1Text Value="h1">
|
||||
<h1>@context.Text</h1>
|
||||
</EditorDropDownItem>
|
||||
<EditorDropDownItem Text="Heading 2" Value="h2">
|
||||
<EditorDropDownItem Text=@Heading2Text Value="h2">
|
||||
<h2>@context.Text</h2>
|
||||
</EditorDropDownItem>
|
||||
<EditorDropDownItem Text="Heading 3" Value="h3">
|
||||
<EditorDropDownItem Text=@Heading3Text Value="h3">
|
||||
<h3>@context.Text</h3>
|
||||
</EditorDropDownItem>
|
||||
<EditorDropDownItem Text="Heading 4" Value="h4">
|
||||
<EditorDropDownItem Text=@Heading4Text Value="h4">
|
||||
<h4>@context.Text</h4>
|
||||
</EditorDropDownItem>
|
||||
<EditorDropDownItem Text="Heading 5" Value="h5">
|
||||
<EditorDropDownItem Text=@Heading5Text Value="h5">
|
||||
<h5>@context.Text</h5>
|
||||
</EditorDropDownItem>
|
||||
<EditorDropDownItem Text="Heading 6" Value="h6">
|
||||
<EditorDropDownItem Text=@Heading6Text Value="h6">
|
||||
<h6>@context.Text</h6>
|
||||
</EditorDropDownItem>
|
||||
</EditorDropDown>
|
||||
@@ -36,6 +36,48 @@ namespace Radzen.Blazor
|
||||
[Parameter]
|
||||
public string Title { get; set; } = "Text style";
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the text displayed for the normal text example. Set to <c>"Normal"</c> by default.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string NormalText { get; set; } = "Normal";
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the text displayed for the h1 example. Set to <c>"Heading 1"</c> by default.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string Heading1Text { get; set; } = "Heading 1";
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the text displayed for the h2 example. Set to <c>"Heading 2"</c> by default.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string Heading2Text { get; set; } = "Heading 2";
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the text displayed for the h3 example. Set to <c>"Heading 3"</c> by default.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string Heading3Text { get; set; } = "Heading 3";
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the text displayed for the h4 example. Set to <c>"Heading 4"</c> by default.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string Heading4Text { get; set; } = "Heading 4";
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the text displayed for the h5 example. Set to <c>"Heading 5"</c> by default.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string Heading5Text { get; set; } = "Heading 5";
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the text displayed for the h6 example. Set to <c>"Heading 6"</c> by default.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string Heading6Text { get; set; } = "Heading 6";
|
||||
|
||||
async Task OnChange(string value)
|
||||
{
|
||||
await Editor.ExecuteCommandAsync("formatBlock", value);
|
||||
|
||||
22
Radzen.Blazor/RadzenHtmlEditorSource.razor
Normal file
22
Radzen.Blazor/RadzenHtmlEditorSource.razor
Normal file
@@ -0,0 +1,22 @@
|
||||
@using System.Text
|
||||
@using Radzen.Blazor.Rendering
|
||||
@using Microsoft.JSInterop
|
||||
@inherits RadzenHtmlEditorButtonBase
|
||||
@inject DialogService DialogService
|
||||
@inject IJSRuntime JSRuntime
|
||||
|
||||
<EditorButton Title=@Title Click=@OnClick Icon="code" PreventBlur=false Selected=@(Editor.GetMode() == HtmlEditorMode.Source) EnabledModes="HtmlEditorMode.Design | HtmlEditorMode.Source" />
|
||||
@code {
|
||||
|
||||
protected override async Task OnClick()
|
||||
{
|
||||
if (Editor.GetMode() == HtmlEditorMode.Design)
|
||||
{
|
||||
Editor.SetMode(HtmlEditorMode.Source);
|
||||
}
|
||||
else
|
||||
{
|
||||
Editor.SetMode(HtmlEditorMode.Design);
|
||||
}
|
||||
}
|
||||
}
|
||||
20
Radzen.Blazor/RadzenHtmlEditorSource.razor.cs
Normal file
20
Radzen.Blazor/RadzenHtmlEditorSource.razor.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// A tool which switches between rendered and source views in <see cref="RadzenHtmlEditor" />.
|
||||
/// </summary>
|
||||
public partial class RadzenHtmlEditorSource
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the title (tooltip) displayed when the user hovers the tool. Set to <c>"View source"</c> by default.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string Title { get; set; } = "View source";
|
||||
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
var pathGenerator = GetPathGenerator();
|
||||
|
||||
var data = Items.Select(item =>
|
||||
var data = Items.Select(item =>
|
||||
{
|
||||
var x = category(item);
|
||||
var y = value(item);
|
||||
@@ -27,7 +27,7 @@
|
||||
var index = Chart.Series.IndexOf(this);
|
||||
var className = $"rz-line-series rz-series-{index}";
|
||||
|
||||
return
|
||||
return
|
||||
@<g class="@className">
|
||||
@if (Items.Any())
|
||||
{
|
||||
@@ -35,7 +35,7 @@
|
||||
var key = $"{path}-{LineType}";
|
||||
<Path @key=@key Style="@style" D="@path" StrokeWidth="@StrokeWidth" Stroke="@Stroke" LineType="@LineType" Fill="none" />
|
||||
}
|
||||
<Markers Data="@Items" Category="@category" Value="@value" MarkerType="@MarkerType" Stroke="@Markers.Stroke" Fill="@(Markers.Fill ?? Stroke)" StrokeWidth="@Markers.StrokeWidth" Size="@Markers.Size" />
|
||||
<Markers Series="@this" Data="@Items" Category="@category" Value="@value" MarkerType="@MarkerType" Stroke="@Markers.Stroke" Fill="@(Markers.Fill ?? Stroke)" StrokeWidth="@Markers.StrokeWidth" Size="@Markers.Size" />
|
||||
</g>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,15 +6,4 @@
|
||||
{
|
||||
<i class="rzi">@((MarkupString)Icon)</i>
|
||||
}
|
||||
<span @ref="@Element" class="rz-link-text">
|
||||
@if (ChildContent != null)
|
||||
{
|
||||
@ChildContent
|
||||
}
|
||||
else
|
||||
{
|
||||
@Text
|
||||
}
|
||||
</span>
|
||||
</Microsoft.AspNetCore.Components.Routing.NavLink>
|
||||
}
|
||||
<span @ref="@Element" class="rz-link-text">@if (ChildContent != null) {@ChildContent} else {@Text}</span></Microsoft.AspNetCore.Components.Routing.NavLink>}
|
||||
@@ -7,14 +7,14 @@
|
||||
<div class="rz-form-row">
|
||||
<label class="rz-label" for=@Id("username")>@UserText</label>
|
||||
<div class="rz-form-input-wrapper">
|
||||
<RadzenTextBox AutoComplete=@AutoComplete id=@Id("username") Name="Username" @bind-Value=@username />
|
||||
<RadzenTextBox AutoComplete=@AutoComplete AutoCompleteType=@UserNameAutoCompleteType id=@Id("username") Name="Username" @bind-Value=@username />
|
||||
<RadzenRequiredValidator Component="Username" Text=@UserRequired />
|
||||
</div>
|
||||
</div>
|
||||
<div class="rz-form-row">
|
||||
<label class="rz-label" for=@Id("password")>@PasswordText</label>
|
||||
<div class="rz-form-input-wrapper">
|
||||
<RadzenPassword id=@Id("password") AutoComplete=@AutoComplete Name="Password" @bind-Value=@password />
|
||||
<RadzenPassword id=@Id("password") AutoComplete=@AutoComplete AutoCompleteType=@PasswordAutoCompleteType Name="Password" @bind-Value=@password />
|
||||
<RadzenRequiredValidator Component="Password" Text=@PasswordRequired />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -42,6 +42,28 @@ namespace Radzen.Blazor
|
||||
[Parameter]
|
||||
public bool AutoComplete { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating the type of built-in autocomplete
|
||||
/// the browser should use.
|
||||
/// <see cref="Blazor.AutoCompleteType" />
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The type of built-in autocomplete.
|
||||
/// </value>
|
||||
[Parameter]
|
||||
public AutoCompleteType UserNameAutoCompleteType { get; set; } = AutoCompleteType.Username;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating the type of built-in autocomplete
|
||||
/// the browser should use.
|
||||
/// <see cref="Blazor.AutoCompleteType" />
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The type of built-in autocomplete.
|
||||
/// </value>
|
||||
[Parameter]
|
||||
public AutoCompleteType PasswordAutoCompleteType { get; set; } = AutoCompleteType.CurrentPassword;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override string GetComponentCssClass()
|
||||
{
|
||||
|
||||
@@ -6,6 +6,6 @@
|
||||
@if (Visible)
|
||||
{
|
||||
<input @ref="@Element" disabled="@Disabled" readonly="@ReadOnly" name="@Name" style="@Style" @attributes="Attributes" class="@GetCssClass()" tabindex="@(Disabled ? "-1" : $"{TabIndex}")"
|
||||
placeholder="@Placeholder" maxlength="@MaxLength" autocomplete="@(AutoComplete ? "on" : "off")" value="@Value" @onchange="@OnChange" id="@GetId()"
|
||||
placeholder="@Placeholder" maxlength="@MaxLength" autocomplete="@AutoCompleteAttribute" value="@Value" @onchange="@OnChange" id="@GetId()"
|
||||
oninput="Radzen.mask('@GetId()', '@Mask', '@Pattern', '@CharacterPattern')"/>
|
||||
}
|
||||
|
||||
@@ -27,6 +27,17 @@ namespace Radzen.Blazor
|
||||
[Parameter]
|
||||
public bool AutoComplete { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating the type of built-in autocomplete
|
||||
/// the browser should use.
|
||||
/// <see cref="Blazor.AutoCompleteType" />
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The type of built-in autocomplete.
|
||||
/// </value>
|
||||
[Parameter]
|
||||
public AutoCompleteType AutoCompleteType { get; set; } = AutoCompleteType.On;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the maximum length.
|
||||
/// </summary>
|
||||
@@ -84,5 +95,18 @@ namespace Radzen.Blazor
|
||||
JSRuntime.InvokeVoidAsync("eval", $"Radzen.mask('{GetId()}', '{Mask}', '{Pattern}', '{CharacterPattern}')");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the autocomplete attribute's string value.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>off</c> if the AutoComplete parameter is false or the
|
||||
/// AutoCompleteType parameter is "off". When the AutoComplete
|
||||
/// parameter is true, the value is <c>on</c> or, if set, the value of
|
||||
/// AutoCompleteType.</value>
|
||||
public string AutoCompleteAttribute
|
||||
{
|
||||
get => !AutoComplete ? "off" : AutoCompleteType.GetAutoCompleteValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<span @ref="@Element" style="@Style" @attributes="Attributes" class="@GetCssClass()" id="@GetId()">
|
||||
<input @ref="@input" type="text" inputmode="decimal" name="@Name" disabled="@Disabled" readonly="@ReadOnly"
|
||||
class="@GetInputCssClass()" tabindex="@(Disabled ? "-1" : $"{TabIndex}")"
|
||||
placeholder="@Placeholder" autocomplete="@(AutoComplete ? "on" : "off")" value="@FormattedValue" @onchange="@OnChange"
|
||||
placeholder="@Placeholder" autocomplete="@AutoCompleteAttribute" value="@FormattedValue" @onchange="@OnChange"
|
||||
onkeypress="Radzen.numericKeyPress(event, @IsInteger().ToString().ToLower())"
|
||||
onblur="@getOnInput()" onpaste="@getOnPaste()" />
|
||||
@if (ShowUpDown)
|
||||
|
||||
@@ -189,6 +189,30 @@ namespace Radzen.Blazor
|
||||
[Parameter]
|
||||
public bool AutoComplete { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating the type of built-in autocomplete
|
||||
/// the browser should use.
|
||||
/// <see cref="Blazor.AutoCompleteType" />
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The type of built-in autocomplete.
|
||||
/// </value>
|
||||
[Parameter]
|
||||
public AutoCompleteType AutoCompleteType { get; set; } = AutoCompleteType.On;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the autocomplete attribute's string value.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>off</c> if the AutoComplete parameter is false or the
|
||||
/// AutoCompleteType parameter is "off". When the AutoComplete
|
||||
/// parameter is true, the value is <c>on</c> or, if set, the value of
|
||||
/// AutoCompleteType.</value>
|
||||
public string AutoCompleteAttribute
|
||||
{
|
||||
get => !AutoComplete ? "off" : AutoCompleteType.GetAutoCompleteValue();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether up down buttons are shown.
|
||||
/// </summary>
|
||||
|
||||
@@ -27,7 +27,14 @@ namespace Radzen.Blazor
|
||||
/// <inheritdoc />
|
||||
protected override string GetComponentCssClass()
|
||||
{
|
||||
return $"rz-paginator rz-unselectable-text rz-helper-clearfix {HorizontalAlignCssClasses[HorizontalAlign]}";
|
||||
var additionalClasses = new List<string>();
|
||||
|
||||
if (Density == Density.Compact)
|
||||
{
|
||||
additionalClasses.Add("rz-density-compact");
|
||||
}
|
||||
|
||||
return $"rz-paginator rz-unselectable-text rz-helper-clearfix {HorizontalAlignCssClasses[HorizontalAlign]} {String.Join(" ", additionalClasses)}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -37,6 +44,12 @@ namespace Radzen.Blazor
|
||||
[Parameter]
|
||||
public HorizontalAlign HorizontalAlign { get; set; } = HorizontalAlign.Justify;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating Pager density.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public Density Density { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the page size.
|
||||
/// </summary>
|
||||
@@ -114,11 +127,11 @@ namespace Radzen.Blazor
|
||||
return Visible && (AlwaysVisible || Count > PageSize || (PageSizeOptions != null && PageSizeOptions.Any()));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether pager is visible even when not enough data for paging.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if pager is visible even when not enough data for paging otherwise, <c>false</c>.</value>
|
||||
[Parameter]
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether pager is visible even when not enough data for paging.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if pager is visible even when not enough data for paging otherwise, <c>false</c>.</value>
|
||||
[Parameter]
|
||||
public bool AlwaysVisible { get; set; }
|
||||
|
||||
/// <summary>
|
||||
@@ -157,7 +170,7 @@ namespace Radzen.Blazor
|
||||
protected async Task OnPageSizeChanged(object value)
|
||||
{
|
||||
bool isFirstPage = CurrentPage == 0;
|
||||
bool isLastPage = CurrentPage == numberOfPages - 1;
|
||||
bool isLastPage = CurrentPage == numberOfPages - 1 && numberOfPages > 1;
|
||||
int prevSkip = skip;
|
||||
PageSize = (int)value;
|
||||
await InvokeAsync(Reload);
|
||||
|
||||
@@ -5,5 +5,5 @@
|
||||
@if (Visible)
|
||||
{
|
||||
<input @ref="@Element" name="@Name" disabled="@Disabled" readonly="@ReadOnly" style="@Style" type="password" @attributes="Attributes" class="@GetCssClass()"
|
||||
placeholder="@Placeholder" autocomplete="@(AutoComplete ? "on" : "new-password")" value="@Value" @onchange="@OnChange" tabindex="@(Disabled ? "-1" : $"{TabIndex}")" id="@GetId()"/>
|
||||
placeholder="@Placeholder" autocomplete="@AutoCompleteAttribute" value="@Value" @onchange="@OnChange" tabindex="@(Disabled ? "-1" : $"{TabIndex}")" id="@GetId()"/>
|
||||
}
|
||||
|
||||
@@ -26,6 +26,17 @@ namespace Radzen.Blazor
|
||||
[Parameter]
|
||||
public bool AutoComplete { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating the type of built-in autocomplete
|
||||
/// the browser should use.
|
||||
/// <see cref="Blazor.AutoCompleteType" />
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The type of built-in autocomplete.
|
||||
/// </value>
|
||||
[Parameter]
|
||||
public AutoCompleteType AutoCompleteType { get; set; } = AutoCompleteType.On;
|
||||
|
||||
/// <summary>
|
||||
/// Handles the <see cref="E:Change" /> event.
|
||||
/// </summary>
|
||||
@@ -44,5 +55,17 @@ namespace Radzen.Blazor
|
||||
{
|
||||
return GetClassList("rz-textbox").ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the autocomplete attribute's string value.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>new-password</c> if the AutoComplete parameter is false. When
|
||||
/// the AutoComplete parameter is true, the value is <c>on</c> or, if
|
||||
/// set, the value of AutoCompleteType.</value>
|
||||
public string AutoCompleteAttribute
|
||||
{
|
||||
get => !AutoComplete ? "new-password" : AutoCompleteType.GetAutoCompleteValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,37 +16,47 @@
|
||||
var y = CenterY;
|
||||
var radius = CurrentRadius;
|
||||
|
||||
return
|
||||
return
|
||||
@<g class="@className">
|
||||
@if (Items.Any())
|
||||
{
|
||||
var sum = Items.Sum(Value);
|
||||
|
||||
double startAngle = -90;
|
||||
|
||||
@foreach(var data in Items)
|
||||
@if (PositiveItems.Any())
|
||||
{
|
||||
var value = Value(data);
|
||||
var angle = sum == 0 ? 0 : (value / sum) * 360;
|
||||
var endAngle = startAngle + angle;
|
||||
var sum = PositiveItems.Sum(Value);
|
||||
|
||||
var d = Segment(x, y, radius, 0, startAngle, endAngle);
|
||||
double startAngle = -90;
|
||||
|
||||
startAngle = endAngle;
|
||||
|
||||
var index = Items.IndexOf(data);
|
||||
var arcClassName = $"rz-series-item-{index}";
|
||||
var fill = PickColor(index, Fills);
|
||||
var stroke = PickColor(index, Strokes);
|
||||
@foreach (var data in PositiveItems)
|
||||
{
|
||||
var value = Value(data);
|
||||
var angle = sum == 0 ? 0 : (value / sum) * 360;
|
||||
var endAngle = startAngle + angle;
|
||||
|
||||
var d = Segment(x, y, radius, 0, startAngle, endAngle);
|
||||
|
||||
startAngle = endAngle;
|
||||
|
||||
var index = Items.IndexOf(data);
|
||||
var arcClassName = $"rz-series-item-{index}";
|
||||
var fill = PickColor(index, Fills);
|
||||
var stroke = PickColor(index, Strokes);
|
||||
|
||||
<g class="@arcClassName">
|
||||
@if (angle > 0)
|
||||
{
|
||||
<Path D="@d" Fill="@fill" StrokeWidth="@StrokeWidth" Stroke="@stroke" />
|
||||
}
|
||||
</g>
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var arcClassName = $"rz-series-item-0";
|
||||
var d = Segment(x, y, radius, radius - 1, -90, 270);
|
||||
var fill = PickColor(0, Fills);
|
||||
var stroke = PickColor(0, Strokes);
|
||||
<g class="@arcClassName">
|
||||
@if (angle > 0)
|
||||
{
|
||||
<Path D="@d" Fill="@fill" StrokeWidth="@StrokeWidth" Stroke="@stroke" />
|
||||
}
|
||||
<Path D="@d" Fill="@fill" StrokeWidth="@StrokeWidth" Stroke="@stroke" />
|
||||
</g>
|
||||
}
|
||||
}
|
||||
</g>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,6 +93,27 @@ namespace Radzen.Blazor
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stores <see cref="Data" /> filtered to items greater than zero as an IList of <typeparamref name="TItem"/>.
|
||||
/// </summary>
|
||||
/// <value>The items.</value>
|
||||
protected IList<TItem> PositiveItems { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override async Task SetParametersAsync(ParameterView parameters)
|
||||
{
|
||||
await base.SetParametersAsync(parameters);
|
||||
|
||||
if (Items != null)
|
||||
{
|
||||
PositiveItems = Items.Where(e => Value(e) > 0).ToList();
|
||||
}
|
||||
else
|
||||
{
|
||||
PositiveItems = new List<TItem>();
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override double MeasureLegend()
|
||||
{
|
||||
@@ -208,11 +229,11 @@ namespace Radzen.Blazor
|
||||
/// <inheritdoc />
|
||||
internal override double TooltipX(TItem item)
|
||||
{
|
||||
var sum = Items.Sum(Value);
|
||||
var sum = PositiveItems.Sum(Value);
|
||||
double startAngle = 0;
|
||||
double endAngle = 0;
|
||||
|
||||
foreach (var data in Items)
|
||||
foreach (var data in PositiveItems)
|
||||
{
|
||||
var value = Value(data);
|
||||
endAngle = startAngle + (value / sum) * 360;
|
||||
@@ -233,7 +254,7 @@ namespace Radzen.Blazor
|
||||
/// <inheritdoc />
|
||||
internal override double TooltipY(TItem item)
|
||||
{
|
||||
var sum = Items.Sum(Value);
|
||||
var sum = PositiveItems.Sum(Value);
|
||||
double startAngle = 0;
|
||||
double endAngle = 0;
|
||||
|
||||
@@ -310,7 +331,7 @@ namespace Radzen.Blazor
|
||||
|
||||
if (Math.Abs(end.X - start.X) < 0.01 && Math.Abs(end.Y - start.Y) < 0.01)
|
||||
{
|
||||
// Full circle - SVG can't render a full circle arc
|
||||
// Full circle - SVG can't render a full circle arc
|
||||
endX = (end.X - 0.01).ToInvariantString();
|
||||
|
||||
innerEndX = (innerEnd.X - 0.01).ToInvariantString();
|
||||
@@ -324,31 +345,36 @@ namespace Radzen.Blazor
|
||||
{
|
||||
var list = new List<ChartDataLabel>();
|
||||
|
||||
foreach (var d in Data)
|
||||
if(Data != null)
|
||||
{
|
||||
var x = TooltipX(d) - CenterX;
|
||||
var y = TooltipY(d) - CenterY;
|
||||
//var DataGreaterZero = Data.Where(e => Value(e) > 0).ToList();
|
||||
|
||||
// find angle and add offset
|
||||
var phi = Math.Atan2(y, x);
|
||||
foreach (var d in PositiveItems)
|
||||
{
|
||||
var x = TooltipX(d) - CenterX;
|
||||
var y = TooltipY(d) - CenterY;
|
||||
|
||||
phi += Polar.ToRadian(offsetY % 360);
|
||||
// find angle and add offset
|
||||
var phi = Math.Atan2(y, x);
|
||||
|
||||
var textAnchor = phi >= -1.5 && phi <= 1.5 ? "start" : "end";
|
||||
phi += Polar.ToRadian(offsetY % 360);
|
||||
|
||||
// find radius
|
||||
var hyp = Math.Sqrt(x * x + y * y) + offsetX + 16;
|
||||
var textAnchor = phi >= -1.5 && phi <= 1.5 ? "start" : "end";
|
||||
|
||||
// move along the radius and rotate
|
||||
x = CenterX + hyp * Math.Cos(phi);
|
||||
y = CenterY + hyp * Math.Sin(phi);
|
||||
// find radius
|
||||
var hyp = Math.Sqrt(x * x + y * y) + offsetX + 16;
|
||||
|
||||
list.Add(new ChartDataLabel
|
||||
{
|
||||
TextAnchor = textAnchor,
|
||||
Position = new Point { X = x, Y = y },
|
||||
Text = Chart.ValueAxis.Format(Chart.ValueScale, Value(d))
|
||||
});
|
||||
// move along the radius and rotate
|
||||
x = CenterX + hyp * Math.Cos(phi);
|
||||
y = CenterY + hyp * Math.Sin(phi);
|
||||
|
||||
list.Add(new ChartDataLabel
|
||||
{
|
||||
TextAnchor = textAnchor,
|
||||
Position = new Point { X = x, Y = y },
|
||||
Text = Chart.ValueAxis.Format(Chart.ValueScale, Value(d))
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
|
||||
@@ -274,6 +274,27 @@ namespace Radzen.Blazor
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Selects the specified <see cref="ISchedulerView"/>. The view must already be present in this scheduler.
|
||||
/// If the specified view is already selected, no action will be performed.
|
||||
/// </summary>
|
||||
/// <param name="view">The <see cref="ISchedulerView"/> to select</param>
|
||||
public async Task SelectView(ISchedulerView view)
|
||||
{
|
||||
var viewIndex = Views.IndexOf(view);
|
||||
if (viewIndex == -1)
|
||||
return;
|
||||
|
||||
if (SelectedView == view)
|
||||
return;
|
||||
|
||||
selectedIndex = viewIndex;
|
||||
|
||||
await InvokeLoadData();
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Causes the current scheduler view to render. Enumerates the items of <see cref="Data" /> and creates instances of <see cref="AppointmentData" /> to
|
||||
/// display in the current view. Use it when <see cref="Data" /> has changed.
|
||||
|
||||
@@ -29,12 +29,15 @@
|
||||
builder.OpenRegion(0);
|
||||
foreach (var label in series.GetDataLabels(OffsetX, OffsetY))
|
||||
{
|
||||
builder.AddContent(1,
|
||||
@<g>
|
||||
<Text @key="@($"{label.Position}-{Chart.Series.IndexOf(series)}")"
|
||||
Value="@label.Text" Position="@label.Position" TextAnchor="@label.TextAnchor" Class="rz-series-data-label" />
|
||||
</g>
|
||||
if (!(double.IsNaN(label.Position.X) || double.IsNaN(label.Position.Y)))
|
||||
{
|
||||
builder.AddContent(1,
|
||||
@<g>
|
||||
<Text @key="@($"{label.Position}-{Chart.Series.IndexOf(series)}")"
|
||||
Value="@label.Text" Position="@label.Position" TextAnchor="@label.TextAnchor" Class="rz-series-data-label" />
|
||||
</g>
|
||||
);
|
||||
}
|
||||
}
|
||||
builder.CloseRegion();
|
||||
};
|
||||
|
||||
@@ -4,24 +4,35 @@
|
||||
@if (Visible)
|
||||
{
|
||||
<div @ref="@Element" style="@Style" @attributes="Attributes" class="@GetCssClass()" id="@GetId()">
|
||||
<button disabled="@Disabled" class="@getButtonCss()" type="button" @onclick="@OnClick">
|
||||
@if (!string.IsNullOrEmpty(@Icon))
|
||||
<button disabled="@IsDisabled" class="@getButtonCss()" type="button" @onclick="@OnClick">
|
||||
@if (IsBusy)
|
||||
{
|
||||
<i class="rz-button-icon-left rzi">@((MarkupString)Icon)</i>
|
||||
}
|
||||
@if (!string.IsNullOrEmpty(Image))
|
||||
{
|
||||
<img class="rz-button-icon-left rzi" src="@Image" />
|
||||
}
|
||||
@if (!string.IsNullOrEmpty(Text))
|
||||
{
|
||||
<span class="rz-button-text">@Text</span>
|
||||
<RadzenIcon Icon="refresh" Style="animation: rotation 700ms linear infinite" />
|
||||
@if (!string.IsNullOrEmpty(BusyText))
|
||||
{
|
||||
<span class="rz-button-text">@BusyText</span>
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="rz-button-text"> </span>
|
||||
@if (!string.IsNullOrEmpty(@Icon))
|
||||
{
|
||||
<i class="rz-button-icon-left rzi">@((MarkupString)Icon)</i>
|
||||
}
|
||||
@if (!string.IsNullOrEmpty(Image))
|
||||
{
|
||||
<img class="rz-button-icon-left rzi" src="@Image" />
|
||||
}
|
||||
@if (!string.IsNullOrEmpty(Text))
|
||||
{
|
||||
<span class="rz-button-text">@Text</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="rz-button-text"> </span>
|
||||
}
|
||||
}
|
||||
</button><button onclick="@OpenPopupScript()" class="@getPopupButtonCss()" type="button">
|
||||
</button><button disabled="@IsDisabled" onclick="@OpenPopupScript()" class="@getPopupButtonCss()" type="button">
|
||||
<span aria-hidden="true" class="rz-button-icon-left rzi rzi-chevron-down"></span><span class="rz-button-text"></span>
|
||||
</button>
|
||||
<div id="@PopupID" class="rz-splitbutton-menu">
|
||||
|
||||
@@ -75,6 +75,26 @@ namespace Radzen.Blazor
|
||||
[Parameter]
|
||||
public ButtonSize Size { get; set; } = ButtonSize.Medium;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance busy text is shown.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance busy text is shown; otherwise, <c>false</c>.</value>
|
||||
[Parameter]
|
||||
public bool IsBusy { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the busy text.
|
||||
/// </summary>
|
||||
/// <value>The busy text.</value>
|
||||
[Parameter]
|
||||
public string BusyText { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this instance is disabled.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance is disabled; otherwise, <c>false</c>.</value>
|
||||
public bool IsDisabled { get => Disabled || IsBusy; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this <see cref="RadzenSplitButton"/> is disabled.
|
||||
/// </summary>
|
||||
@@ -138,12 +158,12 @@ namespace Radzen.Blazor
|
||||
|
||||
private string getButtonCss()
|
||||
{
|
||||
return $"rz-button rz-button-{getButtonSize()} rz-variant-{Enum.GetName(typeof(Variant), Variant).ToLowerInvariant()} rz-{Enum.GetName(typeof(ButtonStyle), ButtonStyle).ToLowerInvariant()} rz-shade-{Enum.GetName(typeof(Shade), Shade).ToLowerInvariant()} {(Disabled ? " rz-state-disabled" : "")}{(string.IsNullOrEmpty(Text) && !string.IsNullOrEmpty(Icon) ? " rz-button-icon-only" : "")}";
|
||||
return $"rz-button rz-button-{getButtonSize()} rz-variant-{Enum.GetName(typeof(Variant), Variant).ToLowerInvariant()} rz-{Enum.GetName(typeof(ButtonStyle), ButtonStyle).ToLowerInvariant()} rz-shade-{Enum.GetName(typeof(Shade), Shade).ToLowerInvariant()} {(IsDisabled ? " rz-state-disabled" : "")}{(string.IsNullOrEmpty(Text) && !string.IsNullOrEmpty(Icon) ? " rz-button-icon-only" : "")}";
|
||||
}
|
||||
|
||||
private string getPopupButtonCss()
|
||||
{
|
||||
return $"rz-splitbutton-menubutton rz-button rz-button-icon-only rz-button-{getButtonSize()} rz-variant-{Enum.GetName(typeof(Variant), Variant).ToLowerInvariant()} rz-{Enum.GetName(typeof(ButtonStyle), ButtonStyle).ToLowerInvariant()} rz-shade-{Enum.GetName(typeof(Shade), Shade).ToLowerInvariant()}{(Disabled ? " rz-state-disabled" : "")}";
|
||||
return $"rz-splitbutton-menubutton rz-button rz-button-icon-only rz-button-{getButtonSize()} rz-variant-{Enum.GetName(typeof(Variant), Variant).ToLowerInvariant()} rz-{Enum.GetName(typeof(ButtonStyle), ButtonStyle).ToLowerInvariant()} rz-shade-{Enum.GetName(typeof(Shade), Shade).ToLowerInvariant()}{(IsDisabled ? " rz-state-disabled" : "")}";
|
||||
}
|
||||
|
||||
private string OpenPopupScript()
|
||||
|
||||
@@ -100,7 +100,7 @@ namespace Radzen.Blazor
|
||||
if (!pane.Resizable)
|
||||
return Task.CompletedTask;
|
||||
|
||||
var paneNextResizable = Panes.Skip(paneIndex + 1).FirstOrDefault(o => o.Resizable && !o.Collapsed);
|
||||
var paneNextResizable = Panes.Skip(paneIndex + 1).FirstOrDefault(o => o.Resizable && !o.GetCollapsed());
|
||||
|
||||
|
||||
return JSRuntime.InvokeVoidAsync("Radzen.startSplitterResize",
|
||||
@@ -164,7 +164,7 @@ namespace Radzen.Blazor
|
||||
var pane = Panes[paneIndex];
|
||||
var paneNext = pane.Next();
|
||||
|
||||
if (paneNext != null && paneNext.Collapsible && paneNext.IsLast && paneNext.Collapsed)
|
||||
if (paneNext != null && paneNext.Collapsible && paneNext.IsLast && paneNext.GetCollapsed())
|
||||
{
|
||||
if (Expand.HasDelegate)
|
||||
{
|
||||
@@ -197,7 +197,7 @@ namespace Radzen.Blazor
|
||||
var pane = Panes[paneIndex];
|
||||
var paneNext = pane.Next();
|
||||
|
||||
if (paneNext != null && paneNext.Collapsible && paneNext.IsLast && !pane.Collapsed)
|
||||
if (paneNext != null && paneNext.Collapsible && paneNext.IsLast && !pane.GetCollapsed())
|
||||
{
|
||||
if (Collapse.HasDelegate)
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
@@ -19,7 +20,7 @@ namespace Radzen.Blazor
|
||||
|
||||
internal bool IsLastResizable
|
||||
{
|
||||
get { return Splitter.Panes.Last(o => o.Resizable && !o.Collapsed) == this; }
|
||||
get { return Splitter.Panes.Last(o => o.Resizable && !o.GetCollapsed()) == this; }
|
||||
}
|
||||
|
||||
internal bool IsLast => Splitter.Panes.Count - 1 == Index;
|
||||
@@ -37,9 +38,9 @@ namespace Radzen.Blazor
|
||||
{
|
||||
var paneNext = Next();
|
||||
|
||||
if (Collapsed
|
||||
if (GetCollapsed()
|
||||
|| (Index == Splitter.Panes.Count - 2 && !paneNext.IsResizable)
|
||||
|| (IsLastResizable && paneNext != null && paneNext.Collapsed)
|
||||
|| (IsLastResizable && paneNext != null && paneNext.GetCollapsed())
|
||||
)
|
||||
return false;
|
||||
|
||||
@@ -52,14 +53,14 @@ namespace Radzen.Blazor
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Collapsible && !Collapsed)
|
||||
if (Collapsible && !GetCollapsed())
|
||||
return true;
|
||||
|
||||
var paneNext = Next();
|
||||
if (paneNext == null)
|
||||
return false;
|
||||
|
||||
return paneNext.IsLast && paneNext.Collapsible && paneNext.Collapsed;
|
||||
return paneNext.IsLast && paneNext.Collapsible && paneNext.GetCollapsed();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,14 +68,14 @@ namespace Radzen.Blazor
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Collapsed)
|
||||
if (GetCollapsed())
|
||||
return true;
|
||||
|
||||
var paneNext = Next();
|
||||
if (paneNext == null)
|
||||
return false;
|
||||
|
||||
return paneNext.IsLast && paneNext.Collapsible && !paneNext.Collapsed;
|
||||
return paneNext.IsLast && paneNext.Collapsible && !paneNext.GetCollapsed();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,7 +83,7 @@ namespace Radzen.Blazor
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Collapsed)
|
||||
if (GetCollapsed())
|
||||
return "collapsed";
|
||||
|
||||
if (IsLastResizable)
|
||||
@@ -109,6 +110,7 @@ namespace Radzen.Blazor
|
||||
[Parameter]
|
||||
public bool Collapsible { get; set; } = true;
|
||||
|
||||
private bool? collapsed;
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this <see cref="RadzenSplitterPane"/> is collapsed.
|
||||
/// </summary>
|
||||
@@ -168,9 +170,13 @@ namespace Radzen.Blazor
|
||||
|
||||
internal void SetCollapsed(bool value)
|
||||
{
|
||||
Collapsed = value;
|
||||
collapsed = value;
|
||||
}
|
||||
|
||||
internal bool GetCollapsed()
|
||||
{
|
||||
return collapsed ?? Collapsed;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Dispose()
|
||||
@@ -179,6 +185,17 @@ namespace Radzen.Blazor
|
||||
Splitter?.RemovePane(this);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override async Task SetParametersAsync(ParameterView parameters)
|
||||
{
|
||||
if (parameters.DidParameterChange(nameof(Collapsed), Collapsed))
|
||||
{
|
||||
collapsed = parameters.GetValueOrDefault<bool>(nameof(Collapsed));
|
||||
}
|
||||
|
||||
await base.SetParametersAsync(parameters);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override string GetComponentCssClass()
|
||||
{
|
||||
|
||||
56
Radzen.Blazor/RadzenStackedBarSeries.razor
Normal file
56
Radzen.Blazor/RadzenStackedBarSeries.razor
Normal file
@@ -0,0 +1,56 @@
|
||||
@using Radzen
|
||||
@using Radzen.Blazor
|
||||
@using Radzen.Blazor.Rendering
|
||||
@typeparam TItem
|
||||
@inherits Radzen.Blazor.CartesianSeries<TItem>
|
||||
@implements IChartStackedBarSeries
|
||||
|
||||
<CascadingValue Value="@this">
|
||||
@ChildContent
|
||||
</CascadingValue>
|
||||
|
||||
@code {
|
||||
public override RenderFragment Render(ScaleBase categoryScale, ScaleBase valueScale)
|
||||
{
|
||||
var value = ComposeValue(categoryScale);
|
||||
var category = ComposeCategory(valueScale);
|
||||
var ticks = Chart.CategoryScale.Ticks(Chart.ValueAxis.TickDistance);
|
||||
var style = $"clip-path: url(#{Chart.ClipPath}); -webkit-clip-path: url(#{Chart.ClipPath});";
|
||||
|
||||
var barSeries = StackedBarSeries;
|
||||
var barIndex = BarIndex;
|
||||
var height = BarHeight;
|
||||
|
||||
var className = $"rz-bar-series rz-series-{Chart.Series.IndexOf(this)}";
|
||||
|
||||
return
|
||||
@<g class="@className">
|
||||
@for (var index = 0; index < Items.Count; index++)
|
||||
{
|
||||
var data = Items[index];
|
||||
var y = GetBarTop(data, category);
|
||||
var x = GetBarRight(data, barIndex, index, barSeries);
|
||||
var radius = Chart.BarOptions.Radius;
|
||||
|
||||
if (radius > height / 2 || barIndex < barSeries.Count - 1)
|
||||
{
|
||||
radius = 0;
|
||||
}
|
||||
var x0 = GetBarLeft(barIndex, index, barSeries);
|
||||
|
||||
var r = radius.ToInvariantString();
|
||||
|
||||
var path = $"M {x0.ToInvariantString()} {y.ToInvariantString()} L {(x-radius).ToInvariantString()} {y.ToInvariantString()} A {r} {r} 0 0 1 {x.ToInvariantString()} {(y+radius).ToInvariantString()} L {x.ToInvariantString()} {(y+height-radius).ToInvariantString()} A {r} {r} 0 0 1 {(x-radius).ToInvariantString()} {(y + height).ToInvariantString()} L {x0.ToInvariantString()} {(y+height).ToInvariantString()} Z";
|
||||
|
||||
if (x < x0)
|
||||
{
|
||||
path = $"M {x0.ToInvariantString()} {y.ToInvariantString()} L {(x+radius).ToInvariantString()} {y.ToInvariantString()} A {r} {r} 0 0 0 {x.ToInvariantString()} {(y+radius).ToInvariantString()} L {x.ToInvariantString()} {(y+height-radius).ToInvariantString()} A {r} {r} 0 0 0 {(x+radius).ToInvariantString()} {(y + height).ToInvariantString()} L {x0.ToInvariantString()} {(y+height).ToInvariantString()} Z";
|
||||
}
|
||||
var fill = PickColor(Items.IndexOf(data), Fills, Fill);
|
||||
var stroke = PickColor(Items.IndexOf(data), Strokes, Stroke);
|
||||
|
||||
<Path @key="@path" D="@path" Stroke="@stroke" StrokeWidth="@StrokeWidth" Fill="@fill" LineType="@LineType" Style="@style" />
|
||||
}
|
||||
</g>;
|
||||
}
|
||||
}
|
||||
265
Radzen.Blazor/RadzenStackedBarSeries.razor.cs
Normal file
265
Radzen.Blazor/RadzenStackedBarSeries.razor.cs
Normal file
@@ -0,0 +1,265 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Radzen.Blazor.Rendering;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// Renders bar series in <see cref="RadzenChart" />.
|
||||
/// </summary>
|
||||
/// <typeparam name="TItem">The type of the series data item.</typeparam>
|
||||
public partial class RadzenStackedBarSeries<TItem> : CartesianSeries<TItem>, IChartStackedBarSeries
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies the fill (background color) of the bar series.
|
||||
/// </summary>
|
||||
/// <value>The fill.</value>
|
||||
[Parameter]
|
||||
public string Fill { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Specifies a list of colors that will be used to set the individual bar backgrounds.
|
||||
/// </summary>
|
||||
/// <value>The fills.</value>
|
||||
[Parameter]
|
||||
public IEnumerable<string> Fills { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the stroke (border color) of the bar series.
|
||||
/// </summary>
|
||||
/// <value>The stroke.</value>
|
||||
[Parameter]
|
||||
public string Stroke { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Specifies a list of colors that will be used to set the individual bar borders.
|
||||
/// </summary>
|
||||
/// <value>The strokes.</value>
|
||||
[Parameter]
|
||||
public IEnumerable<string> Strokes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the width of the stroke (border).
|
||||
/// </summary>
|
||||
/// <value>The width of the stroke.</value>
|
||||
[Parameter]
|
||||
public double StrokeWidth { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the type of the line used to render the bar border.
|
||||
/// </summary>
|
||||
/// <value>The type of the line.</value>
|
||||
[Parameter]
|
||||
public LineType LineType { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Color
|
||||
{
|
||||
get
|
||||
{
|
||||
return Fill;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override ScaleBase TransformCategoryScale(ScaleBase scale)
|
||||
{
|
||||
var stackedBarSeries = BarSeries.Cast<IChartStackedBarSeries>();
|
||||
var count = stackedBarSeries.Max(series => series.Count);
|
||||
var sums = Enumerable.Range(0, count).Select(i => stackedBarSeries.Sum(series => series.ValueAt(i)));
|
||||
var max = sums.Max();
|
||||
var min = Items.Min(Value);
|
||||
|
||||
scale.Input.MergeWidth(new ScaleRange { Start = min, End = max });
|
||||
|
||||
return scale;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override ScaleBase TransformValueScale(ScaleBase scale)
|
||||
{
|
||||
return base.TransformCategoryScale(scale);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override IList<object> GetCategories()
|
||||
{
|
||||
return base.GetCategories().Reverse().ToList();
|
||||
}
|
||||
|
||||
private IList<IChartSeries> BarSeries => Chart.Series.Where(series => series is IChartStackedBarSeries).Cast<IChartSeries>().ToList();
|
||||
|
||||
private IList<IChartSeries> VisibleBarSeries => BarSeries.Where(series => series.Visible).ToList();
|
||||
|
||||
private IList<IChartStackedBarSeries> StackedBarSeries => VisibleBarSeries.Cast<IChartStackedBarSeries>().ToList();
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override string TooltipStyle(TItem item)
|
||||
{
|
||||
var style = base.TooltipStyle(item);
|
||||
|
||||
var index = Items.IndexOf(item);
|
||||
|
||||
if (index >= 0)
|
||||
{
|
||||
var color = PickColor(index, Fills, Fill);
|
||||
|
||||
if (color != null)
|
||||
{
|
||||
style = $"{style}; border-color: {color};";
|
||||
}
|
||||
}
|
||||
|
||||
return style;
|
||||
}
|
||||
|
||||
private double BandHeight
|
||||
{
|
||||
get
|
||||
{
|
||||
var barSeries = VisibleBarSeries;
|
||||
|
||||
if (Chart.BarOptions.Height.HasValue)
|
||||
{
|
||||
return Chart.BarOptions.Height.Value * barSeries.Count;
|
||||
}
|
||||
else
|
||||
{
|
||||
var availableHeight = Chart.ValueScale.OutputSize; // - (Chart.ValueAxis.Padding * 2);
|
||||
var bands = barSeries.Cast<IChartStackedBarSeries>().Max(series => series.Count) + 2;
|
||||
return availableHeight / bands;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double BarHeight => Chart.BarOptions.Height ?? BandHeight - Chart.BarOptions.Margin;
|
||||
|
||||
int BarIndex => VisibleBarSeries.IndexOf(this);
|
||||
|
||||
private double GetBarTop(TItem item, Func<TItem, double> category = null)
|
||||
{
|
||||
category = category ?? ComposeCategory(Chart.ValueScale);
|
||||
|
||||
return category(item) - BarHeight / 2;
|
||||
}
|
||||
|
||||
private double GetBarRight(TItem item, int barIndex, int index, IEnumerable<IChartStackedBarSeries> stackedBarSeries)
|
||||
{
|
||||
var count = stackedBarSeries.Max(series => series.Count);
|
||||
var sum = stackedBarSeries.Take(barIndex).Sum(series => series.ValueAt(index));
|
||||
|
||||
var y = Chart.CategoryScale.Scale(Value(item) + sum);
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
private double GetBarLeft(int barIndex, int index, IEnumerable<IChartStackedBarSeries> stackedBarSeries)
|
||||
{
|
||||
var ticks = Chart.CategoryScale.Ticks(Chart.ValueAxis.TickDistance);
|
||||
|
||||
var sum = stackedBarSeries.Take(barIndex).Sum(series => series.ValueAt(index));
|
||||
|
||||
return Chart.CategoryScale.Scale(Math.Max(0, Math.Max(ticks.Start, sum)));
|
||||
}
|
||||
|
||||
int IChartBarSeries.Count
|
||||
{
|
||||
get
|
||||
{
|
||||
return Items.Count;
|
||||
}
|
||||
}
|
||||
double IChartStackedBarSeries.ValueAt(int index)
|
||||
{
|
||||
if (Items == null || index < 0 || index >= Items.Count)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return Value(Items[index]);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool Contains(double x, double y, double tolerance)
|
||||
{
|
||||
return DataAt(x, y) != null;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
internal override double TooltipX(TItem item)
|
||||
{
|
||||
return GetBarRight(item, BarIndex, Items.IndexOf(item), StackedBarSeries);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override string TooltipValue(TItem item)
|
||||
{
|
||||
return Chart.ValueAxis.Format(Chart.CategoryScale, Chart.CategoryScale.Value(Value(item)));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override string TooltipTitle(TItem item)
|
||||
{
|
||||
var category = Category(Chart.ValueScale);
|
||||
return Chart.CategoryAxis.Format(Chart.ValueScale, Chart.ValueScale.Value(category(item)));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override object DataAt(double x, double y)
|
||||
{
|
||||
var category = ComposeCategory(Chart.ValueScale);
|
||||
var barSeries = VisibleBarSeries;
|
||||
var barIndex = BarIndex;
|
||||
|
||||
for (var index = 0; index < Items.Count; index++)
|
||||
{
|
||||
var data = Items[index];
|
||||
var startY = GetBarTop(data, category);
|
||||
var endY = startY + BandHeight;
|
||||
var dataX = GetBarRight(data, barIndex, index, StackedBarSeries);
|
||||
var x0 = GetBarLeft(barIndex, index, StackedBarSeries);
|
||||
var startX = Math.Min(dataX, x0);
|
||||
var endX = Math.Max(dataX, x0);
|
||||
|
||||
if (startX <= x && x <= endX && startY <= y && y <= endY)
|
||||
{
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
internal override double TooltipY(TItem item)
|
||||
{
|
||||
return GetBarTop(item) + BarHeight / 2;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override IEnumerable<ChartDataLabel> GetDataLabels(double offsetX, double offsetY)
|
||||
{
|
||||
var list = new List<ChartDataLabel>();
|
||||
var barIndex = BarIndex;
|
||||
var stackedBarSeries = StackedBarSeries;
|
||||
|
||||
for (var index = 0; index < Items.Count; index++)
|
||||
{
|
||||
var data = Items[index];
|
||||
var left = GetBarLeft(barIndex, index, stackedBarSeries);
|
||||
var right = GetBarRight(data, barIndex, index, stackedBarSeries);
|
||||
var x = left + (right - left) / 2;
|
||||
list.Add(new ChartDataLabel
|
||||
{
|
||||
Position = new Point() { X = x + offsetX, Y = TooltipY(data) + offsetY },
|
||||
TextAnchor = "middle",
|
||||
Text = Chart.ValueAxis.Format(Chart.CategoryScale, Value(data))
|
||||
});
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
}
|
||||
}
|
||||
51
Radzen.Blazor/RadzenStackedColumnSeries.razor
Normal file
51
Radzen.Blazor/RadzenStackedColumnSeries.razor
Normal file
@@ -0,0 +1,51 @@
|
||||
@using Radzen.Blazor
|
||||
@using Radzen.Blazor.Rendering
|
||||
@typeparam TItem
|
||||
@inherits Radzen.Blazor.CartesianSeries<TItem>
|
||||
@implements IChartStackedColumnSeries
|
||||
|
||||
<CascadingValue Value="@this">
|
||||
@ChildContent
|
||||
</CascadingValue>
|
||||
@code {
|
||||
public override RenderFragment Render(ScaleBase categoryScale, ScaleBase valueScale)
|
||||
{
|
||||
var category = ComposeCategory(categoryScale);
|
||||
var style = $"clip-path: url(#{Chart.ClipPath}); -webkit-clip-path: url(#{Chart.ClipPath});";
|
||||
|
||||
var columnIndex = ColumnIndex;
|
||||
var stackedColumnSeries = StackedColumnSeries;
|
||||
|
||||
var width = ColumnWidth;
|
||||
var className = $"rz-column-series rz-series-{Chart.Series.IndexOf(this)}";
|
||||
|
||||
return
|
||||
@<g class="@className">
|
||||
@for (var index = 0; index < Items.Count; index++)
|
||||
{
|
||||
var data = Items[index];
|
||||
var x = GetColumnLeft(data, category);
|
||||
var y = GetColumnTop(data, columnIndex, index, stackedColumnSeries);
|
||||
var radius = Chart.ColumnOptions.Radius;
|
||||
|
||||
if (radius > width / 2 || columnIndex < stackedColumnSeries.Count - 1)
|
||||
{
|
||||
radius = 0;
|
||||
}
|
||||
|
||||
var y0 = GetColumnBottom(columnIndex, index, stackedColumnSeries);
|
||||
|
||||
var path = $"M {x.ToInvariantString()} {(y+radius).ToInvariantString()} A {radius.ToInvariantString()} {radius.ToInvariantString()} 0 0 1 {(x + radius).ToInvariantString()} {y.ToInvariantString()} L {(x + width - radius).ToInvariantString()} {y.ToInvariantString()} A {radius.ToInvariantString()} {radius.ToInvariantString()} 0 0 1 {(x + width).ToInvariantString()} {(y+radius).ToInvariantString()} L {(x+width).ToInvariantString()} {y0.ToInvariantString()} L {x.ToInvariantString()} {y0.ToInvariantString()} Z";
|
||||
|
||||
if (y > y0)
|
||||
{
|
||||
path = $"M {x.ToInvariantString()} {y0.ToInvariantString()} L {(x+width).ToInvariantString()} {y0.ToInvariantString()} L {(x+width).ToInvariantString()} {(y-radius).ToInvariantString()} A {radius.ToInvariantString()} {radius.ToInvariantString()} 0 0 1 {(x + width - radius).ToInvariantString()} {y.ToInvariantString()} L {(x + radius).ToInvariantString()} {y.ToInvariantString()} A {radius.ToInvariantString()} {radius.ToInvariantString()} 0 0 1 {x.ToInvariantString()} {(y-radius).ToInvariantString()} L {x.ToInvariantString()} {y0.ToInvariantString()} Z";
|
||||
}
|
||||
var fill = PickColor(Items.IndexOf(data), Fills, Fill);
|
||||
var stroke = PickColor(Items.IndexOf(data), Strokes, Stroke);
|
||||
|
||||
<Path @key="@path" D="@path" Stroke="@stroke" StrokeWidth="@StrokeWidth" Fill="@fill" LineType="@LineType" Style="@style" />
|
||||
}
|
||||
</g>;
|
||||
}
|
||||
}
|
||||
248
Radzen.Blazor/RadzenStackedColumnSeries.razor.cs
Normal file
248
Radzen.Blazor/RadzenStackedColumnSeries.razor.cs
Normal file
@@ -0,0 +1,248 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Radzen.Blazor.Rendering;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// Renders column series in <see cref="RadzenChart" />
|
||||
/// </summary>
|
||||
/// <typeparam name="TItem">The type of the series data item.</typeparam>
|
||||
public partial class RadzenStackedColumnSeries<TItem> : CartesianSeries<TItem>, IChartStackedColumnSeries
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies the fill (background color) of the column series.
|
||||
/// </summary>
|
||||
/// <value>The fill.</value>
|
||||
[Parameter]
|
||||
public string Fill { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Specifies a list of colors that will be used to set the individual column backgrounds.
|
||||
/// </summary>
|
||||
/// <value>The fills.</value>
|
||||
[Parameter]
|
||||
public IEnumerable<string> Fills { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the stroke (border color) of the column series.
|
||||
/// </summary>
|
||||
/// <value>The stroke.</value>
|
||||
[Parameter]
|
||||
public string Stroke { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Specifies a list of colors that will be used to set the individual column borders.
|
||||
/// </summary>
|
||||
/// <value>The strokes.</value>
|
||||
[Parameter]
|
||||
public IEnumerable<string> Strokes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the width of the stroke (border).
|
||||
/// </summary>
|
||||
/// <value>The width of the stroke.</value>
|
||||
[Parameter]
|
||||
public double StrokeWidth { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the type of the line used to render the column border.
|
||||
/// </summary>
|
||||
/// <value>The type of the line.</value>
|
||||
[Parameter]
|
||||
public LineType LineType { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Color
|
||||
{
|
||||
get
|
||||
{
|
||||
return Fill;
|
||||
}
|
||||
}
|
||||
|
||||
int IChartStackedColumnSeries.Count
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Items == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return Items.Count();
|
||||
}
|
||||
}
|
||||
|
||||
double IChartStackedColumnSeries.ValueAt(int index)
|
||||
{
|
||||
if (Items == null || index < 0 || index >= Items.Count)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return Value(Items[index]);
|
||||
}
|
||||
|
||||
private IList<IChartSeries> ColumnSeries => Chart.Series.Where(series => series is IChartStackedColumnSeries).Cast<IChartSeries>().ToList();
|
||||
|
||||
private IList<IChartSeries> VisibleColumnSeries => ColumnSeries.Where(series => series.Visible).ToList();
|
||||
|
||||
private IList<IChartStackedColumnSeries> StackedColumnSeries => VisibleColumnSeries.Cast<IChartStackedColumnSeries>().ToList();
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override string TooltipStyle(TItem item)
|
||||
{
|
||||
var style = base.TooltipStyle(item);
|
||||
|
||||
var index = Items.IndexOf(item);
|
||||
|
||||
if (index >= 0)
|
||||
{
|
||||
var color = PickColor(index, Fills, Fill);
|
||||
|
||||
if (color != null)
|
||||
{
|
||||
style = $"{style}; border-color: {color};";
|
||||
}
|
||||
}
|
||||
|
||||
return style;
|
||||
}
|
||||
|
||||
private double BandWidth
|
||||
{
|
||||
get
|
||||
{
|
||||
var columnSeries = VisibleColumnSeries;
|
||||
|
||||
if (Chart.ColumnOptions.Width.HasValue)
|
||||
{
|
||||
return Chart.ColumnOptions.Width.Value * columnSeries.Count + Chart.ColumnOptions.Margin * (columnSeries.Count - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
var availableWidth = Chart.CategoryScale.OutputSize - (Chart.CategoryAxis.Padding * 2);
|
||||
var bands = columnSeries.Cast<IChartStackedColumnSeries>().Max(series => series.Count) + 2;
|
||||
return availableWidth / bands;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool Contains(double x, double y, double tolerance)
|
||||
{
|
||||
return DataAt(x, y) != null;
|
||||
}
|
||||
|
||||
double ColumnWidth => Chart.ColumnOptions.Width ?? BandWidth - Chart.ColumnOptions.Margin;
|
||||
|
||||
private double GetColumnLeft(TItem item, Func<TItem, double> category = null)
|
||||
{
|
||||
category = category ?? ComposeCategory(Chart.CategoryScale);
|
||||
|
||||
return category(item) - ColumnWidth / 2;
|
||||
}
|
||||
|
||||
private double GetColumnTop(TItem item, int columnIndex, int index, IEnumerable<IChartStackedColumnSeries> stackedColumnSeries)
|
||||
{
|
||||
var count = stackedColumnSeries.Max(series => series.Count);
|
||||
var sum = stackedColumnSeries.Take(columnIndex).Sum(series => series.ValueAt(index));
|
||||
|
||||
var y = Chart.ValueScale.Scale(Value(item) + sum);
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
private double GetColumnBottom(int columnIndex, int index, IEnumerable<IChartStackedColumnSeries> stackedColumnSeries)
|
||||
{
|
||||
var ticks = Chart.ValueScale.Ticks(Chart.ValueAxis.TickDistance);
|
||||
|
||||
var sum = stackedColumnSeries.Take(columnIndex).Sum(series => series.ValueAt(index));
|
||||
|
||||
return Chart.ValueScale.Scale(Math.Max(0, Math.Max(ticks.Start, sum)));
|
||||
}
|
||||
|
||||
int ColumnIndex => VisibleColumnSeries.IndexOf(this);
|
||||
|
||||
/// <inheritdoc />
|
||||
internal override double TooltipX(TItem item)
|
||||
{
|
||||
return GetColumnLeft(item) + ColumnWidth / 2;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
internal override double TooltipY(TItem item)
|
||||
{
|
||||
return GetColumnTop(item, ColumnIndex, Items.IndexOf(item), StackedColumnSeries);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override object DataAt(double x, double y)
|
||||
{
|
||||
var category = ComposeCategory(Chart.CategoryScale);
|
||||
var columnIndex = ColumnIndex;
|
||||
var width = ColumnWidth;
|
||||
var stackedColumnSeries = StackedColumnSeries;
|
||||
|
||||
for (var index = 0; index < Items.Count; index++)
|
||||
{
|
||||
var data = Items[index];
|
||||
var startX = GetColumnLeft(data, category);
|
||||
var endX = startX + width;
|
||||
var dataY = GetColumnTop(data, columnIndex, index, stackedColumnSeries);
|
||||
var y0 = GetColumnBottom(columnIndex, index, stackedColumnSeries);
|
||||
var startY = Math.Min(dataY, y0);
|
||||
var endY = Math.Max(dataY, y0);
|
||||
|
||||
if (startX <= x && x <= endX && startY <= y && y <= endY)
|
||||
{
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override IEnumerable<ChartDataLabel> GetDataLabels(double offsetX, double offsetY)
|
||||
{
|
||||
var list = new List<ChartDataLabel>();
|
||||
var stackedColumnSeries = StackedColumnSeries;
|
||||
var columnIndex = ColumnIndex;
|
||||
|
||||
for (var index = 0; index < Items.Count; index++)
|
||||
{
|
||||
var data = Items[index];
|
||||
var top = GetColumnTop(data, columnIndex, index, stackedColumnSeries);
|
||||
var bottom = GetColumnBottom(columnIndex, index, stackedColumnSeries);
|
||||
var y = top + (bottom - top) / 2;
|
||||
|
||||
list.Add(new ChartDataLabel
|
||||
{
|
||||
Position = new Point { X = TooltipX(data) + offsetX, Y = y + offsetY },
|
||||
TextAnchor = "middle",
|
||||
Text = Chart.ValueAxis.Format(Chart.ValueScale, Value(data))
|
||||
});
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override ScaleBase TransformValueScale(ScaleBase scale)
|
||||
{
|
||||
var stackedColumnSeries = ColumnSeries.Cast<IChartStackedColumnSeries>();
|
||||
var count = stackedColumnSeries.Max(series => series.Count);
|
||||
var sums = Enumerable.Range(0, count).Select(i => stackedColumnSeries.Sum(series => series.ValueAt(i)));
|
||||
var max = sums.Max();
|
||||
var min = Items.Min(Value);
|
||||
|
||||
scale.Input.MergeWidth(new ScaleRange { Start = min, End = max });
|
||||
|
||||
return scale;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,5 +2,5 @@
|
||||
@if (Visible)
|
||||
{
|
||||
<input @ref="@Element" disabled="@Disabled" readonly="@ReadOnly" name="@Name" style="@Style" @attributes="Attributes" class="@GetCssClass()" tabindex="@(Disabled ? "-1" : $"{TabIndex}")"
|
||||
placeholder="@Placeholder" maxlength="@MaxLength" autocomplete="@(AutoComplete ? "on" : "off")" value="@Value" @onchange="@OnChange" id="@GetId()" />
|
||||
placeholder="@Placeholder" maxlength="@MaxLength" autocomplete="@AutoCompleteAttribute" value="@Value" @onchange="@OnChange" id="@GetId()" />
|
||||
}
|
||||
@@ -27,6 +27,17 @@ namespace Radzen.Blazor
|
||||
[Parameter]
|
||||
public bool AutoComplete { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating the type of built-in autocomplete
|
||||
/// the browser should use.
|
||||
/// <see cref="Blazor.AutoCompleteType" />
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The type of built-in autocomplete.
|
||||
/// </value>
|
||||
[Parameter]
|
||||
public AutoCompleteType AutoCompleteType { get; set; } = AutoCompleteType.On;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the maximum allowed text length.
|
||||
/// </summary>
|
||||
@@ -68,5 +79,16 @@ namespace Radzen.Blazor
|
||||
{
|
||||
return GetClassList("rz-textbox").ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the autocomplete attribute's string value.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>off</c> if the AutoComplete parameter is false or the
|
||||
/// AutoCompleteType parameter is "off". When the AutoComplete
|
||||
/// parameter is true, the value is <c>on</c> or, if set, the value of
|
||||
/// AutoCompleteType.</value>
|
||||
public string AutoCompleteAttribute { get => !AutoComplete ? "off" :
|
||||
AutoCompleteType.GetAutoCompleteValue(); }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -274,7 +274,14 @@ namespace Radzen.Blazor
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clear the current selection to allow re-selection by mouse click
|
||||
/// </summary>
|
||||
public void ClearSelection()
|
||||
{
|
||||
SelectedItem?.Unselect();
|
||||
SelectedItem = null;
|
||||
}
|
||||
internal async Task ExpandItem(RadzenTreeItem item)
|
||||
{
|
||||
var args = new TreeExpandEventArgs()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
@using Radzen
|
||||
@using Radzen.Blazor.Rendering
|
||||
@implements IDisposable
|
||||
<li class="rz-treenode">
|
||||
<li class="rz-treenode" @attributes="Attributes">
|
||||
<div class=@ContentClassList @onclick="@Select">
|
||||
@if (ChildContent != null || HasChildren)
|
||||
{
|
||||
|
||||
@@ -13,6 +13,9 @@ namespace Radzen.Blazor
|
||||
/// </summary>
|
||||
public partial class RadzenTreeItem : IDisposable
|
||||
{
|
||||
[Parameter(CaptureUnmatchedValues = true)]
|
||||
public IReadOnlyDictionary<string, object> Attributes { get; set; }
|
||||
|
||||
ClassList ContentClassList => ClassList.Create("rz-treenode-content")
|
||||
.Add("rz-treenode-content-selected", selected);
|
||||
ClassList IconClassList => ClassList.Create("rz-tree-toggler rzi")
|
||||
|
||||
31
Radzen.Blazor/RadzenYearPlannerView.razor
Normal file
31
Radzen.Blazor/RadzenYearPlannerView.razor
Normal file
@@ -0,0 +1,31 @@
|
||||
@using Radzen.Blazor
|
||||
@using Radzen.Blazor.Rendering
|
||||
|
||||
@inherits SchedulerViewBase
|
||||
|
||||
@code {
|
||||
public override RenderFragment Render()
|
||||
{
|
||||
var appointments = Scheduler.GetAppointmentsInRange(StartDate, EndDate);
|
||||
|
||||
var maxAppointmentsInSlot = 0;
|
||||
|
||||
if (MaxAppointmentsInSlot != null)
|
||||
{
|
||||
maxAppointmentsInSlot = MaxAppointmentsInSlot.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
var slotHeight = (Scheduler.Height - 60) / 12;
|
||||
maxAppointmentsInSlot = Convert.ToInt32(Math.Floor(slotHeight / 16)) - 1;
|
||||
}
|
||||
|
||||
return @<CascadingValue Value=@Scheduler>
|
||||
<YearPlannerView StartDate=@StartDate
|
||||
EndDate=@EndDate
|
||||
MaxAppointmentsInSlot=@maxAppointmentsInSlot
|
||||
MoreText=@MoreText
|
||||
Appointments=@appointments />
|
||||
</CascadingValue>;
|
||||
}
|
||||
}
|
||||
83
Radzen.Blazor/RadzenYearPlannerView.razor.cs
Normal file
83
Radzen.Blazor/RadzenYearPlannerView.razor.cs
Normal file
@@ -0,0 +1,83 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Radzen.Blazor.Rendering;
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// Displays the appointments in a month day in <see cref="RadzenScheduler{TItem}" />
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// <RadzenScheduler Data="@appointments">
|
||||
/// <RadzenMonthView />
|
||||
/// </RadzenScheduler>
|
||||
/// </code>
|
||||
/// </example>
|
||||
public partial class RadzenYearPlannerView : SchedulerViewBase
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string Icon => "view_list";
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Title
|
||||
{
|
||||
get => Scheduler.CurrentDate.ToString("yyyy", Scheduler.Culture);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[Parameter]
|
||||
public override string Text { get; set; } = "Planner";
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the maximum appointnments to render in a slot.
|
||||
/// </summary>
|
||||
/// <value>The maximum appointments in slot.</value>
|
||||
[Parameter]
|
||||
public int? MaxAppointmentsInSlot { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the text displayed when there are more appointments in a slot than <see cref="MaxAppointmentsInSlot" />.
|
||||
/// </summary>
|
||||
/// <value>The more text. Set to <c>"+ {0} more"</c> by default.</value>
|
||||
[Parameter]
|
||||
public string MoreText { get; set; } = "+{0}";
|
||||
|
||||
/// <inheritdoc />
|
||||
public override DateTime StartDate
|
||||
{
|
||||
get
|
||||
{
|
||||
var d = new DateTime(Scheduler.CurrentDate.Date.Year, 1, 1).StartOfWeek();
|
||||
if (d.DayOfWeek == DateTimeFormatInfo.CurrentInfo.FirstDayOfWeek) d.AddDays(-7);
|
||||
|
||||
return d;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override DateTime EndDate
|
||||
{
|
||||
get
|
||||
{
|
||||
var d = new DateTime(Scheduler.CurrentDate.Date.Year, 1, 1).AddDays(DateTime.IsLeapYear(Scheduler.CurrentDate.Date.Year) ? 366 : 365).EndOfWeek();
|
||||
|
||||
return d;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override DateTime Next()
|
||||
{
|
||||
return Scheduler.CurrentDate.Date.AddYears(1);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override DateTime Prev()
|
||||
{
|
||||
return Scheduler.CurrentDate.Date.AddYears(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
31
Radzen.Blazor/RadzenYearTimelineView.razor
Normal file
31
Radzen.Blazor/RadzenYearTimelineView.razor
Normal file
@@ -0,0 +1,31 @@
|
||||
@using Radzen.Blazor
|
||||
@using Radzen.Blazor.Rendering
|
||||
|
||||
@inherits SchedulerViewBase
|
||||
|
||||
@code {
|
||||
public override RenderFragment Render()
|
||||
{
|
||||
var appointments = Scheduler.GetAppointmentsInRange(StartDate, EndDate);
|
||||
|
||||
var maxAppointmentsInSlot = 0;
|
||||
|
||||
if (MaxAppointmentsInSlot != null)
|
||||
{
|
||||
maxAppointmentsInSlot = MaxAppointmentsInSlot.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
var slotHeight = 100.0;
|
||||
maxAppointmentsInSlot = Convert.ToInt32(Math.Floor(slotHeight / 24)) - 1;
|
||||
}
|
||||
|
||||
return @<CascadingValue Value=@Scheduler>
|
||||
<YearTimelineView StartDate=@StartDate
|
||||
EndDate=@EndDate
|
||||
MaxAppointmentsInSlot=@maxAppointmentsInSlot
|
||||
MoreText=@MoreText
|
||||
Appointments=@appointments />
|
||||
</CascadingValue>;
|
||||
}
|
||||
}
|
||||
83
Radzen.Blazor/RadzenYearTimelineView.razor.cs
Normal file
83
Radzen.Blazor/RadzenYearTimelineView.razor.cs
Normal file
@@ -0,0 +1,83 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Radzen.Blazor.Rendering;
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// Displays the appointments in a month day in <see cref="RadzenScheduler{TItem}" />
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// <RadzenScheduler Data="@appointments">
|
||||
/// <RadzenMonthView />
|
||||
/// </RadzenScheduler>
|
||||
/// </code>
|
||||
/// </example>
|
||||
public partial class RadzenYearTimelineView : SchedulerViewBase
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string Icon => "view_timeline";
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Title
|
||||
{
|
||||
get => Scheduler.CurrentDate.ToString("yyyy", Scheduler.Culture);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[Parameter]
|
||||
public override string Text { get; set; } = "Timeline";
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the maximum appointnments to render in a slot.
|
||||
/// </summary>
|
||||
/// <value>The maximum appointments in slot.</value>
|
||||
[Parameter]
|
||||
public int? MaxAppointmentsInSlot { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the text displayed when there are more appointments in a slot than <see cref="MaxAppointmentsInSlot" />.
|
||||
/// </summary>
|
||||
/// <value>The more text. Set to <c>"+ {0} more"</c> by default.</value>
|
||||
[Parameter]
|
||||
public string MoreText { get; set; } = "+ {0} more";
|
||||
|
||||
/// <inheritdoc />
|
||||
public override DateTime StartDate
|
||||
{
|
||||
get
|
||||
{
|
||||
var d = new DateTime(Scheduler.CurrentDate.Date.Year, 1, 1).StartOfWeek();
|
||||
if (d.DayOfWeek == DateTimeFormatInfo.CurrentInfo.FirstDayOfWeek) d.AddDays(-7);
|
||||
|
||||
return d;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override DateTime EndDate
|
||||
{
|
||||
get
|
||||
{
|
||||
var d = new DateTime(Scheduler.CurrentDate.Date.Year, 1, 1).AddDays(DateTime.IsLeapYear(Scheduler.CurrentDate.Date.Year) ? 366 : 365).EndOfWeek();
|
||||
|
||||
return d;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override DateTime Next()
|
||||
{
|
||||
return Scheduler.CurrentDate.Date.AddYears(1);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override DateTime Prev()
|
||||
{
|
||||
return Scheduler.CurrentDate.Date.AddYears(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
17
Radzen.Blazor/RadzenYearView.razor
Normal file
17
Radzen.Blazor/RadzenYearView.razor
Normal file
@@ -0,0 +1,17 @@
|
||||
@using Radzen.Blazor
|
||||
@using Radzen.Blazor.Rendering
|
||||
|
||||
@inherits SchedulerViewBase
|
||||
|
||||
@code {
|
||||
public override RenderFragment Render()
|
||||
{
|
||||
var appointments = Scheduler.GetAppointmentsInRange(StartDate, EndDate);
|
||||
|
||||
var maxAppointmentsInSlot = 0;
|
||||
|
||||
return @<CascadingValue Value=@Scheduler>
|
||||
<YearView StartDate=@StartDate EndDate=@EndDate MaxAppointmentsInSlot=@maxAppointmentsInSlot MoreText=@MoreText Appointments=@appointments />
|
||||
</CascadingValue>;
|
||||
}
|
||||
}
|
||||
75
Radzen.Blazor/RadzenYearView.razor.cs
Normal file
75
Radzen.Blazor/RadzenYearView.razor.cs
Normal file
@@ -0,0 +1,75 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Radzen.Blazor.Rendering;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// Displays the appointments in a month day in <see cref="RadzenScheduler{TItem}" />
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// <RadzenScheduler Data="@appointments">
|
||||
/// <RadzenMonthView />
|
||||
/// </RadzenScheduler>
|
||||
/// </code>
|
||||
/// </example>
|
||||
public partial class RadzenYearView : SchedulerViewBase
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string Icon => "calendar_month";
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Title
|
||||
{
|
||||
get => Scheduler.CurrentDate.ToString("yyyy", Scheduler.Culture);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[Parameter]
|
||||
public override string Text { get; set; } = "Year";
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the text displayed when there are more appointments in a slot than <see cref="MaxAppointmentsInSlot" />.
|
||||
/// </summary>
|
||||
/// <value>The more text. Set to <c>"+ {0} more"</c> by default.</value>
|
||||
[Parameter]
|
||||
public string MoreText { get; set; } = "+ {0} more";
|
||||
|
||||
/// <inheritdoc />
|
||||
public override DateTime StartDate
|
||||
{
|
||||
get
|
||||
{
|
||||
var d = new DateTime(Scheduler.CurrentDate.Date.Year, 1, 1).StartOfWeek();
|
||||
if (d.DayOfWeek == DateTimeFormatInfo.CurrentInfo.FirstDayOfWeek) d.AddDays(-7);
|
||||
|
||||
return d;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override DateTime EndDate
|
||||
{
|
||||
get
|
||||
{
|
||||
var d = new DateTime(Scheduler.CurrentDate.Date.Year, 1, 1).AddDays(DateTime.IsLeapYear(Scheduler.CurrentDate.Date.Year) ? 366 : 365).EndOfWeek();
|
||||
|
||||
return d;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override DateTime Next()
|
||||
{
|
||||
return Scheduler.CurrentDate.Date.AddYears(1);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override DateTime Prev()
|
||||
{
|
||||
return Scheduler.CurrentDate.Date.AddYears(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,10 @@
|
||||
|
||||
<div class="rz-event" style=@Style @onclick=@OnClick>
|
||||
<div class="rz-event-content" title=@Data?.Text @attributes=@Attributes>
|
||||
@Scheduler.RenderAppointment(Data)
|
||||
@if (ShowAppointmentContent)
|
||||
{
|
||||
@Scheduler.RenderAppointment(Data)
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
@code {
|
||||
@@ -27,6 +30,9 @@
|
||||
[Parameter]
|
||||
public AppointmentData Data { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public bool ShowAppointmentContent { get; set; } = true;
|
||||
|
||||
[CascadingParameter]
|
||||
public IScheduler Scheduler { get; set; }
|
||||
|
||||
|
||||
@@ -1,6 +1,15 @@
|
||||
<button tabindex="-1" @onclick=@OnClick class=@Class disabled=@(Editor.Disabled || Disabled) @onmousedown=@Empty @onmousedown:preventDefault @onclick:preventDefault title=@Title>
|
||||
@if (PreventBlur)
|
||||
{
|
||||
<button tabindex="-1" @onclick=@OnClick class=@Class disabled=@(Editor.Disabled || Disabled || !EnabledModes.HasFlag(Editor.GetMode())) @onmousedown=@Empty @onmousedown:preventDefault @onclick:preventDefault title=@Title>
|
||||
<i class="rzi">@Icon</i>
|
||||
</button>
|
||||
}
|
||||
else
|
||||
{
|
||||
<button tabindex="-1" @onclick=@OnClick class=@Class disabled=@(Editor.Disabled || Disabled || !EnabledModes.HasFlag(Editor.GetMode())) title=@Title>
|
||||
<i class="rzi">@Icon</i>
|
||||
</button>
|
||||
}
|
||||
@code {
|
||||
[CascadingParameter]
|
||||
public RadzenHtmlEditor Editor { get; set; }
|
||||
@@ -11,12 +20,18 @@
|
||||
[Parameter]
|
||||
public bool Disabled { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public bool PreventBlur { get; set; } = true;
|
||||
|
||||
[Parameter]
|
||||
public bool Selected { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string Icon { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public HtmlEditorMode EnabledModes { get; set; } = HtmlEditorMode.Design;
|
||||
|
||||
[Parameter]
|
||||
public EventCallback Click { get; set; }
|
||||
|
||||
@@ -31,7 +46,7 @@
|
||||
{
|
||||
var classList = new List<string>() { "rz-html-editor-button" };
|
||||
|
||||
if (Selected && !Editor.Disabled)
|
||||
if (Selected && !Editor.Disabled && EnabledModes.HasFlag(Editor.GetMode()))
|
||||
{
|
||||
classList.Add("rz-selected");
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<div title=@Title class="rz-html-editor-colorpicker" @onmousedown:preventDefault>
|
||||
<button tabindex="-1" class="rz-html-editor-color" @onclick=@OnClick disabled=@Editor.Disabled @onclick:preventDefault>
|
||||
<button tabindex="-1" class="rz-html-editor-color" @onclick=@OnClick disabled=@(Editor.Disabled || !EnabledModes.HasFlag(Editor.GetMode())) @onclick:preventDefault>
|
||||
<i class="rzi">@Icon</i>
|
||||
<div class="rz-html-editor-color-value" style="background-color:@Value"></div>
|
||||
</button>
|
||||
<RadzenColorPicker
|
||||
@bind-Value=@Value Change=@OnChange @onclick:stopPropagation
|
||||
Open=@OnOpen Disabled=@Editor.Disabled ShowHSV=@ShowHSV
|
||||
<RadzenColorPicker
|
||||
@bind-Value=@Value Change=@OnChange @onclick:stopPropagation
|
||||
Open=@OnOpen Disabled=@(Editor.Disabled || !EnabledModes.HasFlag(Editor.GetMode())) ShowHSV=@ShowHSV
|
||||
ShowRGBA=@ShowRGBA ShowColors=@ShowColors ShowButton=@ShowButton
|
||||
HexText=@HexText RedText=@RedText GreenText=@GreenText BlueText=@BlueText AlphaText=@AlphaText
|
||||
ButtonText=@ButtonText
|
||||
@@ -30,6 +30,9 @@
|
||||
[Parameter]
|
||||
public string Value { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public HtmlEditorMode EnabledModes { get; set; } = HtmlEditorMode.Design;
|
||||
|
||||
[Parameter]
|
||||
public bool ShowHSV { get; set; } = true;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
@inherits RadzenComponent
|
||||
@using Microsoft.JSInterop
|
||||
<div title=@Title @ref=@Element class=@Class @onclick=@Toggle @onmousedown:preventDefault @attributes=@Attributes>
|
||||
<div title=@Title @ref=@Element class=@Class @onclick=@Toggle @onmousedown:preventDefault @attributes=@Attributes disabled=@(Editor.Disabled || !EnabledModes.HasFlag(Editor.GetMode()))>
|
||||
<div class="rz-html-editor-dropdown-value">
|
||||
@if (SelectedItem != null)
|
||||
{
|
||||
@@ -11,7 +11,7 @@
|
||||
@Placeholder
|
||||
}
|
||||
</div>
|
||||
<button @onclick:preventDefault tabindex="-1" class="rz-html-editor-dropdown-trigger" disabled=@Editor.Disabled><i class="rzi" /></button>
|
||||
<button @onclick:preventDefault tabindex="-1" class="rz-html-editor-dropdown-trigger" disabled=@(Editor.Disabled || !EnabledModes.HasFlag(Editor.GetMode()))><i class="rzi" /></button>
|
||||
<Popup @ref=Popup class="rz-html-editor-dropdown-items" Style=@PopupStyle>
|
||||
<CascadingValue Value=@this>
|
||||
@ChildContent
|
||||
@@ -22,7 +22,7 @@
|
||||
[CascadingParameter]
|
||||
public RadzenHtmlEditor Editor { get; set; }
|
||||
|
||||
Popup Popup { get; set; }
|
||||
Popup Popup { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string Title { get; set; }
|
||||
@@ -36,9 +36,12 @@
|
||||
[Parameter]
|
||||
public string Placeholder { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public HtmlEditorMode EnabledModes { get; set; } = HtmlEditorMode.Design;
|
||||
|
||||
async Task Toggle()
|
||||
{
|
||||
if (!Editor.Disabled)
|
||||
if (!Editor.Disabled && EnabledModes.HasFlag(Editor.GetMode()))
|
||||
{
|
||||
await Popup.ToggleAsync(Element);
|
||||
}
|
||||
@@ -57,7 +60,7 @@
|
||||
|
||||
internal async Task Select(EditorDropDownItem item, bool change)
|
||||
{
|
||||
if (SelectedItem != item && !Editor.Disabled)
|
||||
if (SelectedItem != item && !Editor.Disabled && EnabledModes.HasFlag(Editor.GetMode()))
|
||||
{
|
||||
SelectedItem = item;
|
||||
|
||||
@@ -78,7 +81,7 @@
|
||||
{
|
||||
var classList = new List<string>() { "rz-html-editor-dropdown" };
|
||||
|
||||
if (Editor.Disabled)
|
||||
if (Editor.Disabled || !EnabledModes.HasFlag(Editor.GetMode()))
|
||||
{
|
||||
classList.Add("rz-disabled");
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
@if (InPlotArea(x, y))
|
||||
{
|
||||
<Marker X="@x" Y="@y" Type="@MarkerType" Fill="@Fill" Stroke="@Stroke" StrokeWidth="@StrokeWidth" Size="@Size" />
|
||||
<Marker Click="@(() => OnClick(data))" X="@x" Y="@y" Type="@MarkerType" Fill="@Fill" Stroke="@Stroke" StrokeWidth="@StrokeWidth" Size="@Size" />
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,12 +15,20 @@
|
||||
[CascadingParameter]
|
||||
public RadzenChart Chart { get; set;}
|
||||
|
||||
[Parameter]
|
||||
public IChartSeries Series { get; set; }
|
||||
|
||||
private async Task OnClick(TItem data)
|
||||
{
|
||||
await Series.InvokeClick(Chart.SeriesClick, data);
|
||||
}
|
||||
|
||||
[Parameter]
|
||||
public IEnumerable<TItem> Data { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public Func<TItem, double> Category { get; set; }
|
||||
|
||||
|
||||
[Parameter]
|
||||
public Func<TItem, double> Value { get; set; }
|
||||
|
||||
|
||||
@@ -18,17 +18,18 @@
|
||||
style.Append($"fill: {Fill};");
|
||||
}
|
||||
|
||||
if (StrokeWidth != null)
|
||||
if (StrokeWidth >= 0)
|
||||
{
|
||||
style.Append($"stroke-width: {StrokeWidth.ToInvariantString()};");
|
||||
}
|
||||
|
||||
if (Style != null)
|
||||
if (!string.IsNullOrEmpty(Style))
|
||||
{
|
||||
foreach (var value in Style.Split(';'))
|
||||
if (style.Length > 0)
|
||||
{
|
||||
style.Append(value);
|
||||
style.Append(";");
|
||||
}
|
||||
style.Append(Style);
|
||||
}
|
||||
|
||||
return style.ToString();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
@inherits RadzenComponent
|
||||
@using Microsoft.JSInterop
|
||||
<div @ref=@Element @onmousedown:preventDefault @attributes=@Attributes style=@Style id=@GetId()>
|
||||
<div @ref=@Element @attributes=@Attributes style=@Style id=@GetId()>
|
||||
@if (open || !Lazy)
|
||||
{
|
||||
@ChildContent
|
||||
|
||||
233
Radzen.Blazor/Rendering/YearPlannerView.razor
Normal file
233
Radzen.Blazor/Rendering/YearPlannerView.razor
Normal file
@@ -0,0 +1,233 @@
|
||||
@using Radzen
|
||||
@using Radzen.Blazor
|
||||
@using Radzen.Blazor.Rendering
|
||||
@inject DialogService DialogService
|
||||
|
||||
@{
|
||||
var points = new Dictionary<AppointmentData, double>();
|
||||
var startyear = StartDate.AddDays(7).Year;
|
||||
DateTime date = StartDate;
|
||||
DateTime realstart = StartDate;
|
||||
int daysinmonth;
|
||||
|
||||
const double NUMBER_DAYS_COLUMNS = 38.0;
|
||||
}
|
||||
|
||||
<div class="rz-view rz-planner-view">
|
||||
<div class="rz-view-header">
|
||||
<div class="rz-slot-header">
|
||||
</div>
|
||||
@for (var dateheader = StartDate; dateheader <= StartDate.AddDays(NUMBER_DAYS_COLUMNS - 1); dateheader = dateheader.AddDays(1))
|
||||
{
|
||||
<div class="rz-slot-header">
|
||||
@dateheader.ToString("dddd", Scheduler.Culture).Substring(0,3)
|
||||
</div>
|
||||
}
|
||||
<div class="rz-slot-header">
|
||||
</div>
|
||||
</div>
|
||||
@for (int month = 1; month < 13; month++)
|
||||
{
|
||||
realstart = new DateTime(startyear, month, 1);
|
||||
daysinmonth = DateTime.DaysInMonth(startyear, month);
|
||||
date = realstart.StartOfMonth().StartOfWeek();
|
||||
|
||||
<div class="rz-month">
|
||||
<div class="rz-events">
|
||||
@for (var start = date; start < date.AddDays(NUMBER_DAYS_COLUMNS); start = start.AddDays(1))
|
||||
{
|
||||
var end = start.AddDays(1);
|
||||
var appointments = AppointmentsInSlot(start, end);
|
||||
var excessCount = appointments.Count() - MaxAppointmentsInSlot;
|
||||
var existingTops = ExistingTops(points, appointments.Take(MaxAppointmentsInSlot));
|
||||
if (start.Month == month)
|
||||
{
|
||||
@foreach (var item in appointments.Take(MaxAppointmentsInSlot))
|
||||
{
|
||||
var startSlotIndex = realstart.Subtract(date).Days + 1;
|
||||
var slotIndex = startSlotIndex + item.Start.Date.Subtract(realstart).Days;
|
||||
var slotWidth = 100 / 40.0;
|
||||
var left = slotIndex * slotWidth;
|
||||
|
||||
var length = Math.Max(1, Math.Ceiling(item.End.Subtract(realstart).TotalDays) - (slotIndex - startSlotIndex));
|
||||
var width = item.End <= realstart.AddDays(daysinmonth - 1) ? (length) * slotWidth : (daysinmonth + startSlotIndex - slotIndex) * slotWidth;
|
||||
if (!points.TryGetValue(item, out var top))
|
||||
{
|
||||
top = DetermineTop(existingTops);
|
||||
points.Add(item, top);
|
||||
existingTops.Add(top);
|
||||
}
|
||||
var height = 0.6;
|
||||
var data = item;
|
||||
|
||||
|
||||
@if (item.Start >= realstart && item.Start <= end)
|
||||
{
|
||||
<Appointment Data=@item Top=@top Left=@left Width=@width Height=@height Click=@OnAppointmentClick ShowAppointmentContent=false />
|
||||
}
|
||||
else if (realstart == start)
|
||||
{
|
||||
left = startSlotIndex * slotWidth;
|
||||
length = Math.Max(1, Math.Min(daysinmonth, Math.Ceiling(item.End.Subtract(date).TotalDays - (startSlotIndex - 1))));
|
||||
width = length * slotWidth;
|
||||
|
||||
<Appointment Data=@item Top=@top Left=@left Width=@width Height=@height Click=@OnAppointmentClick ShowAppointmentContent=false />
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@if (excessCount > 0)
|
||||
{
|
||||
var slotIndex = start.Subtract(date).Days;
|
||||
var slotWidth = 100 / 40.0;
|
||||
var left = (slotIndex + 1) * slotWidth;
|
||||
var top = ((MaxAppointmentsInSlot + 1) * 0.6) + 1.3;
|
||||
var listDate = start;
|
||||
<a class="rz-event-list-btn" style="top: @(top.ToInvariantString())em; left: @(left.ToInvariantString())%" @onclick=@(args => OnListClick(listDate, appointments))>@String.Format(MoreText, excessCount)</a>
|
||||
}
|
||||
}
|
||||
}
|
||||
</div>
|
||||
<div class="rz-slots">
|
||||
<div @attributes=@Attributes(realstart, "rz-slot")>
|
||||
<div class="rz-slot-header">
|
||||
@realstart.ToString("MMM", Scheduler.Culture)
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@for (var day = 0; day < NUMBER_DAYS_COLUMNS; day++)
|
||||
{
|
||||
string dayType = "";
|
||||
var dayOfWeek = date.AddDays(day);
|
||||
bool slotInMonth = dayOfWeek.Month == month;
|
||||
|
||||
dayType = dayOfWeek.DayOfWeek == DayOfWeek.Saturday || dayOfWeek.DayOfWeek == DayOfWeek.Sunday ? "rz-weekend" : "";
|
||||
dayType = dayOfWeek.Month != month ? "rz-other-month" : dayType;
|
||||
|
||||
@if (slotInMonth)
|
||||
{
|
||||
<div @onclick="@(args => OnSlotClick(dayOfWeek))" @attributes=@Attributes(dayOfWeek, ($"rz-slot {dayType}"))>
|
||||
<div class="rz-slot-title">
|
||||
@if (dayOfWeek.Month == month)
|
||||
{
|
||||
@dayOfWeek.Day
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div @attributes=@Attributes(dayOfWeek, ($"rz-slot {dayType}"))>
|
||||
<div class="rz-slot-title">
|
||||
@if (dayOfWeek.Month == month)
|
||||
{
|
||||
@dayOfWeek.Day
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
<div @attributes=@Attributes(realstart, "rz-slot")>
|
||||
<div class="rz-slot-header">
|
||||
@realstart.ToString("MMM", Scheduler.Culture)
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public DateTime StartDate { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public DateTime EndDate { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public int MaxAppointmentsInSlot { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string MoreText { get; set; }
|
||||
|
||||
[CascadingParameter]
|
||||
public IScheduler Scheduler { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public IEnumerable<AppointmentData> Appointments { get; set; }
|
||||
|
||||
IDictionary<string, object> Attributes(DateTime start, string className)
|
||||
{
|
||||
var attributes = Scheduler.GetSlotAttributes(start, start.AddDays(1));
|
||||
attributes["class"] = ClassList.Create(className).Add(attributes).ToString();
|
||||
return attributes;
|
||||
}
|
||||
|
||||
async Task OnSlotClick(DateTime date)
|
||||
{
|
||||
await Scheduler.SelectSlot(date, date.AddDays(1));
|
||||
}
|
||||
|
||||
double DetermineTop(HashSet<double> existingTops)
|
||||
{
|
||||
var top = 1.2;
|
||||
|
||||
while (existingTops.Contains(top))
|
||||
{
|
||||
top += 0.6;
|
||||
}
|
||||
|
||||
return top;
|
||||
}
|
||||
|
||||
HashSet<double> ExistingTops(IDictionary<AppointmentData, double> tops, IEnumerable<AppointmentData> appointments)
|
||||
{
|
||||
var existingTops = new HashSet<double>();
|
||||
|
||||
foreach (var appointment in appointments)
|
||||
{
|
||||
if (tops.TryGetValue(appointment, out var existingTop))
|
||||
{
|
||||
existingTops.Add(existingTop);
|
||||
}
|
||||
}
|
||||
|
||||
return existingTops;
|
||||
}
|
||||
|
||||
async Task OnAppointmentClick(AppointmentData data)
|
||||
{
|
||||
await Scheduler.SelectAppointment(data);
|
||||
}
|
||||
|
||||
private AppointmentData[] AppointmentsInSlot(DateTime start, DateTime end)
|
||||
{
|
||||
if (Appointments == null)
|
||||
{
|
||||
return Array.Empty<AppointmentData>();
|
||||
}
|
||||
|
||||
return Appointments.Where(item => Scheduler.IsAppointmentInRange(item, start, end)).OrderBy(item => item.Start).ThenByDescending(item => item.End).ToArray();
|
||||
}
|
||||
|
||||
async Task OnListClick(DateTime date, IEnumerable<AppointmentData> appointments)
|
||||
{
|
||||
await DialogService.OpenAsync(date.ToShortDateString(), ds =>
|
||||
@<div class="rz-event-list">
|
||||
<CascadingValue Value=@Scheduler>
|
||||
@foreach (var item in appointments)
|
||||
{
|
||||
<Appointment Data=@item Click="OnListEventClick" />
|
||||
}
|
||||
</CascadingValue>
|
||||
</div>);
|
||||
}
|
||||
|
||||
async Task OnListEventClick(AppointmentData data)
|
||||
{
|
||||
DialogService.Close();
|
||||
|
||||
await OnAppointmentClick(data);
|
||||
}
|
||||
}
|
||||
226
Radzen.Blazor/Rendering/YearTimelineView.razor
Normal file
226
Radzen.Blazor/Rendering/YearTimelineView.razor
Normal file
@@ -0,0 +1,226 @@
|
||||
@using Radzen
|
||||
@using Radzen.Blazor
|
||||
@using Radzen.Blazor.Rendering
|
||||
@inject DialogService DialogService
|
||||
|
||||
@{
|
||||
var points = new Dictionary<AppointmentData, double>();
|
||||
var startyear = StartDate.AddDays(7).Year;
|
||||
DateTime date = StartDate;
|
||||
DateTime realstart = StartDate;
|
||||
int daysinmonth;
|
||||
|
||||
const double NUMBER_DAYS_COLUMNS = 37.0;
|
||||
const double SLOT_WIDTH = 100.0;
|
||||
const double CALENDAR_WIDTH = 3800.0;
|
||||
}
|
||||
|
||||
<div class="rz-view rz-timeline-view">
|
||||
<div class="rz-view-header">
|
||||
<div class="rz-slot-header">
|
||||
</div>
|
||||
@for (var dateheader = StartDate; dateheader <= StartDate.AddDays(NUMBER_DAYS_COLUMNS - 1); dateheader = dateheader.AddDays(1))
|
||||
{
|
||||
<div class="rz-slot-header">
|
||||
@dateheader.ToString("dddd", Scheduler.Culture)
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
@for (int month = 1; month < 13; month++)
|
||||
{
|
||||
realstart = new DateTime(startyear, month, 1);
|
||||
daysinmonth = DateTime.DaysInMonth(startyear, month);
|
||||
date = realstart.StartOfMonth().StartOfWeek();
|
||||
|
||||
<div class="rz-month">
|
||||
<div class="rz-events">
|
||||
@for (var start = date; start < date.AddDays(NUMBER_DAYS_COLUMNS); start = start.AddDays(1))
|
||||
{
|
||||
var end = start.AddDays(1);
|
||||
var appointments = AppointmentsInSlot(start, end);
|
||||
var excessCount = appointments.Count() - MaxAppointmentsInSlot;
|
||||
var existingTops = ExistingTops(points, appointments.Take(MaxAppointmentsInSlot));
|
||||
if (start.Month == month)
|
||||
{
|
||||
@foreach (var item in appointments.Take(MaxAppointmentsInSlot))
|
||||
{
|
||||
var startSlotIndex = realstart.Subtract(date).Days + 1;
|
||||
var slotIndex = startSlotIndex + item.Start.Date.Subtract(realstart).Days;
|
||||
var slotWidth = (SLOT_WIDTH / CALENDAR_WIDTH) * 100;
|
||||
var left = slotIndex * slotWidth;
|
||||
|
||||
var length = Math.Max(1, Math.Ceiling(item.End.Subtract(realstart).TotalDays) - (slotIndex - startSlotIndex));
|
||||
var width = item.End <= realstart.AddDays(daysinmonth - 1) ? (length) * slotWidth : (daysinmonth + startSlotIndex - slotIndex) * slotWidth;
|
||||
if (!points.TryGetValue(item, out var top))
|
||||
{
|
||||
top = DetermineTop(existingTops);
|
||||
points.Add(item, top);
|
||||
existingTops.Add(top);
|
||||
}
|
||||
var height = 1.5;
|
||||
var data = item;
|
||||
|
||||
|
||||
@if (item.Start >= realstart && item.Start <= end)
|
||||
{
|
||||
<Appointment Data=@item Top=@top Left=@left Width=@width Height=@height Click=@OnAppointmentClick />
|
||||
}
|
||||
else if (realstart == start)
|
||||
{
|
||||
left = startSlotIndex * slotWidth;
|
||||
length = Math.Max(1, Math.Min(daysinmonth, Math.Ceiling(item.End.Subtract(date).TotalDays - (startSlotIndex - 1))));
|
||||
width = length * slotWidth;
|
||||
|
||||
<Appointment Data=@item Top=@top Left=@left Width=@width Height=@height Click=@OnAppointmentClick />
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@if (excessCount > 0)
|
||||
{
|
||||
var slotIndex = start.Subtract(date).Days;
|
||||
var slotWidth = (SLOT_WIDTH / CALENDAR_WIDTH) * 100;
|
||||
var left = ((slotIndex + 1) * slotWidth) + (100.0 / 85.0);
|
||||
var top = ((MaxAppointmentsInSlot + 1) * 1.5) + 1.7;
|
||||
var listDate = start;
|
||||
<a class="rz-event-list-btn" style="top: @(top.ToInvariantString())em; left: @(left.ToInvariantString())%" @onclick=@(args => OnListClick(listDate, appointments))>@String.Format(MoreText, excessCount)</a>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
<div class="rz-slots">
|
||||
<div @attributes=@Attributes(realstart, "rz-slot")>
|
||||
<div class="rz-slot-header">
|
||||
@realstart.ToString("MMMM", Scheduler.Culture)
|
||||
</div>
|
||||
</div>
|
||||
@for (var day = 0; day < NUMBER_DAYS_COLUMNS; day++)
|
||||
{
|
||||
string dayType = "";
|
||||
var dayOfWeek = date.AddDays(day);
|
||||
bool slotInMonth = dayOfWeek.Month == month;
|
||||
|
||||
dayType = dayOfWeek.DayOfWeek == DayOfWeek.Saturday || dayOfWeek.DayOfWeek == DayOfWeek.Sunday ? "rz-weekend" : "";
|
||||
dayType = dayOfWeek.Month != month ? "rz-other-month" : dayType;
|
||||
|
||||
@if (slotInMonth)
|
||||
{
|
||||
<div @onclick="@(args => OnSlotClick(dayOfWeek))" @attributes=@Attributes(dayOfWeek, ($"rz-slot {dayType}"))>
|
||||
<div class="rz-slot-title">
|
||||
@if (dayOfWeek.Month == month)
|
||||
{
|
||||
@dayOfWeek.Day
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div @attributes=@Attributes(dayOfWeek, ($"rz-slot {dayType}"))>
|
||||
<div class="rz-slot-title">
|
||||
@if (dayOfWeek.Month == month)
|
||||
{
|
||||
@dayOfWeek.Day
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public DateTime StartDate { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public DateTime EndDate { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public int MaxAppointmentsInSlot { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string MoreText { get; set; }
|
||||
|
||||
[CascadingParameter]
|
||||
public IScheduler Scheduler { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public IEnumerable<AppointmentData> Appointments { get; set; }
|
||||
|
||||
IDictionary<string, object> Attributes(DateTime start, string className)
|
||||
{
|
||||
var attributes = Scheduler.GetSlotAttributes(start, start.AddDays(1));
|
||||
attributes["class"] = ClassList.Create(className).Add(attributes).ToString();
|
||||
return attributes;
|
||||
}
|
||||
|
||||
async Task OnSlotClick(DateTime date)
|
||||
{
|
||||
await Scheduler.SelectSlot(date, date.AddDays(1));
|
||||
}
|
||||
|
||||
double DetermineTop(HashSet<double> existingTops)
|
||||
{
|
||||
var top = 1.5;
|
||||
|
||||
while (existingTops.Contains(top))
|
||||
{
|
||||
top += 1.5;
|
||||
}
|
||||
|
||||
return top;
|
||||
}
|
||||
|
||||
HashSet<double> ExistingTops(IDictionary<AppointmentData, double> tops, IEnumerable<AppointmentData> appointments)
|
||||
{
|
||||
var existingTops = new HashSet<double>();
|
||||
|
||||
foreach (var appointment in appointments)
|
||||
{
|
||||
if (tops.TryGetValue(appointment, out var existingTop))
|
||||
{
|
||||
existingTops.Add(existingTop);
|
||||
}
|
||||
}
|
||||
|
||||
return existingTops;
|
||||
}
|
||||
|
||||
async Task OnAppointmentClick(AppointmentData data)
|
||||
{
|
||||
await Scheduler.SelectAppointment(data);
|
||||
}
|
||||
|
||||
private AppointmentData[] AppointmentsInSlot(DateTime start, DateTime end)
|
||||
{
|
||||
if (Appointments == null)
|
||||
{
|
||||
return Array.Empty<AppointmentData>();
|
||||
}
|
||||
|
||||
return Appointments.Where(item => Scheduler.IsAppointmentInRange(item, start, end)).OrderBy(item => item.Start).ThenByDescending(item => item.End).ToArray();
|
||||
}
|
||||
|
||||
async Task OnListClick(DateTime date, IEnumerable<AppointmentData> appointments)
|
||||
{
|
||||
await DialogService.OpenAsync(date.ToShortDateString(), ds =>
|
||||
@<div class="rz-event-list">
|
||||
<CascadingValue Value=@Scheduler>
|
||||
@foreach (var item in appointments)
|
||||
{
|
||||
<Appointment Data=@item Click="OnListEventClick" />
|
||||
}
|
||||
</CascadingValue>
|
||||
</div>);
|
||||
}
|
||||
|
||||
async Task OnListEventClick(AppointmentData data)
|
||||
{
|
||||
DialogService.Close();
|
||||
|
||||
await OnAppointmentClick(data);
|
||||
}
|
||||
}
|
||||
193
Radzen.Blazor/Rendering/YearView.razor
Normal file
193
Radzen.Blazor/Rendering/YearView.razor
Normal file
@@ -0,0 +1,193 @@
|
||||
@using Radzen
|
||||
@using Radzen.Blazor
|
||||
@using Radzen.Blazor.Rendering
|
||||
@inject DialogService DialogService
|
||||
|
||||
@{
|
||||
var points = new Dictionary<AppointmentData, double>();
|
||||
|
||||
// delaci check usage
|
||||
var year = StartDate.AddDays(7).Year;
|
||||
|
||||
DateTime date = StartDate.AddDays(7);
|
||||
DateTime realstart = StartDate;
|
||||
int daysinmonth;
|
||||
}
|
||||
|
||||
|
||||
<div class="rz-view rz-year-view">
|
||||
<div class="rz-display-flex rz-row rz-align-items-normal rz-justify-content-space-between">
|
||||
@for (int month = 1; month < 13; month++)
|
||||
{
|
||||
realstart = new DateTime(year, month, 1);
|
||||
daysinmonth = DateTime.DaysInMonth(year, month);
|
||||
date = realstart.StartOfMonth().StartOfWeek();
|
||||
|
||||
<div class="rz-display-flex rz-flex-column rz-col-12 rz-col-sm-6 rz-col-md-4 rz-col-lg-3">
|
||||
|
||||
<div class="rz-slot-header rz-pb-2">
|
||||
<span class="rz-text-subtitle1">
|
||||
@realstart.ToString("MMMM yyyy")
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="rz-view-header">
|
||||
@for (var dateheader = StartDate; dateheader <= StartDate.EndOfWeek(); dateheader = dateheader.AddDays(1))
|
||||
{
|
||||
<div class="rz-slot-header">
|
||||
@dateheader.ToString("ddd", Scheduler.Culture).Substring(0,1)
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@for (var row = 0; row < 6; row++)
|
||||
{
|
||||
<div class="rz-week">
|
||||
<div class="rz-events">
|
||||
<div class="rz-slots">
|
||||
@for (var col = 0; col < 7; col++)
|
||||
{
|
||||
var day = date.AddDays((row * 7) + col);
|
||||
var appointments = AppointmentsInSlot(day, day.AddDays(1));
|
||||
var excessCount = appointments.Count();
|
||||
string classname;
|
||||
|
||||
@if (day.Month != month)
|
||||
{
|
||||
if (excessCount > 0)
|
||||
{
|
||||
classname = "rz-slot-title rz-other-month rz-has-appointments";
|
||||
<div @onclick=@(args => OnListClick(day, appointments)) @attributes=@Attributes(day, "rz-slot")>
|
||||
<div class="@classname">
|
||||
@day.Day
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
classname = "rz-slot-title rz-other-month";
|
||||
<div @onclick=@(args => OnListClick(day, appointments)) @attributes=@Attributes(day, "rz-slot")>
|
||||
<div class="@classname">
|
||||
@day.Day
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (excessCount > 0)
|
||||
{
|
||||
classname = "rz-slot-title rz-has-appointments";
|
||||
<div @onclick=@(args => OnListClick(day, appointments)) @attributes=@Attributes(day, "rz-slot")>
|
||||
<div class="@classname">
|
||||
@day.Day
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
classname = "rz-slot-title";
|
||||
<div @onclick=@(args => OnListClick(day, appointments)) @attributes=@Attributes(day, "rz-slot")>
|
||||
<div class="@classname">
|
||||
@day.Day
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<style>
|
||||
|
||||
|
||||
|
||||
</style>
|
||||
|
||||
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public DateTime StartDate { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public DateTime EndDate { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public int MaxAppointmentsInSlot { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string MoreText { get; set; }
|
||||
|
||||
[CascadingParameter]
|
||||
public IScheduler Scheduler { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public IEnumerable<AppointmentData> Appointments { get; set; }
|
||||
|
||||
IDictionary<string, object> Attributes(DateTime start, string className)
|
||||
{
|
||||
var attributes = Scheduler.GetSlotAttributes(start, start.AddDays(1));
|
||||
attributes["class"] = ClassList.Create(className).Add(attributes).ToString();
|
||||
return attributes;
|
||||
}
|
||||
|
||||
async Task OnSlotClick(DateTime date)
|
||||
{
|
||||
await Scheduler.SelectSlot(date, date.AddDays(1));
|
||||
}
|
||||
|
||||
async Task OnAppointmentClick(AppointmentData data)
|
||||
{
|
||||
await Scheduler.SelectAppointment(data);
|
||||
}
|
||||
|
||||
private AppointmentData[] AppointmentsInSlot(DateTime start, DateTime end)
|
||||
{
|
||||
if (Appointments == null)
|
||||
{
|
||||
return Array.Empty<AppointmentData>();
|
||||
}
|
||||
|
||||
return Appointments.Where(item => Scheduler.IsAppointmentInRange(item, start, end)).OrderBy(item => item.Start).ThenByDescending(item => item.End).ToArray();
|
||||
}
|
||||
|
||||
async Task OnListClick(DateTime date, IEnumerable<AppointmentData> appointments)
|
||||
{
|
||||
if (appointments.Count() > 0)
|
||||
{
|
||||
await DialogService.OpenAsync(date.ToShortDateString(), ds =>
|
||||
@<div class="rz-event-list">
|
||||
<CascadingValue Value=@Scheduler>
|
||||
@foreach (var item in appointments)
|
||||
{
|
||||
<Appointment Data=@item Click="OnListEventClick" />
|
||||
}
|
||||
</CascadingValue>
|
||||
</div>
|
||||
);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
await DialogService.OpenAsync(date.ToShortDateString(), ds =>
|
||||
@<div class="rz-event-list">
|
||||
There are no scheduled events taking place on this day
|
||||
</div>
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
async Task OnListEventClick(AppointmentData data)
|
||||
{
|
||||
DialogService.Close();
|
||||
|
||||
await OnAppointmentClick(data);
|
||||
}
|
||||
}
|
||||
@@ -96,10 +96,12 @@ namespace Radzen.Blazor
|
||||
private void ValidateField(object sender, FieldChangedEventArgs args)
|
||||
{
|
||||
var component = Form.FindComponent(Component);
|
||||
|
||||
if (args.FieldIdentifier.FieldName == component?.FieldIdentifier.FieldName)
|
||||
if (component != null)
|
||||
{
|
||||
ValidateModel(sender, ValidationRequestedEventArgs.Empty);
|
||||
if (args.FieldIdentifier.Equals(component.FieldIdentifier))
|
||||
{
|
||||
ValidateModel(sender, ValidationRequestedEventArgs.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,4 +171,4 @@ namespace Radzen.Blazor
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,18 @@
|
||||
}
|
||||
}
|
||||
|
||||
@mixin rz-utility-list-breakpoints-css($property, $list, $breakpoints) {
|
||||
@each $breakpoint, $breakpoint-value in $breakpoints {
|
||||
@media (min-width: #{$breakpoint-value}) {
|
||||
@each $value in $list {
|
||||
.rz-#{$property}-#{$breakpoint}-#{$value} {
|
||||
#{$property}: #{$value} !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@mixin rz-ripple($ripple-background: rgba(0,0,0,.12), $pseudo: false) {
|
||||
@if $pseudo == true {
|
||||
|
||||
|
||||
@@ -11,12 +11,15 @@ $button-hover-shadow: inset 0 -3px 0 0 rgba(255, 255, 255, 0.2) !default;
|
||||
$button-hover-gradient: linear-gradient(rgba(#fff, 0.1), rgba(#fff, 0.1)) !default;
|
||||
$button-hover-background-size: $button-background-size !default;
|
||||
|
||||
$button-focus-shadow: inset 0 -3px 0 0 rgba(255, 255, 255, 0.2) !default;
|
||||
$button-focus-gradient: linear-gradient(rgba(#fff, 0.1), rgba(#fff, 0.1)) !default;
|
||||
$button-focus-background-size: $button-background-size !default;
|
||||
$button-focus-outline: none !default;
|
||||
|
||||
$button-active-shadow: inset 0 3px 0 0 rgba(0, 0, 0, 0.1) !default;
|
||||
$button-active-gradient: linear-gradient(rgba(#000, 0.1), rgba(#000, 0.1)) !default;
|
||||
$button-active-background-size: $button-background-size !default;
|
||||
|
||||
$button-focus-outline: none !default;
|
||||
|
||||
$button-disabled-opacity: 0.2 !default;
|
||||
|
||||
$button-sizes: () !default;
|
||||
@@ -157,20 +160,23 @@ $button-styles: map-merge(
|
||||
:root {
|
||||
--rz-button-base-background-color: #{$button-base-background-color};
|
||||
--rz-button-base-color: #{$button-base-color};
|
||||
--rz-button-hover-shadow: #{$button-hover-shadow};
|
||||
--rz-button-hover-gradient: #{$button-hover-gradient};
|
||||
--rz-button-active-shadow: #{$button-active-shadow};
|
||||
--rz-button-active-gradient: #{$button-active-gradient};
|
||||
--rz-button-focus-outline: #{$button-focus-outline};
|
||||
--rz-button-background-size: #{$button-background-size};
|
||||
--rz-button-border-radius: #{$button-border-radius};
|
||||
--rz-button-shadow: #{$button-shadow};
|
||||
--rz-button-transition: #{$button-transition};
|
||||
--rz-button-disabled-opacity: #{$button-disabled-opacity};
|
||||
--rz-button-line-height: #{$button-line-height};
|
||||
--rz-button-vertical-align: #{$button-vertical-align};
|
||||
--rz-button-background-size: #{$button-background-size};
|
||||
--rz-button-hover-shadow: #{$button-hover-shadow};
|
||||
--rz-button-hover-gradient: #{$button-hover-gradient};
|
||||
--rz-button-hover-background-size: #{$button-hover-background-size};
|
||||
--rz-button-focus-shadow: #{$button-focus-shadow};
|
||||
--rz-button-focus-gradient: #{$button-focus-gradient};
|
||||
--rz-button-focus-background-size: #{$button-focus-background-size};
|
||||
--rz-button-focus-outline: #{$button-focus-outline};
|
||||
--rz-button-active-shadow: #{$button-active-shadow};
|
||||
--rz-button-active-gradient: #{$button-active-gradient};
|
||||
--rz-button-active-background-size: #{$button-active-background-size};
|
||||
--rz-button-disabled-opacity: #{$button-disabled-opacity};
|
||||
}
|
||||
|
||||
.rz-button {
|
||||
@@ -205,6 +211,15 @@ $button-styles: map-merge(
|
||||
}
|
||||
}
|
||||
|
||||
&:focus {
|
||||
&:not(:active) {
|
||||
text-decoration: none;
|
||||
background-image: var(--rz-button-focus-gradient);
|
||||
background-size: var(--rz-button-focus-background-size);
|
||||
box-shadow: var(--rz-button-focus-shadow);
|
||||
}
|
||||
}
|
||||
|
||||
&:active {
|
||||
text-decoration: none;
|
||||
background-image: var(--rz-button-active-gradient);
|
||||
@@ -315,6 +330,7 @@ $button-styles: map-merge(
|
||||
background-color: transparent;
|
||||
|
||||
&:not(.rz-state-disabled):hover:not(:active),
|
||||
&:not(.rz-state-disabled):focus:not(:active),
|
||||
&:not(.rz-state-disabled):active {
|
||||
&.rz-shade-lighter {
|
||||
color: var(--rz-#{$style})
|
||||
@@ -366,6 +382,7 @@ $button-styles: map-merge(
|
||||
box-shadow: none;
|
||||
|
||||
&:not(.rz-state-disabled):hover:not(:active),
|
||||
&:not(.rz-state-disabled):focus:not(:active),
|
||||
&:not(.rz-state-disabled):active {
|
||||
&.rz-shade-lighter {
|
||||
color: var(--rz-#{$style})
|
||||
|
||||
@@ -76,36 +76,6 @@ $chart-color-schemes: (
|
||||
--rz-chart-tooltip-color: #{$chart-tooltip-color};
|
||||
}
|
||||
|
||||
.chart,
|
||||
.pie {
|
||||
height: 200px;
|
||||
|
||||
.ngx-charts {
|
||||
overflow: visible !important;
|
||||
|
||||
.gridline-path {
|
||||
stroke: var(--rz-chart-axis-color);
|
||||
}
|
||||
}
|
||||
|
||||
.chart-legend {
|
||||
.legend-labels {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.legend-title {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tick {
|
||||
text {
|
||||
fill: var(--rz-chart-axis-label-color);
|
||||
font-size: var(--rz-chart-axis-font-size) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.rz-chart {
|
||||
position: relative;
|
||||
height: 300px;
|
||||
|
||||
@@ -58,8 +58,8 @@ $colorpicker-input-labels-color: var(--rz-text-tertiary-color) !default;
|
||||
|
||||
@extend %input;
|
||||
|
||||
&.rz-disabled {
|
||||
color: var(--rz-text-color);
|
||||
&.rz-state-disabled {
|
||||
@extend %input-disabled;
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
@@ -80,6 +80,11 @@ button.rz-colorpicker-trigger {
|
||||
content: 'arrow_drop_down';
|
||||
}
|
||||
}
|
||||
|
||||
.rz-state-disabled & {
|
||||
color: var(--rz-input-disabled-color);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.rz-colorpicker-popup {
|
||||
|
||||
@@ -79,6 +79,7 @@ $multiselect-checkbox-margin: 0 0.5rem 0 0 !default;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
text-align: start;
|
||||
|
||||
@extend %input;
|
||||
|
||||
|
||||
@@ -43,6 +43,19 @@ $editor-content-background-color: var(--rz-base-background-color) !default;
|
||||
background-color: var(--rz-editor-content-background-color);
|
||||
}
|
||||
|
||||
.rz-html-editor-source.rz-textarea {
|
||||
--rz-input-hover-shadow: none;
|
||||
--rz-input-border: none;
|
||||
--rz-input-hover-border: none;
|
||||
--rz-input-focus-shadow: none;
|
||||
--rz-input-focus-border: none;
|
||||
flex: 1;
|
||||
padding: 0.5rem;
|
||||
overflow: auto;
|
||||
outline: none;
|
||||
background-color: var(--rz-editor-content-background-color);
|
||||
}
|
||||
|
||||
.rz-html-editor-toolbar {
|
||||
border-bottom: var(--rz-editor-border);
|
||||
display: flex;
|
||||
@@ -206,19 +219,15 @@ $editor-content-background-color: var(--rz-base-background-color) !default;
|
||||
background-color: var(--rz-editor-separator-background-color);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.rz-html-editor-toolbar {
|
||||
|
||||
|
||||
.rz-html-editor-colorpicker {
|
||||
.rz-colorpicker {
|
||||
&:not(:disabled):not(.rz-state-disabled):hover {
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.rz-colorpicker-trigger {
|
||||
.rzi {
|
||||
font-size: 1.25rem;
|
||||
|
||||
@@ -776,11 +776,36 @@ $column-draggable-shadow: 0 8px 10px 0 rgba(0, 0, 0, 0.1) !default;
|
||||
td,
|
||||
.rz-cell-data {
|
||||
transition: background-color var(--rz-transition), color var(--rz-transition);
|
||||
|
||||
&.rz-frozen-cell {
|
||||
&:before,
|
||||
&:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
transition: background-color var(--rz-transition), color var(--rz-transition);
|
||||
}
|
||||
|
||||
&:before {
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
&:after {
|
||||
z-index: -2;
|
||||
background-color: var(--rz-grid-frozen-cell-background-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.rz-state-highlight {
|
||||
> td {
|
||||
background-color: var(--rz-grid-selected-background-color);
|
||||
|
||||
&.rz-frozen-cell {
|
||||
&:before {
|
||||
background-color: var(--rz-grid-selected-background-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.rz-cell-data {
|
||||
@@ -799,8 +824,14 @@ $column-draggable-shadow: 0 8px 10px 0 rgba(0, 0, 0, 0.1) !default;
|
||||
|
||||
&:hover {
|
||||
&:not(.rz-state-highlight) {
|
||||
> td:not(.rz-frozen-cell) {
|
||||
> td {
|
||||
background-color: var(--rz-grid-hover-background-color);
|
||||
|
||||
&.rz-frozen-cell {
|
||||
&:before {
|
||||
background-color: var(--rz-grid-hover-background-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.rz-cell-data {
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
cursor: pointer;
|
||||
|
||||
.rz-link-text {
|
||||
vertical-align: middle;
|
||||
text-decoration: var(--rz-link-text-decoration)
|
||||
}
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ $listbox-header-icon-margin: 0 !default;
|
||||
background-color: var(--rz-listbox-background-color);
|
||||
border: var(--rz-listbox-border);
|
||||
border-radius: var(--rz-listbox-border-radius);
|
||||
text-align: start;
|
||||
|
||||
.rz-chkbox {
|
||||
margin: var(--rz-listbox-checkbox-margin);
|
||||
|
||||
@@ -80,8 +80,6 @@ $paginator-button-size: ".rz-button-md" !default;
|
||||
--rz-paginator-summary-padding: #{$paginator-summary-padding};
|
||||
--rz-paginator-summary-font-size: #{$paginator-summary-font-size};
|
||||
--rz-paginator-summary-color: #{$paginator-summary-color};
|
||||
|
||||
--rz-paginator-button-size: #{$paginator-button-size};
|
||||
}
|
||||
|
||||
.rz-paginator {
|
||||
@@ -318,3 +316,19 @@ $paginator-button-size: ".rz-button-md" !default;
|
||||
margin: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
// Density
|
||||
.rz-paginator {
|
||||
&.rz-density-compact {
|
||||
--rz-paginator-padding: 0.25rem;
|
||||
--rz-paginator-numeric-button-margin: 0 0.125rem;
|
||||
--rz-paginator-first-button-margin: 0 0.25rem 0 0;
|
||||
--rz-paginator-last-button-margin: 0 0 0 0.25rem;
|
||||
--rz-paginator-dropdown-margin: 0 0 0 0.25rem;
|
||||
--rz-paginator-summary-padding: 0 0.5rem 0 0;
|
||||
|
||||
.rz-paginator-element {
|
||||
@extend .rz-button-sm;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ $scheduler-view-selected-border-color: $scheduler-view-selected-background-color
|
||||
|
||||
$scheduler-header-background-color: var(--rz-base-200) !default;
|
||||
$scheduler-header-font-size: 0.75rem !default;
|
||||
$scheduler-header-font-size-small: 0.5rem !default;
|
||||
$scheduler-header-text-transform: uppercase !default;
|
||||
$scheduler-header-color: inherit !default;
|
||||
$scheduler-header-border: var(--rz-border-normal) !default;
|
||||
@@ -55,10 +56,26 @@ $scheduler-event-list-button-color: var(--rz-secondary);
|
||||
$scheduler-event-list-button-font-size: 0.75rem;
|
||||
|
||||
$scheduler-slot-title-font-size: 0.875rem !default;
|
||||
$scheduler-slot-title-font-size-small: 0.6rem !default;
|
||||
$scheduler-slot-title-padding: 0 0.25rem !default;
|
||||
|
||||
$scheduler-day-number-padding: 0 0.5rem !default;
|
||||
|
||||
$scheduler-weekend-color: var(--rz-text-disabled-color) !default;
|
||||
$scheduler-weekend-background-color: var(--rz-base-50) !default;
|
||||
$scheduler-other-month-background-color: var(--rz-base-100) !default;
|
||||
|
||||
$scheduler-timeline-slot-width: 7rem !default;
|
||||
$scheduler-timeline-slot-height: 7rem !default;
|
||||
|
||||
$scheduler-year-padding: 1.5rem !default;
|
||||
$scheduler-year-slot-padding: 1px !default;
|
||||
$scheduler-year-slot-title-width: 100% !default;
|
||||
$scheduler-year-slot-title-border-radius: 0.25rem !default;
|
||||
|
||||
$scheduler-planner-slot-width: 3rem !default;
|
||||
$scheduler-planner-slot-height: 4.5rem !default;
|
||||
|
||||
// Scheduler CSS variables
|
||||
|
||||
:root {
|
||||
@@ -98,6 +115,7 @@ $scheduler-day-number-padding: 0 0.5rem !default;
|
||||
|
||||
--rz-scheduler-header-background-color: #{$scheduler-header-background-color};
|
||||
--rz-scheduler-header-font-size: #{$scheduler-header-font-size};
|
||||
--rz-scheduler-header-font-size-small: #{$scheduler-header-font-size-small};
|
||||
--rz-scheduler-header-text-transform: #{$scheduler-header-text-transform};
|
||||
--rz-scheduler-header-color: #{$scheduler-header-color};
|
||||
--rz-scheduler-header-border: #{$scheduler-header-border};
|
||||
@@ -114,9 +132,25 @@ $scheduler-day-number-padding: 0 0.5rem !default;
|
||||
--rz-scheduler-event-list-button-font-size: #{$scheduler-event-list-button-font-size};
|
||||
|
||||
--rz-scheduler-slot-title-font-size: #{$scheduler-slot-title-font-size};
|
||||
--rz-scheduler-slot-title-font-size-small: #{$scheduler-slot-title-font-size-small};
|
||||
--rz-scheduler-slot-title-padding: #{$scheduler-slot-title-padding};
|
||||
|
||||
--rz-scheduler-day-number-padding: #{$scheduler-day-number-padding};
|
||||
|
||||
--rz-scheduler-weekend-color: #{$scheduler-weekend-color};
|
||||
--rz-scheduler-weekend-background-color: #{$scheduler-weekend-background-color};
|
||||
--rz-scheduler-other-month-background-color: #{$scheduler-other-month-background-color};
|
||||
|
||||
--rz-scheduler-timeline-slot-width: #{$scheduler-timeline-slot-width};
|
||||
--rz-scheduler-timeline-slot-height: #{$scheduler-timeline-slot-height};
|
||||
|
||||
--rz-scheduler-year-padding: #{$scheduler-year-padding};
|
||||
--rz-scheduler-year-slot-padding: #{$scheduler-year-slot-padding};
|
||||
--rz-scheduler-year-slot-title-width: #{$scheduler-year-slot-title-width};
|
||||
--rz-scheduler-year-slot-title-border-radius: #{$scheduler-year-slot-title-border-radius};
|
||||
|
||||
--rz-scheduler-planner-slot-width: #{$scheduler-planner-slot-width};
|
||||
--rz-scheduler-planner-slot-height: #{$scheduler-planner-slot-height};
|
||||
}
|
||||
|
||||
.rz-scheduler {
|
||||
@@ -152,6 +186,12 @@ $scheduler-day-number-padding: 0 0.5rem !default;
|
||||
border-left: 1px solid var(--rz-scheduler-border-color);
|
||||
}
|
||||
|
||||
.rz-slot-title {
|
||||
text-align: right;
|
||||
font-size: var(--rz-scheduler-slot-title-font-size);
|
||||
padding: var(--rz-scheduler-slot-title-padding);
|
||||
}
|
||||
|
||||
.rz-slot-hours {
|
||||
.rz-slot-header {
|
||||
height: 1.5rem;
|
||||
@@ -178,6 +218,7 @@ $scheduler-day-number-padding: 0 0.5rem !default;
|
||||
.rz-event {
|
||||
position: absolute;
|
||||
padding: var(--rz-scheduler-event-padding);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.rz-event-content {
|
||||
@@ -195,20 +236,6 @@ $scheduler-day-number-padding: 0 0.5rem !default;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.rz-month-view {
|
||||
.rz-view-content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
|
||||
.rz-slot-title {
|
||||
text-align: right;
|
||||
font-size: var(--rz-scheduler-slot-title-font-size);
|
||||
padding: var(--rz-scheduler-slot-title-padding);
|
||||
}
|
||||
|
||||
.rz-scheduler-nav {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
@@ -259,55 +286,11 @@ $scheduler-day-number-padding: 0 0.5rem !default;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.rz-week-view-content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.rz-slots {
|
||||
flex: 1;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.rz-week {
|
||||
flex: 1;
|
||||
font-size: 1rem;
|
||||
|
||||
.rz-slots {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
&:first-child .rz-slot {
|
||||
border-top: none;
|
||||
}
|
||||
}
|
||||
|
||||
.rz-month-view {
|
||||
.rz-slot {
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
|
||||
&:first-child {
|
||||
border-left: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.rz-day-view,
|
||||
.rz-week-view {
|
||||
.rz-slot:nth-of-type(2) {
|
||||
border-top: none;
|
||||
}
|
||||
}
|
||||
|
||||
.rz-week-view,
|
||||
.rz-day-view {
|
||||
.rz-view-header {
|
||||
padding-right: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.rz-scheduler-nav-views {
|
||||
display: flex;
|
||||
|
||||
@@ -371,6 +354,260 @@ $scheduler-day-number-padding: 0 0.5rem !default;
|
||||
}
|
||||
}
|
||||
|
||||
// Week range slots
|
||||
|
||||
.rz-week {
|
||||
flex: 1;
|
||||
font-size: 1rem;
|
||||
|
||||
.rz-slots {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
&:first-child .rz-slot {
|
||||
border-top: none;
|
||||
}
|
||||
}
|
||||
|
||||
// Month range slots
|
||||
.rz-month {
|
||||
flex: 1;
|
||||
font-size: 1rem;
|
||||
|
||||
.rz-slots {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
&:nth-child(2) .rz-slot {
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
.rz-slot {
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
border-top: 1px solid var(--rz-scheduler-border-color);
|
||||
border-left: 1px solid var(--rz-scheduler-border-color);
|
||||
|
||||
&:first-child {
|
||||
position: sticky;
|
||||
z-index: 9998;
|
||||
left: 0;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background-color: var(--rz-scheduler-header-background-color);
|
||||
border-left: none;
|
||||
border-right: 1px solid var(--rz-scheduler-border-color);
|
||||
|
||||
|
||||
.rz-slot-header {
|
||||
text-align: center;
|
||||
font-size: var(--rz-scheduler-header-font-size);
|
||||
padding: var(--rz-scheduler-header-padding);
|
||||
text-transform: var(--rz-scheduler-header-text-transform);
|
||||
color: var(--rz-scheduler-header-color);
|
||||
}
|
||||
}
|
||||
|
||||
&:nth-child(2) {
|
||||
border-left: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Day View
|
||||
|
||||
.rz-day-view{
|
||||
.rz-slot:nth-of-type(2) {
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
.rz-view-header {
|
||||
padding-right: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
// Week View
|
||||
|
||||
.rz-week-view-content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.rz-week-view {
|
||||
.rz-slot:nth-of-type(2) {
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
.rz-view-header {
|
||||
padding-right: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
// Month View
|
||||
|
||||
.rz-month-view {
|
||||
.rz-view-content {
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.rz-slot {
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
|
||||
&:first-child {
|
||||
border-left: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Planner View
|
||||
|
||||
.rz-planner-view {
|
||||
overflow: auto;
|
||||
|
||||
.rz-view-header {
|
||||
position: sticky;
|
||||
top: 0px;
|
||||
min-height: 2.25rem;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
.rz-month {
|
||||
.rz-slot {
|
||||
&:first-child {
|
||||
.rz-slot-header {
|
||||
writing-mode: vertical-lr;
|
||||
transform: rotate(-180deg);
|
||||
}
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background-color: var(--rz-scheduler-header-background-color);
|
||||
|
||||
.rz-slot-header {
|
||||
writing-mode: vertical-rl;
|
||||
text-align: center;
|
||||
font-size: var(--rz-scheduler-header-font-size);
|
||||
padding: var(--rz-scheduler-header-padding);
|
||||
text-transform: var(--rz-scheduler-header-text-transform);
|
||||
color: var(--rz-scheduler-header-color);
|
||||
}
|
||||
}
|
||||
|
||||
&.rz-other-month {
|
||||
background-color: var(--rz-scheduler-other-month-background-color);
|
||||
}
|
||||
|
||||
&.rz-weekend {
|
||||
color: var(--rz-scheduler-weekend-color);
|
||||
background-color: var(--rz-scheduler-weekend-background-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Timeline View
|
||||
|
||||
.rz-timeline-view {
|
||||
flex: auto;
|
||||
overflow: auto;
|
||||
flex-wrap: wrap;
|
||||
flex-direction: unset;
|
||||
|
||||
.rz-view-header {
|
||||
position: sticky;
|
||||
top: 0px;
|
||||
min-height: 36px;
|
||||
z-index: 9999;
|
||||
|
||||
.rz-slot-header {
|
||||
min-width: var(--rz-scheduler-timeline-slot-width);
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
}
|
||||
|
||||
.rz-month {
|
||||
flex: 0 0 auto;
|
||||
|
||||
.rz-slots {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.rz-slot {
|
||||
width: var(--rz-scheduler-timeline-slot-width);
|
||||
height: var(--rz-scheduler-timeline-slot-height);
|
||||
|
||||
&.rz-other-month {
|
||||
background-color: var(--rz-scheduler-other-month-background-color);
|
||||
}
|
||||
|
||||
&.rz-weekend {
|
||||
color: var(--rz-scheduler-weekend-color);
|
||||
background-color: var(--rz-scheduler-weekend-background-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Year View
|
||||
|
||||
.rz-year-view {
|
||||
overflow: auto;
|
||||
padding: var(--rz-scheduler-year-padding);
|
||||
--rz-gap: var(--rz-scheduler-year-padding);
|
||||
|
||||
.rz-flex-column,
|
||||
.rz-week {
|
||||
min-width: fit-content;
|
||||
}
|
||||
|
||||
.rz-slot {
|
||||
flex: 1;
|
||||
border-top: none;
|
||||
justify-content: center;
|
||||
height: initial;
|
||||
padding: var(--rz-scheduler-year-slot-padding);
|
||||
cursor: pointer;
|
||||
|
||||
.rz-slot-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
width: var(--rz-scheduler-year-slot-title-width);
|
||||
min-width: 2rem;
|
||||
min-height: 2rem;
|
||||
border-radius: var(--rz-scheduler-year-slot-title-border-radius);
|
||||
transition: var(--rz-datepicker-calendar-transition);
|
||||
|
||||
&.rz-other-month {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
&.rz-has-appointments {
|
||||
color: var(--rz-scheduler-event-color);
|
||||
background-color: var(--rz-scheduler-event-background-color)
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.rz-slot-title:not(.rz-has-appointments) {
|
||||
color: var(--rz-datepicker-calendar-hover-color);
|
||||
background: var(--rz-datepicker-calendar-hover-background-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Responsive Styles
|
||||
|
||||
@media (max-width: 576px) {
|
||||
.rz-scheduler-nav {
|
||||
.rz-scheduler-nav-prev-next {
|
||||
@@ -409,4 +646,31 @@ $scheduler-day-number-padding: 0 0.5rem !default;
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1399px) {
|
||||
.rz-planner-view {
|
||||
flex-wrap: wrap;
|
||||
flex-direction: unset;
|
||||
|
||||
.rz-view-header {
|
||||
.rz-slot-header {
|
||||
flex: 0 0 auto;
|
||||
width: var(--rz-scheduler-planner-slot-width);
|
||||
}
|
||||
}
|
||||
|
||||
.rz-month {
|
||||
flex: 0 0 auto;
|
||||
|
||||
.rz-slots {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.rz-slot {
|
||||
width: var(--rz-scheduler-planner-slot-width);
|
||||
height: var(--rz-scheduler-planner-slot-height);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,6 +115,49 @@ $text-align: (
|
||||
}
|
||||
}
|
||||
|
||||
// Text Align with responsive breakpoints
|
||||
@each $breakpoint, $breakpoint-value in $rz-breakpoints-map {
|
||||
@media (min-width: #{$breakpoint-value}) {
|
||||
@each $name, $property in $text-align {
|
||||
.rz-text-align-#{$breakpoint}-#{$name} {
|
||||
@each $property, $value in $property {
|
||||
#{$property}: #{$value} !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Text Wrap, NoWrap and Truncate
|
||||
.rz-text-wrap {
|
||||
white-space: normal !important;
|
||||
}
|
||||
|
||||
.rz-text-nowrap {
|
||||
white-space: nowrap !important;
|
||||
}
|
||||
|
||||
.rz-text-truncate {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
// Text Transform
|
||||
$text-transform: (
|
||||
capitalize: (text-transform: capitalize),
|
||||
uppercase: (text-transform: uppercase),
|
||||
lowercase: (text-transform: lowercase),
|
||||
) !default;
|
||||
|
||||
@each $name, $property in $text-transform {
|
||||
.rz-text-#{$name} {
|
||||
@each $property, $value in $property {
|
||||
#{$property}: #{$value};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Body
|
||||
@if $base == false {
|
||||
:root {
|
||||
|
||||
@@ -426,6 +426,7 @@ $rz-gutter-map: map-merge(
|
||||
// Example .rz-display-block
|
||||
$display: none, block, inline, inline-block, flex, inline-flex, grid, inline-grid;
|
||||
@include rz-utility-list-css('display', $display);
|
||||
@include rz-utility-list-breakpoints-css('display', $display, $rz-breakpoints-map);
|
||||
|
||||
// Justify-content
|
||||
// Example .rz-justify-content-center
|
||||
|
||||
@@ -294,6 +294,9 @@ $scheduler-header-background-color: var(--rz-base-700) !default;
|
||||
$scheduler-header-border: none !default;
|
||||
$scheduler-border-color: var(--rz-base-700) !default;
|
||||
$scheduler-minor-border-color: var(--rz-base-700) !default;
|
||||
$scheduler-weekend-color: var(--rz-text-tertiary-color) !default;
|
||||
$scheduler-weekend-background-color: var(--rz-base-700) !default;
|
||||
$scheduler-other-month-background-color: var(--rz-base-900) !default;
|
||||
|
||||
.rz-slot-minor {
|
||||
border-top: 1px dotted var(--rz-scheduler-minor-border-color) !important;
|
||||
|
||||
@@ -329,6 +329,9 @@ $scheduler-header-background-color: var(--rz-base-700) !default;
|
||||
$scheduler-header-border: none !default;
|
||||
$scheduler-border-color: var(--rz-base-700) !default;
|
||||
$scheduler-minor-border-color: var(--rz-base-700) !default;
|
||||
$scheduler-weekend-color: var(--rz-text-tertiary-color) !default;
|
||||
$scheduler-weekend-background-color: var(--rz-base-700) !default;
|
||||
$scheduler-other-month-background-color: var(--rz-base-900) !default;
|
||||
|
||||
.rz-slot-minor {
|
||||
border-top: 1px dotted var(--rz-scheduler-minor-border-color) !important;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user