mirror of
https://github.com/radzenhq/radzen-blazor.git
synced 2026-02-04 05:35:44 +00:00
Compare commits
1844 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
41d64f1b7c | ||
|
|
36023fdc35 | ||
|
|
8437cf279d | ||
|
|
d2e19cf3c7 | ||
|
|
9a90be6e79 | ||
|
|
903a4c78e2 | ||
|
|
19049bfea8 | ||
|
|
0c4e92ebec | ||
|
|
aefe937adc | ||
|
|
63eda04815 | ||
|
|
18c7783942 | ||
|
|
6c17e1e9c5 | ||
|
|
955355460e | ||
|
|
51a110b9a3 | ||
|
|
43da6c3656 | ||
|
|
411c916a26 | ||
|
|
c0cc14ec99 | ||
|
|
4f8dd8844c | ||
|
|
36f8f43aad | ||
|
|
534d7f570e | ||
|
|
599e514afc | ||
|
|
42054827a2 | ||
|
|
bfe517ef75 | ||
|
|
c585f3455d | ||
|
|
fe1d3dd82b | ||
|
|
92d503335b | ||
|
|
782f93169d | ||
|
|
0c12177091 | ||
|
|
cc90ff97e3 | ||
|
|
525230cf2d | ||
|
|
2df9ef3fca | ||
|
|
9de1b6d9d2 | ||
|
|
94b096259a | ||
|
|
4e7011f12b | ||
|
|
ff123ddcb4 | ||
|
|
9d98fefdef | ||
|
|
573bddb1ae | ||
|
|
8386848e0e | ||
|
|
5ba0220a74 | ||
|
|
d24cadcf00 | ||
|
|
fbe53df424 | ||
|
|
eb0347073e | ||
|
|
45907bdcca | ||
|
|
b5b8aaf731 | ||
|
|
d4eb749729 | ||
|
|
3e09882b0c | ||
|
|
a443b57ead | ||
|
|
3a430b3586 | ||
|
|
f09f8ba4eb | ||
|
|
c6a1560a0f | ||
|
|
805f596f1f | ||
|
|
bcee601d4c | ||
|
|
ea009e802b | ||
|
|
e421eaaf1a | ||
|
|
997cd88db8 | ||
|
|
ccc8fbde05 | ||
|
|
0fdf7721a7 | ||
|
|
96f1863711 | ||
|
|
ea9c7543d9 | ||
|
|
b69a02c878 | ||
|
|
4d9c792a25 | ||
|
|
7a6992845a | ||
|
|
f2deb8f402 | ||
|
|
c067b162b9 | ||
|
|
f1415d7583 | ||
|
|
14f23e79f1 | ||
|
|
a5a55e207c | ||
|
|
990337e4f4 | ||
|
|
c35cce7b34 | ||
|
|
cb36e60af7 | ||
|
|
65baef92b1 | ||
|
|
c624db6833 | ||
|
|
8aed964f47 | ||
|
|
3874cb93e1 | ||
|
|
f966d7ab99 | ||
|
|
2079705626 | ||
|
|
e0a56d350b | ||
|
|
181aa4f43b | ||
|
|
302ba9be44 | ||
|
|
77422c8dda | ||
|
|
eead43e0d9 | ||
|
|
87927d04aa | ||
|
|
aa1b4b2785 | ||
|
|
a7f1d7181d | ||
|
|
c4a50efa43 | ||
|
|
b30f7d95e2 | ||
|
|
845b8aac1b | ||
|
|
d449469a99 | ||
|
|
776ae01c7b | ||
|
|
a9951fc624 | ||
|
|
d8dfcd9cf7 | ||
|
|
fac6744ead | ||
|
|
0a539d1328 | ||
|
|
3e137d1c0e | ||
|
|
8391556f8f | ||
|
|
365374e73e | ||
|
|
19a118c096 | ||
|
|
62a5505c9d | ||
|
|
60dcb66805 | ||
|
|
51e6306c19 | ||
|
|
683453f63a | ||
|
|
366e042c60 | ||
|
|
e599d96b7f | ||
|
|
6f3fde82ef | ||
|
|
8ba561b55b | ||
|
|
79ac8e8cd8 | ||
|
|
cb809156f2 | ||
|
|
d8aa4dde98 | ||
|
|
938fd759c1 | ||
|
|
2740f54331 | ||
|
|
6f929e48b8 | ||
|
|
308db7888a | ||
|
|
657a5c5416 | ||
|
|
d12f3921f9 | ||
|
|
601957ba2a | ||
|
|
e12ffb1a75 | ||
|
|
25543b363b | ||
|
|
3e8ab559b2 | ||
|
|
9059f3f60b | ||
|
|
aa4ce25bda | ||
|
|
5ecd9e0782 | ||
|
|
ba84cc7ea6 | ||
|
|
7edae77736 | ||
|
|
b5f414623e | ||
|
|
58c92c94f6 | ||
|
|
3f0509b0b9 | ||
|
|
33858d2679 | ||
|
|
5d3b4fab0b | ||
|
|
6f998cffe9 | ||
|
|
1f520b904f | ||
|
|
94c49deaf7 | ||
|
|
4360896634 | ||
|
|
8513edc118 | ||
|
|
6dc08ede91 | ||
|
|
8f05520c2f | ||
|
|
0c3878a8fc | ||
|
|
e0d9fa6e95 | ||
|
|
ef5f613b0b | ||
|
|
8617557084 | ||
|
|
55c0fe05cc | ||
|
|
bdaaa9643e | ||
|
|
883ab83c91 | ||
|
|
6df9a499ef | ||
|
|
2bbb6919b6 | ||
|
|
44e0102073 | ||
|
|
a772a2dd51 | ||
|
|
8cd812cf33 | ||
|
|
dbf30f4869 | ||
|
|
3b5ec52a06 | ||
|
|
740e39fb46 | ||
|
|
44fff4fc0a | ||
|
|
acc3a0c9d4 | ||
|
|
e9f7f9d027 | ||
|
|
3ff9bcf853 | ||
|
|
18dd011a84 | ||
|
|
5ccfd4e838 | ||
|
|
b0baad56e7 | ||
|
|
0732938d1d | ||
|
|
1df2d8da9b | ||
|
|
dfdc7567f5 | ||
|
|
3453b7f84c | ||
|
|
59137196c6 | ||
|
|
8d686da3fb | ||
|
|
10aa459ebd | ||
|
|
a3737624fe | ||
|
|
70dd7d8744 | ||
|
|
8d52a98504 | ||
|
|
994166c88f | ||
|
|
2a9252b53b | ||
|
|
e8ff2a36be | ||
|
|
9ac700b758 | ||
|
|
1bf994384d | ||
|
|
0258389b61 | ||
|
|
8491807987 | ||
|
|
e95d07fee1 | ||
|
|
7b0d07e116 | ||
|
|
5228ed8543 | ||
|
|
8f5550576f | ||
|
|
c51e4b5411 | ||
|
|
ef3918f50c | ||
|
|
2b29e5371d | ||
|
|
249815607e | ||
|
|
b9f9138ae4 | ||
|
|
00296bacf2 | ||
|
|
18e6771fcc | ||
|
|
0c8131ebb3 | ||
|
|
831f0209ae | ||
|
|
488fc2719f | ||
|
|
ba98d6dfef | ||
|
|
45d9b69191 | ||
|
|
5205c94c73 | ||
|
|
953bc6370a | ||
|
|
7ffd7b10f5 | ||
|
|
2a054bce6e | ||
|
|
de1ed66aaa | ||
|
|
caeeee9109 | ||
|
|
3c9368b05f | ||
|
|
e31567727a | ||
|
|
7b761c50d7 | ||
|
|
11306a3ce5 | ||
|
|
9d23d4df1f | ||
|
|
45c35d1d37 | ||
|
|
7b1c7cbcb2 | ||
|
|
01b4431627 | ||
|
|
70b478a4b7 | ||
|
|
6e7d227504 | ||
|
|
962afaf613 | ||
|
|
ad0ba5d3bf | ||
|
|
6c729deb77 | ||
|
|
0e887d8b28 | ||
|
|
8fdaf68707 | ||
|
|
0bbbf70e81 | ||
|
|
1342c306a3 | ||
|
|
8890ae4520 | ||
|
|
72d6fa5454 | ||
|
|
1f700a80bc | ||
|
|
d9a25c88e7 | ||
|
|
e060b80b67 | ||
|
|
45687e665d | ||
|
|
5a3dffbc98 | ||
|
|
9e932f025f | ||
|
|
5ea729d0d0 | ||
|
|
67b6c52031 | ||
|
|
8b9c26c12b | ||
|
|
bede7d3fc9 | ||
|
|
cf2d4b890a | ||
|
|
3aa05efe9c | ||
|
|
ac00b513a8 | ||
|
|
7fb4f6de65 | ||
|
|
26251a2158 | ||
|
|
4a0b1f8f10 | ||
|
|
d6cce4a11b | ||
|
|
2ad79ea3d1 | ||
|
|
82ce761b88 | ||
|
|
d1241a6997 | ||
|
|
eb28720cd2 | ||
|
|
436a36a704 | ||
|
|
c2298b2ae0 | ||
|
|
9bc1431291 | ||
|
|
695a57153a | ||
|
|
b19ce01e2e | ||
|
|
d0c74b73dc | ||
|
|
673fce5054 | ||
|
|
9195f7ed31 | ||
|
|
baf97b205f | ||
|
|
13da03396f | ||
|
|
52846e3bf2 | ||
|
|
164c43e2e5 | ||
|
|
3af93df990 | ||
|
|
6026d27b18 | ||
|
|
ba8786c4fe | ||
|
|
5650349868 | ||
|
|
8bd3c32a65 | ||
|
|
07623acf41 | ||
|
|
446629b9f8 | ||
|
|
21dca42e33 | ||
|
|
7c5c9fc8be | ||
|
|
b2262ad4b8 | ||
|
|
4f7aba1e4b | ||
|
|
2bfbc68df8 | ||
|
|
682ae2ed59 | ||
|
|
a13705c1fe | ||
|
|
e4f4ba46f5 | ||
|
|
1f4b343a2e | ||
|
|
f4e01f42c5 | ||
|
|
7416ea1a54 | ||
|
|
b9593b7b4c | ||
|
|
43d7725522 | ||
|
|
d8d3a392b2 | ||
|
|
5a36e72616 | ||
|
|
e9bfe72914 | ||
|
|
db23f28388 | ||
|
|
46bd9a5324 | ||
|
|
d225b6d454 | ||
|
|
17fb991744 | ||
|
|
1035d413de | ||
|
|
9bbccb72e4 | ||
|
|
4b525256fb | ||
|
|
960059e307 | ||
|
|
0941627527 | ||
|
|
efea8c451b | ||
|
|
d9811f4ff1 | ||
|
|
11e6713f20 | ||
|
|
0d37538778 | ||
|
|
c88f8bb277 | ||
|
|
cd8a8ba310 | ||
|
|
9cb81c5fb8 | ||
|
|
e2d3dc1258 | ||
|
|
3c51397be8 | ||
|
|
84d51bf653 | ||
|
|
70c541b06f | ||
|
|
79a7095739 | ||
|
|
cf7fbf0b83 | ||
|
|
f1bf807b67 | ||
|
|
f02581d20a | ||
|
|
03450fc4f7 | ||
|
|
5e0eaa529f | ||
|
|
56184370a7 | ||
|
|
6fdc672dc4 | ||
|
|
ec82a24910 | ||
|
|
06157a9e5c | ||
|
|
a53022bac0 | ||
|
|
896c775fef | ||
|
|
f907d689e5 | ||
|
|
90a9850034 | ||
|
|
4418d348c5 | ||
|
|
7ce93da521 | ||
|
|
aeb08616b5 | ||
|
|
a10df3a133 | ||
|
|
c4039f5663 | ||
|
|
30df4a257a | ||
|
|
6f0df065ad | ||
|
|
8cfc5567d1 | ||
|
|
32defc6833 | ||
|
|
4485cf33df | ||
|
|
d7638ea764 | ||
|
|
d334a472ce | ||
|
|
19672dba39 | ||
|
|
24358eeb51 | ||
|
|
c1a823cd42 | ||
|
|
849c4982a8 | ||
|
|
032d6a1ae1 | ||
|
|
b012c48e62 | ||
|
|
76aa0f70aa | ||
|
|
1c3c525d2b | ||
|
|
9042b16df4 | ||
|
|
1f9198964b | ||
|
|
698513ea84 | ||
|
|
0cb68d9b5d | ||
|
|
221a0942ab | ||
|
|
c83fcc4602 | ||
|
|
b51abc68a8 | ||
|
|
9040c32f52 | ||
|
|
dc81c7244a | ||
|
|
62debd3df4 | ||
|
|
a048cf0f23 | ||
|
|
50ed79c0b3 | ||
|
|
b6963c7cab | ||
|
|
9f5af15987 | ||
|
|
5119048f33 | ||
|
|
090f45092c | ||
|
|
925e36e33b | ||
|
|
720b64ff90 | ||
|
|
4cd9f11f0b | ||
|
|
1b54504165 | ||
|
|
080e514527 | ||
|
|
392ed8b517 | ||
|
|
546701894d | ||
|
|
b90139aee4 | ||
|
|
5d39b554e0 | ||
|
|
51b9ab3661 | ||
|
|
b58672b8ec | ||
|
|
4148b57819 | ||
|
|
8a9f0ddd24 | ||
|
|
4ccc377f1c | ||
|
|
dc56d18595 | ||
|
|
ff78f68443 | ||
|
|
5b52b070d9 | ||
|
|
8f28becd6c | ||
|
|
14212a744a | ||
|
|
cb0af54ab4 | ||
|
|
b6b737a0cd | ||
|
|
092ec1a8f0 | ||
|
|
9476d8bbcd | ||
|
|
72e4a6ccc7 | ||
|
|
73d2c83d8e | ||
|
|
540b315213 | ||
|
|
9594014358 | ||
|
|
d3e781607d | ||
|
|
e9d6874ff5 | ||
|
|
729b43cd54 | ||
|
|
5278060aaa | ||
|
|
d25a1e8463 | ||
|
|
24e260dc0d | ||
|
|
ea6a010c5e | ||
|
|
07715fd541 | ||
|
|
6b9e0e60c5 | ||
|
|
1040b041a4 | ||
|
|
914dcced2b | ||
|
|
520d2bf0a8 | ||
|
|
886a09553f | ||
|
|
9436fa50b8 | ||
|
|
feae293d17 | ||
|
|
8eba025e02 | ||
|
|
060f5dfd6c | ||
|
|
e3e3bb2731 | ||
|
|
1082dd5aa4 | ||
|
|
aaba37325b | ||
|
|
fe225efde5 | ||
|
|
1726a45738 | ||
|
|
09f3ebec80 | ||
|
|
f8a4534496 | ||
|
|
299833b974 | ||
|
|
317a1cd8ca | ||
|
|
81d7ecde04 | ||
|
|
1377769eff | ||
|
|
1cbde75953 | ||
|
|
72d16e22be | ||
|
|
8fa6721a26 | ||
|
|
aeb2355d75 | ||
|
|
81a3adb483 | ||
|
|
8298a22023 | ||
|
|
c3612ec9a6 | ||
|
|
c05f158663 | ||
|
|
671851f345 | ||
|
|
1611429d83 | ||
|
|
a8593078ad | ||
|
|
6165c25976 | ||
|
|
47598a9d7a | ||
|
|
09c727e91a | ||
|
|
0619557f05 | ||
|
|
aa5a9c6c2d | ||
|
|
e3ad81926e | ||
|
|
37abd6d5b8 | ||
|
|
5a7499c80e | ||
|
|
ce3bb23b8c | ||
|
|
845d5b2351 | ||
|
|
08ee361c9c | ||
|
|
c6e6a4bd7d | ||
|
|
85b571594c | ||
|
|
5088c94db5 | ||
|
|
2dc9e9e04c | ||
|
|
2752c641ed | ||
|
|
4c0b6bff9d | ||
|
|
5acebc3e44 | ||
|
|
1e8c065fdb | ||
|
|
b35775b3e0 | ||
|
|
0693853c0a | ||
|
|
6994d12eb6 | ||
|
|
dc0dda35fc | ||
|
|
085fc2a764 | ||
|
|
7ecae9e3a2 | ||
|
|
61d687882f | ||
|
|
354eed23b9 | ||
|
|
99996613bc | ||
|
|
c6e7b1d68a | ||
|
|
69e9823640 | ||
|
|
6e74d02e95 | ||
|
|
397d3073c6 | ||
|
|
ecba921352 | ||
|
|
bea36fdcb5 | ||
|
|
0379e0ee6d | ||
|
|
787a48a795 | ||
|
|
ce257fcc95 | ||
|
|
becc50d2b8 | ||
|
|
673be6056c | ||
|
|
5c7b19527d | ||
|
|
4304099d3a | ||
|
|
5911968469 | ||
|
|
6afde15a1d | ||
|
|
ab578f499c | ||
|
|
e78c3bc6aa | ||
|
|
6394a8ee76 | ||
|
|
5f4e62824f | ||
|
|
f1966f42de | ||
|
|
704039afc2 | ||
|
|
b1c9b27f17 | ||
|
|
3a1c0a707a | ||
|
|
781c28044a | ||
|
|
76346a435a | ||
|
|
a4ebe3532b | ||
|
|
189c8c5a2a | ||
|
|
c1c50fcdb0 | ||
|
|
aad91c32d1 | ||
|
|
b80a84822e | ||
|
|
3e4f86d5fe | ||
|
|
3cb9fa6926 | ||
|
|
900fe003d4 | ||
|
|
3c923f7a20 | ||
|
|
6d95c85719 | ||
|
|
5a0bdb6358 | ||
|
|
49f8d7ac56 | ||
|
|
fd99d88510 | ||
|
|
29f37bbe43 | ||
|
|
1567dd6163 | ||
|
|
297d0b7466 | ||
|
|
7db378a8c8 | ||
|
|
3f5c73ca26 | ||
|
|
53f7ddcb82 | ||
|
|
1f54a40147 | ||
|
|
4c3cdaf593 | ||
|
|
af00eeaf2a | ||
|
|
ed5629f7cf | ||
|
|
88d1854b0d | ||
|
|
328cb3a4dc | ||
|
|
a1c83ebb10 | ||
|
|
d440a78c7b | ||
|
|
6e643d7cda | ||
|
|
0f705bd755 | ||
|
|
f436e44233 | ||
|
|
29f6c5907c | ||
|
|
a4d5015875 | ||
|
|
e8aa282a3a | ||
|
|
44dc55822d | ||
|
|
473bc16384 | ||
|
|
8984a1baf6 | ||
|
|
8fda96eabf | ||
|
|
5110c5d248 | ||
|
|
d23bdee6ed | ||
|
|
2f2ecbbeb0 | ||
|
|
867fe28c5f | ||
|
|
958cdc627a | ||
|
|
473aa9c429 | ||
|
|
846dd24dde | ||
|
|
c01823024d | ||
|
|
1cba327f24 | ||
|
|
c973edee05 | ||
|
|
6744926708 | ||
|
|
a5f040d69d | ||
|
|
0507f25e86 | ||
|
|
f782f18f04 | ||
|
|
ddb58f148d | ||
|
|
75904cf88c | ||
|
|
522deec88b | ||
|
|
4c07d608c5 | ||
|
|
c3490ac819 | ||
|
|
0ada1f2e46 | ||
|
|
6d7493c6e5 | ||
|
|
3306d8a276 | ||
|
|
d5b607eb72 | ||
|
|
af22c74602 | ||
|
|
1822850835 | ||
|
|
f185b9c30d | ||
|
|
d6c39e05f9 | ||
|
|
d7abef33a6 | ||
|
|
a0f6712c57 | ||
|
|
e81acee86b | ||
|
|
bbc9080cfa | ||
|
|
2095280783 | ||
|
|
d2b2e9a0d9 | ||
|
|
e62adf9131 | ||
|
|
4f22a869b8 | ||
|
|
8cf5868a30 | ||
|
|
f8d2b47006 | ||
|
|
71f0f53cae | ||
|
|
5b1fe105ba | ||
|
|
7f447ac21f | ||
|
|
425c7cd390 | ||
|
|
7f72143ee7 | ||
|
|
e743500d6c | ||
|
|
77e3952849 | ||
|
|
21dab1bf50 | ||
|
|
4e9aa726c6 | ||
|
|
004babb572 | ||
|
|
256c048598 | ||
|
|
59b884f4e4 | ||
|
|
45ff535d31 | ||
|
|
4cd8c53645 | ||
|
|
b856ef4ea6 | ||
|
|
ea3d83962f | ||
|
|
1d79076e65 | ||
|
|
1e6bae6801 | ||
|
|
6cda51ebbe | ||
|
|
e4c4c1b964 | ||
|
|
939c8c6d0e | ||
|
|
33c3963f66 | ||
|
|
88bfaa532d | ||
|
|
66e321ebea | ||
|
|
8d2838e928 | ||
|
|
98d896eb81 | ||
|
|
62bd56e70d | ||
|
|
bbc7e0f648 | ||
|
|
534c8e0bc3 | ||
|
|
1f9897e551 | ||
|
|
eba54c8da3 | ||
|
|
e47ac5b02d | ||
|
|
9d134f8171 | ||
|
|
1ec477b5bc | ||
|
|
022f203a2e | ||
|
|
191f21bf50 | ||
|
|
98c4b37664 | ||
|
|
2f2b40ca53 | ||
|
|
8a8be30657 | ||
|
|
0c0aafb956 | ||
|
|
c0bca5b923 | ||
|
|
55ea356efd | ||
|
|
fbcd357b69 | ||
|
|
41db619e28 | ||
|
|
1de8b11d75 | ||
|
|
b85f082d03 | ||
|
|
c2f08b47aa | ||
|
|
329784c9a7 | ||
|
|
1d357aab0a | ||
|
|
fe6deb559b | ||
|
|
591ef4d1f9 | ||
|
|
6a8a991f42 | ||
|
|
87161cb97a | ||
|
|
a28b667b38 | ||
|
|
62c8b4b9e9 | ||
|
|
bc0d5e2e7e | ||
|
|
a66ea60ae7 | ||
|
|
80f908353f | ||
|
|
a3a8ad87d3 | ||
|
|
ea52a7a9ec | ||
|
|
972042645c | ||
|
|
e01c8d4e13 | ||
|
|
351373aea5 | ||
|
|
287680df87 | ||
|
|
aa96a98722 | ||
|
|
58aa231cd2 | ||
|
|
d0a59e9d6f | ||
|
|
972c278356 | ||
|
|
d3b236107b | ||
|
|
ddd359afe0 | ||
|
|
0278777ff4 | ||
|
|
c8b703778b | ||
|
|
a0d49f8c29 | ||
|
|
93f9a318b0 | ||
|
|
bc6679505d | ||
|
|
5698e1a4fb | ||
|
|
61c39a8919 | ||
|
|
ae2e8b6abd | ||
|
|
e1bce30ee3 | ||
|
|
44da884057 | ||
|
|
7f9f05ae0e | ||
|
|
4638d173b6 | ||
|
|
43bc3cee06 | ||
|
|
2db68559d5 | ||
|
|
122b07b757 | ||
|
|
d6760ca4b9 | ||
|
|
fe036e75a3 | ||
|
|
a574e77f0a | ||
|
|
b4c885067d | ||
|
|
200fb9d9ee | ||
|
|
ec06fdcda6 | ||
|
|
fb31cc7268 | ||
|
|
afdbf2ac0b | ||
|
|
4197230ffd | ||
|
|
952e22367e | ||
|
|
a497660c64 | ||
|
|
bd3f4e08b2 | ||
|
|
c2e5aba0e4 | ||
|
|
729cf2c033 | ||
|
|
2633bd46c3 | ||
|
|
f6430d421e | ||
|
|
1045290320 | ||
|
|
0416bb20b3 | ||
|
|
cb7223dee1 | ||
|
|
59b535b0d8 | ||
|
|
6b9d2c19a7 | ||
|
|
3d7fbefa24 | ||
|
|
24311c2e71 | ||
|
|
93db8cc163 | ||
|
|
bdd833e05b | ||
|
|
64bcb9b4c3 | ||
|
|
6f2cf36ba6 | ||
|
|
4828af7130 | ||
|
|
0d0aa7c9a0 | ||
|
|
f0c962fde0 | ||
|
|
a04197f145 | ||
|
|
530e9b05ef | ||
|
|
5276b5f9f7 | ||
|
|
9a8f5f7186 | ||
|
|
7de2b3567d | ||
|
|
2a53fd6f13 | ||
|
|
1092fd4198 | ||
|
|
dd5619c1f9 | ||
|
|
06cffc101f | ||
|
|
5f17dae777 | ||
|
|
001a8a276f | ||
|
|
16986f0f56 | ||
|
|
36ff2808bd | ||
|
|
b566e10847 | ||
|
|
1b4fbf17a8 | ||
|
|
1475b1a299 | ||
|
|
147c5455ff | ||
|
|
73bfd9b66c | ||
|
|
f5fa061392 | ||
|
|
71b50171de | ||
|
|
a172caba24 | ||
|
|
ab39c3bbdb | ||
|
|
29733cc474 | ||
|
|
00a358cfb6 | ||
|
|
000475884d | ||
|
|
49b2cda0c2 | ||
|
|
fdf229400a | ||
|
|
c79d485d69 | ||
|
|
3f9aa621d1 | ||
|
|
c94c00d933 | ||
|
|
e540855bf9 | ||
|
|
e3d55f4e3d | ||
|
|
988fc92456 | ||
|
|
c02b153ef1 | ||
|
|
70ca4893ba | ||
|
|
4e15d3779c | ||
|
|
f924a18d07 | ||
|
|
bce1ec1c66 | ||
|
|
7c4347ad9b | ||
|
|
820c594c1e | ||
|
|
5c2d319b3a | ||
|
|
ff62cc55c2 | ||
|
|
dee872fec2 | ||
|
|
87b670ca4e | ||
|
|
60c4c2f526 | ||
|
|
6fd03f826c | ||
|
|
365cdb9fef | ||
|
|
4342602202 | ||
|
|
a168c10938 | ||
|
|
09da6f870a | ||
|
|
8a4b334d20 | ||
|
|
4f6916a2df | ||
|
|
14a9c94944 | ||
|
|
6ad0fda364 | ||
|
|
491c124ac1 | ||
|
|
81cb7b4f84 | ||
|
|
90c91c2b16 | ||
|
|
161d2810a3 | ||
|
|
9c0dae8d9a | ||
|
|
6375be4d2c | ||
|
|
64234815cc | ||
|
|
b56d4d1ca3 | ||
|
|
8d31b287f2 | ||
|
|
8e59d905ba | ||
|
|
028661f9f8 | ||
|
|
f6189c6d8a | ||
|
|
ee677ced24 | ||
|
|
5f5c142d03 | ||
|
|
2a7fe455ad | ||
|
|
047469de5b | ||
|
|
7a61a68f00 | ||
|
|
50f71390f8 | ||
|
|
fba7bb68fe | ||
|
|
2f6749bf5e | ||
|
|
9253c6dd7b | ||
|
|
e23ad8239b | ||
|
|
2f9e624c31 | ||
|
|
a336b50e0f | ||
|
|
5bc4a96e77 | ||
|
|
113ba8223c | ||
|
|
a760150d75 | ||
|
|
42a52dc606 | ||
|
|
b0c45c115e | ||
|
|
6a427a04ff | ||
|
|
1959c009fd | ||
|
|
35f5bdd483 | ||
|
|
ff422bae19 | ||
|
|
f2e4d5cc1b | ||
|
|
5fba69cad3 | ||
|
|
a1385956aa | ||
|
|
9493cbc6ff | ||
|
|
0762841ef0 | ||
|
|
e94fb73fd2 | ||
|
|
6cb5f738d4 | ||
|
|
1b66d6fe4d | ||
|
|
3a9511a6b2 | ||
|
|
70cfcda727 | ||
|
|
ef7ab11078 | ||
|
|
14ad9618d3 | ||
|
|
41ce3d862c | ||
|
|
2ae9e8bb6f | ||
|
|
8ebdaee97f | ||
|
|
9dab0f0c03 | ||
|
|
3144a6b5fd | ||
|
|
f6ed045b8f | ||
|
|
b31c29b440 | ||
|
|
0bf4181056 | ||
|
|
ff3fc84563 | ||
|
|
644af53193 | ||
|
|
b52eb24e85 | ||
|
|
b0ee04fab2 | ||
|
|
0b01f5ec1c | ||
|
|
310a2f5443 | ||
|
|
9c7de1a8fe | ||
|
|
2ff2d55f25 | ||
|
|
3d5e7be6b6 | ||
|
|
4bce655cb6 | ||
|
|
f2aa01d23c | ||
|
|
37907ed7f6 | ||
|
|
17d34ae443 | ||
|
|
5e442d43aa | ||
|
|
3594c81b17 | ||
|
|
221c830d60 | ||
|
|
962c2db587 | ||
|
|
e22d3367ba | ||
|
|
27df815529 | ||
|
|
64ad14ae80 | ||
|
|
3de09dc8db | ||
|
|
170aede49f | ||
|
|
9ab740e53b | ||
|
|
ddd4a806e1 | ||
|
|
5b4b427589 | ||
|
|
67900764f0 | ||
|
|
df3995f0bb | ||
|
|
96278eb6d4 | ||
|
|
b012abbffb | ||
|
|
cd52110e95 | ||
|
|
eba00e0e26 | ||
|
|
baab38c7f6 | ||
|
|
539530bcb9 | ||
|
|
829cdec53c | ||
|
|
1bbe89f962 | ||
|
|
1ae9724d34 | ||
|
|
d71142a253 | ||
|
|
ca0437d765 | ||
|
|
7e4619c2ae | ||
|
|
65dd9e26e9 | ||
|
|
fe788ca5dc | ||
|
|
4e3fd87481 | ||
|
|
6244663e80 | ||
|
|
3bce988e12 | ||
|
|
0fcc9e112a | ||
|
|
d083ae6d0e | ||
|
|
ddffc72e76 | ||
|
|
20d22fa036 | ||
|
|
ccb923ecc4 | ||
|
|
90f98c69c5 | ||
|
|
2f273777b2 | ||
|
|
3936960caf | ||
|
|
e32262a3b3 | ||
|
|
bc9d7f7c2a | ||
|
|
71fe870b1d | ||
|
|
28a0456fa7 | ||
|
|
ad7e00add5 | ||
|
|
6e5749063c | ||
|
|
048de253a9 | ||
|
|
c6c9578691 | ||
|
|
b052c04749 | ||
|
|
5085255f61 | ||
|
|
cd306135ad | ||
|
|
fbb9cac178 | ||
|
|
291210aadf | ||
|
|
458a9b9907 | ||
|
|
d210feab0d | ||
|
|
c3aaf78161 | ||
|
|
a86c7c6c1e | ||
|
|
8f79204fbc | ||
|
|
c21823c84e | ||
|
|
c40f64a193 | ||
|
|
f42cd221cc | ||
|
|
a8dc2a07db | ||
|
|
93e27f318d | ||
|
|
7ecb3ccf46 | ||
|
|
1dd48aa3f1 | ||
|
|
9ee7c6809a | ||
|
|
4eec46012a | ||
|
|
455edff025 | ||
|
|
79a43fe897 | ||
|
|
34306f023c | ||
|
|
e42baf816c | ||
|
|
f4cf76bc8f | ||
|
|
d7ef57a24e | ||
|
|
a349a3390c | ||
|
|
eae6e6ed8d | ||
|
|
14d87875ae | ||
|
|
62d997c85a | ||
|
|
02f37b2eeb | ||
|
|
636e6b82be | ||
|
|
72c544a512 | ||
|
|
97c7a4db17 | ||
|
|
aa8b4881ce | ||
|
|
c6d37a4281 | ||
|
|
05b269c0cf | ||
|
|
07d14cee67 | ||
|
|
70fb35bd25 | ||
|
|
574f4f90da | ||
|
|
6a951e1325 | ||
|
|
4a1abadd09 | ||
|
|
84bd0af02e | ||
|
|
115b838d3c | ||
|
|
13032e726b | ||
|
|
cf6efbaa2d | ||
|
|
580db415d6 | ||
|
|
30b2d1d913 | ||
|
|
510b2bcdd5 | ||
|
|
30856325be | ||
|
|
a5ab34b707 | ||
|
|
90ee139265 | ||
|
|
1e298edbdd | ||
|
|
925afb70c3 | ||
|
|
c399b850c5 | ||
|
|
8cf03e3ee3 | ||
|
|
e6ba1fc61b | ||
|
|
a2a434d6fd | ||
|
|
fe00182efd | ||
|
|
b00fcc25ea | ||
|
|
e9624ab6d6 | ||
|
|
c2d129aaa6 | ||
|
|
6b3b7d6945 | ||
|
|
1889b840b1 | ||
|
|
bfb1a4ef23 | ||
|
|
f178f31248 | ||
|
|
9c13832307 | ||
|
|
1c3f87165e | ||
|
|
c6ce339d40 | ||
|
|
5a90b00e19 | ||
|
|
e6bf8b5321 | ||
|
|
156e493a90 | ||
|
|
2cf073495c | ||
|
|
43b193e965 | ||
|
|
b4b8dfb217 | ||
|
|
99051af886 | ||
|
|
768926fec3 | ||
|
|
a73042abc1 | ||
|
|
da36e3c1fa | ||
|
|
0024e3e74d | ||
|
|
9b14caf300 | ||
|
|
adee153190 | ||
|
|
c476cd7f25 | ||
|
|
d4da6b02a8 | ||
|
|
1d3f651846 | ||
|
|
d6af0ffc95 | ||
|
|
c1ba96d395 | ||
|
|
52f53e3410 | ||
|
|
aba4875cf3 | ||
|
|
f5057c2ac7 | ||
|
|
cfd5558765 | ||
|
|
77bbeb6de0 | ||
|
|
bf3e22bf4c | ||
|
|
a5596ac8f6 | ||
|
|
a3dddfa7f8 | ||
|
|
922abe8ba3 | ||
|
|
9b85f8673c | ||
|
|
b8e0bf92c2 | ||
|
|
05c7adbfee | ||
|
|
4081802dc8 | ||
|
|
45fb1cd801 | ||
|
|
50ed4a6988 | ||
|
|
96997e95a0 | ||
|
|
9029a64a19 | ||
|
|
cb6c9dd374 | ||
|
|
5b1e9d3f16 | ||
|
|
ceb1f954ff | ||
|
|
f67e4f953f | ||
|
|
76c071da14 | ||
|
|
c8dafae31d | ||
|
|
1924056c02 | ||
|
|
257dd22345 | ||
|
|
4211259874 | ||
|
|
9fa7d0182d | ||
|
|
8a00736c8f | ||
|
|
f1fd6b6d8b | ||
|
|
b1adad5866 | ||
|
|
f8aaa21b39 | ||
|
|
6b207e29fc | ||
|
|
4effb7cfdd | ||
|
|
83f48ac009 | ||
|
|
6788612ab5 | ||
|
|
8329c38894 | ||
|
|
5e96f69c52 | ||
|
|
f4c6b4f08d | ||
|
|
95fef77042 | ||
|
|
9814f44ead | ||
|
|
13189c6c6c | ||
|
|
aed16dfec6 | ||
|
|
3167399da9 | ||
|
|
c6b77fe861 | ||
|
|
aa1e4ecb7d | ||
|
|
1b677770b6 | ||
|
|
c707f20b3f | ||
|
|
c368e065b6 | ||
|
|
90eab0573f | ||
|
|
35d7286eec | ||
|
|
b68fe58a23 | ||
|
|
ea133a96cd | ||
|
|
69e48c77a9 | ||
|
|
606fb38ae6 | ||
|
|
b29955d191 | ||
|
|
7539fb3699 | ||
|
|
2d8911947a | ||
|
|
2044042973 | ||
|
|
dd02f890c2 | ||
|
|
45ca2eaaca | ||
|
|
aaf535c33f | ||
|
|
e9c6da2c11 | ||
|
|
e2c8efe29f | ||
|
|
e76b789eb7 | ||
|
|
75d1431e50 | ||
|
|
8a9da8a3ae | ||
|
|
3b718b0461 | ||
|
|
65b0d1fc23 | ||
|
|
c56ed37f7a | ||
|
|
340754d062 | ||
|
|
db85c34e61 | ||
|
|
807995fe8b | ||
|
|
111120edaa | ||
|
|
0bac8d6ae3 | ||
|
|
2ba17d8d5b | ||
|
|
a61633194d | ||
|
|
caa86bb931 | ||
|
|
cfe08bc542 | ||
|
|
4e55742219 | ||
|
|
f98ed62045 | ||
|
|
03653fb653 | ||
|
|
240a89da2c | ||
|
|
cfacd05578 | ||
|
|
c0ab5f955d | ||
|
|
f2346c5709 | ||
|
|
798bfc964c | ||
|
|
2af9014962 | ||
|
|
f8759278bc | ||
|
|
abed1b0645 | ||
|
|
8999fc8fd6 | ||
|
|
a1f9db4114 | ||
|
|
2336f1dc79 | ||
|
|
335e177578 | ||
|
|
a4434b16de | ||
|
|
9b3624e818 | ||
|
|
120a95f94d | ||
|
|
db0a658be2 | ||
|
|
822a8afcb1 | ||
|
|
eed371130f | ||
|
|
dd19c1040c | ||
|
|
54130e5ee7 | ||
|
|
827128d048 | ||
|
|
26c18562c4 | ||
|
|
0a847c8427 | ||
|
|
27a976fc53 | ||
|
|
73a3a881ca | ||
|
|
f07545285b | ||
|
|
4d02883a48 | ||
|
|
4eb9f0a0a4 | ||
|
|
1f630181d7 | ||
|
|
71a9b79527 | ||
|
|
b32d098d3b | ||
|
|
9118c1d64f | ||
|
|
8e4f7b0f08 | ||
|
|
3acc0592b4 | ||
|
|
dc5e24201c | ||
|
|
eda8f9ac86 | ||
|
|
ed19c9c534 | ||
|
|
c0ee0195e9 | ||
|
|
ffa35bed94 | ||
|
|
9442be13f1 | ||
|
|
a017803429 | ||
|
|
951e88f1c8 | ||
|
|
de93247c5c | ||
|
|
06038bc105 | ||
|
|
43c5975524 | ||
|
|
891f183f80 | ||
|
|
c126c28fa3 | ||
|
|
fc99e46e0f | ||
|
|
9543e10241 | ||
|
|
327bc47017 | ||
|
|
96ccc5d4f5 | ||
|
|
eef2b4eb58 | ||
|
|
26346c8acb | ||
|
|
565e77ef6d | ||
|
|
84506a9340 | ||
|
|
25298012f9 | ||
|
|
236e2f6d48 | ||
|
|
483283fdd1 | ||
|
|
776c2f38f8 | ||
|
|
c20cc09959 | ||
|
|
ce7d3f0324 | ||
|
|
55e85dbd74 | ||
|
|
4c6f6d8b1c | ||
|
|
651381c9d7 | ||
|
|
146af5cf2d | ||
|
|
49a7c80423 | ||
|
|
e770eb147a | ||
|
|
a08802df0a | ||
|
|
61eba87de6 | ||
|
|
0e0a56ac38 | ||
|
|
36e6c2fa25 | ||
|
|
0c157eee69 | ||
|
|
ba2ac37f6c | ||
|
|
9a29db8c62 | ||
|
|
212ec834c8 | ||
|
|
bd70d80f81 | ||
|
|
55e2e3463d | ||
|
|
2e16eba739 | ||
|
|
35bf66ccf4 | ||
|
|
ec4679d85c | ||
|
|
15c4b0e5eb | ||
|
|
5f170f0953 | ||
|
|
07a1e9311b | ||
|
|
7d1274af4b | ||
|
|
9d096aed5d | ||
|
|
8477ad810a | ||
|
|
60e3fb6f45 | ||
|
|
7efb9ec1de | ||
|
|
70c0a4b9e6 | ||
|
|
d9b3474846 | ||
|
|
97cb7fc2eb | ||
|
|
6394612630 | ||
|
|
a78df50826 | ||
|
|
59c1948e14 | ||
|
|
e92fa3d615 | ||
|
|
faee5d0276 | ||
|
|
f2b1e7becc | ||
|
|
5352d55589 | ||
|
|
75386e55af | ||
|
|
fe2a28d013 | ||
|
|
aa2e07d163 | ||
|
|
23c1c41415 | ||
|
|
8be6988e5b | ||
|
|
262ccc2f11 | ||
|
|
09c3952a0a | ||
|
|
ea9c4df4bc | ||
|
|
43c95c24fe | ||
|
|
21a19dcf89 | ||
|
|
2b6cc3e52d | ||
|
|
f639704d6d | ||
|
|
b93995081e | ||
|
|
0dc68b830c | ||
|
|
5521b90aec | ||
|
|
7f0a13b434 | ||
|
|
c0e2445439 | ||
|
|
6037b87b52 | ||
|
|
b80c5d43e9 | ||
|
|
ed258e624d | ||
|
|
e1fd87b251 | ||
|
|
092cf6be4f | ||
|
|
a4286ea2de | ||
|
|
7ada2de54c | ||
|
|
0f01f513eb | ||
|
|
4bebcec778 | ||
|
|
6d2bf8402b | ||
|
|
674f99d738 | ||
|
|
f12c2d3a7c | ||
|
|
8748b1e122 | ||
|
|
b6e4206772 | ||
|
|
2c6224d45e | ||
|
|
a0c764d87c | ||
|
|
a1f6278711 | ||
|
|
3ca45f4eef | ||
|
|
07ff46b98e | ||
|
|
c73d3fd96b | ||
|
|
e8594d05cb | ||
|
|
253db597bd | ||
|
|
8058276990 | ||
|
|
1e3f704ffd | ||
|
|
871d470c71 | ||
|
|
fd442bc08c | ||
|
|
b93499e373 | ||
|
|
0a2ddc696b | ||
|
|
d8f4020fa8 | ||
|
|
cfbf2c3bed | ||
|
|
3aa41ed16f | ||
|
|
6dae186ed6 | ||
|
|
9b3f0d84a8 | ||
|
|
ce1f7280c7 | ||
|
|
612ef7ef1a | ||
|
|
8800303766 | ||
|
|
5dfcc6e851 | ||
|
|
2d5703d9d9 | ||
|
|
796a4753c9 | ||
|
|
69cbeaaa1f | ||
|
|
10e37a2f8e | ||
|
|
416635020c | ||
|
|
36e9810f43 | ||
|
|
ecd3699620 | ||
|
|
cb63d3689d | ||
|
|
d69e7ae872 | ||
|
|
33dabab5a6 | ||
|
|
c8dec26d15 | ||
|
|
cce77d00ff | ||
|
|
7853d457a1 | ||
|
|
fd9318c127 | ||
|
|
8bd9f6cb4a | ||
|
|
c3aeb82137 | ||
|
|
322d4ab8a1 | ||
|
|
1fa6d61468 | ||
|
|
bf15621d24 | ||
|
|
39ce0abfe5 | ||
|
|
5ee754f82f | ||
|
|
ff7ffcbacb | ||
|
|
0d02b443e7 | ||
|
|
4ddae3d3ed | ||
|
|
1194a3a231 | ||
|
|
612cfc5bfc | ||
|
|
0340fcd8bf | ||
|
|
4bb4a2836c | ||
|
|
8d9da9f6b2 | ||
|
|
faf306ab83 | ||
|
|
fcaa13e4c4 | ||
|
|
4987cc92a1 | ||
|
|
fe9ad58989 | ||
|
|
95470804f1 | ||
|
|
300e2aabba | ||
|
|
f9f917f007 | ||
|
|
dbb49cac6c | ||
|
|
5540c1855f | ||
|
|
7d64e08093 | ||
|
|
4dafd8c3ff | ||
|
|
b6f65c40cf | ||
|
|
07e61cd1d3 | ||
|
|
c12c496058 | ||
|
|
4a5db41302 | ||
|
|
21f269593a | ||
|
|
56a14ecd77 | ||
|
|
a2c770d798 | ||
|
|
31351837a7 | ||
|
|
bc9a0f749b | ||
|
|
e8d590c622 | ||
|
|
5cb7314b56 | ||
|
|
b724e728d9 | ||
|
|
c686014204 | ||
|
|
b6534fd91d | ||
|
|
5a964a1dd5 | ||
|
|
1d290e97b8 | ||
|
|
9f68cdbd6e | ||
|
|
bb3269646d | ||
|
|
abba89bcad | ||
|
|
352642c93a | ||
|
|
fb8f5120e0 | ||
|
|
c9bcf947c6 | ||
|
|
7100612187 | ||
|
|
b1d1022930 | ||
|
|
1c39460172 | ||
|
|
ed12e59e67 | ||
|
|
30563b19ef | ||
|
|
79f1ee85c0 | ||
|
|
12d38bc8fc | ||
|
|
70b15f5f9a | ||
|
|
207744b628 | ||
|
|
f07e0868e5 | ||
|
|
38bf3d0d34 | ||
|
|
a0e5bd4769 | ||
|
|
601dec9768 | ||
|
|
63cb5ee909 | ||
|
|
e3d8bd0242 | ||
|
|
489e334acb | ||
|
|
8c9069b765 | ||
|
|
1066421df5 | ||
|
|
6535dc3e66 | ||
|
|
05d75eb9e2 | ||
|
|
7dc5aaa7a4 | ||
|
|
08a4c8f6ad | ||
|
|
f8fb029d95 | ||
|
|
053cce5f51 | ||
|
|
4afbe84391 | ||
|
|
abd87c42ca | ||
|
|
50876fee39 | ||
|
|
56ca97d74e | ||
|
|
32b90262ed | ||
|
|
e3db36613e | ||
|
|
b96299e3d0 | ||
|
|
9dc06419cf | ||
|
|
d9ffcdf59b | ||
|
|
4f4d7a19f1 | ||
|
|
b65ede4f4f | ||
|
|
ff344082c6 | ||
|
|
387684445e | ||
|
|
9ee9de7695 | ||
|
|
fdc7a04141 | ||
|
|
399a51b2bb | ||
|
|
5c146c0ba1 | ||
|
|
f11196975b | ||
|
|
728a2e7276 | ||
|
|
f3ac621bbf | ||
|
|
1e67e6f2af | ||
|
|
fc3e915da6 | ||
|
|
e8830d2837 | ||
|
|
ff45b12b13 | ||
|
|
77ea27f340 | ||
|
|
9086a07f69 | ||
|
|
69f06c2b12 | ||
|
|
5737093e66 | ||
|
|
b5ebec5167 | ||
|
|
56d519a780 | ||
|
|
0805130582 | ||
|
|
9ef6380f0a | ||
|
|
a669a7ee75 | ||
|
|
e89d2006f5 | ||
|
|
a17522095c | ||
|
|
61f4b7c1e5 | ||
|
|
104f434f57 | ||
|
|
e6d03ebc9a | ||
|
|
13b34a8c50 | ||
|
|
9b541ce614 | ||
|
|
391a7da7da | ||
|
|
fd152df645 | ||
|
|
1bfdfb1a24 | ||
|
|
0d93cbf797 | ||
|
|
aaab58e9b2 | ||
|
|
af48ab19d6 | ||
|
|
d5fd2710fc | ||
|
|
93becd5a98 | ||
|
|
4e6eb6c53a | ||
|
|
85ac31af36 | ||
|
|
594657acd0 | ||
|
|
a1bfb0da5b | ||
|
|
9742ffe769 | ||
|
|
a9ddb52c5d | ||
|
|
5babbe19c3 | ||
|
|
fd8bab6348 | ||
|
|
e6764c1bdf | ||
|
|
d998f87099 | ||
|
|
e90e035825 | ||
|
|
3817597229 | ||
|
|
d97da4d532 | ||
|
|
1e2b6fed14 | ||
|
|
31cd1cb5e8 | ||
|
|
d567e95f7f | ||
|
|
354530ba66 | ||
|
|
c532ecbfb8 | ||
|
|
6e5a887fdb | ||
|
|
2632b0ad09 | ||
|
|
8577330e27 | ||
|
|
996be526fb | ||
|
|
e3146abae1 | ||
|
|
7f756c5028 | ||
|
|
94e570917a | ||
|
|
5c11fb87c2 | ||
|
|
67a0e4bf28 | ||
|
|
c4485fe742 | ||
|
|
33f56831b7 | ||
|
|
cc467c1b74 | ||
|
|
ea3271b49e | ||
|
|
3eeddfdd85 | ||
|
|
7df7e7c9e9 | ||
|
|
c5a20a334e | ||
|
|
3c5e9459de | ||
|
|
77f99cec6f | ||
|
|
39d6384b15 | ||
|
|
1115558d0d | ||
|
|
d6d1226a6c | ||
|
|
7ecff3bd9c | ||
|
|
98bf800d78 | ||
|
|
bd897b67d3 | ||
|
|
a3b5c6b716 | ||
|
|
c67d6e8474 | ||
|
|
29d8800907 | ||
|
|
2a769dd43e | ||
|
|
cdfb6484b8 | ||
|
|
4f3eacd322 | ||
|
|
9690659278 | ||
|
|
da009b5130 | ||
|
|
1bebc5baee | ||
|
|
199405cb56 | ||
|
|
45fcde1d73 | ||
|
|
b12eca2460 | ||
|
|
092cd39ed7 | ||
|
|
b349d12326 | ||
|
|
fe375548a5 | ||
|
|
2a771ab203 | ||
|
|
d90e54849a | ||
|
|
f85e3ce24b | ||
|
|
61f667622a | ||
|
|
d60e2abcce | ||
|
|
ceec364360 | ||
|
|
fffdc70a5c | ||
|
|
b94136e99c | ||
|
|
7257f13b9b | ||
|
|
e90ad0afdc | ||
|
|
67e44a2d3c | ||
|
|
01c199b0d0 | ||
|
|
4e53ea3ee5 | ||
|
|
28a06a16eb | ||
|
|
8d5d74dc48 | ||
|
|
209e192942 | ||
|
|
515c15a662 | ||
|
|
54d90a1062 | ||
|
|
c5a6776ccc | ||
|
|
8cbc22bb29 | ||
|
|
2b17edc82d | ||
|
|
1f79572c07 | ||
|
|
d15ddb5923 | ||
|
|
25fed73b74 | ||
|
|
82f7908384 | ||
|
|
ec294cd951 | ||
|
|
2fba579edd | ||
|
|
efe671ceff | ||
|
|
169a014437 | ||
|
|
41a14d440f | ||
|
|
f120bf56b0 | ||
|
|
d5dc89004e | ||
|
|
a60d83f588 | ||
|
|
e332a9bd71 | ||
|
|
b8ec9e1935 | ||
|
|
2cea42184b | ||
|
|
981256287a | ||
|
|
c2b84a6de4 | ||
|
|
5fea7316bd | ||
|
|
f3ef9224ef | ||
|
|
92c785746e | ||
|
|
b10ba79056 | ||
|
|
d73f29941d | ||
|
|
b0fccf1d8f | ||
|
|
2c93f6038e | ||
|
|
588e2c71f1 | ||
|
|
8aaaed0f3c | ||
|
|
0df1041339 | ||
|
|
5470222496 | ||
|
|
b86d43d829 | ||
|
|
df96cb890b | ||
|
|
db89739e6d | ||
|
|
02134ceaf8 | ||
|
|
958caabd8e | ||
|
|
9406bcc2e5 | ||
|
|
b19dbc9ffd | ||
|
|
021dd04707 | ||
|
|
fc43cc703e | ||
|
|
a99e99f70f | ||
|
|
0051cba426 | ||
|
|
6aabb3d6df | ||
|
|
16cca6572c | ||
|
|
af11ca49fe | ||
|
|
0e07147d07 | ||
|
|
8e5573b8f9 | ||
|
|
e7fc1844a2 | ||
|
|
4759724d2b | ||
|
|
96086c1b6e | ||
|
|
fd63f74b98 | ||
|
|
d7e6a145e9 | ||
|
|
6a3b449e46 | ||
|
|
a2a9124f07 | ||
|
|
a18a959ef6 | ||
|
|
444b3c0af4 | ||
|
|
eae2fe427d | ||
|
|
970bf46d8c | ||
|
|
0d0ebeeacb | ||
|
|
c8a9e3e443 | ||
|
|
9bbd2fe078 | ||
|
|
25b2bb9e30 | ||
|
|
7dda099a50 | ||
|
|
9f9376e7bf | ||
|
|
4549f271a2 | ||
|
|
ca4ef952c8 | ||
|
|
92c2b2566b | ||
|
|
4a7d5938f1 | ||
|
|
e50eb147f4 | ||
|
|
e0eedae8a0 | ||
|
|
5ac49e58f6 | ||
|
|
3b65dd9765 | ||
|
|
d882c26c03 | ||
|
|
319d8bdde4 | ||
|
|
a8c065cfc8 | ||
|
|
f57b8d0eec | ||
|
|
bafc8ab28d | ||
|
|
48179125f4 | ||
|
|
6468c548e3 | ||
|
|
e165440623 | ||
|
|
2e1936df52 | ||
|
|
1a52d98966 | ||
|
|
05ce9531d1 | ||
|
|
20e400b101 | ||
|
|
123f907f83 | ||
|
|
dd91ece92a | ||
|
|
462f555d5f | ||
|
|
b05d419b2f | ||
|
|
e435b772f3 | ||
|
|
ce345a3c71 | ||
|
|
110e3f2e8b | ||
|
|
83a8ebff7e | ||
|
|
ff7141fa43 | ||
|
|
5f4cc07a98 | ||
|
|
d855c7d3d2 | ||
|
|
bd145f8c3a | ||
|
|
99a1e4a557 | ||
|
|
cbaa5c8228 | ||
|
|
cc767d3964 | ||
|
|
8320681e92 | ||
|
|
c01b333d77 | ||
|
|
bbdba2b7c5 | ||
|
|
db170b67ad | ||
|
|
dd8077d7e2 | ||
|
|
006ee37e0a | ||
|
|
d607fb053a | ||
|
|
1db607822b | ||
|
|
72c07c4cd4 | ||
|
|
51ede1c550 | ||
|
|
6275df77a3 | ||
|
|
0d5f00117d | ||
|
|
b6bc3687ae | ||
|
|
e18f13c315 | ||
|
|
f41d2da14b | ||
|
|
1f8ebb83f5 | ||
|
|
cf5af654e1 | ||
|
|
5afbad5616 | ||
|
|
0f4360fa63 | ||
|
|
39c9362a41 | ||
|
|
3e08481516 | ||
|
|
90f9278b69 | ||
|
|
6741e69b08 | ||
|
|
88b4a75f95 | ||
|
|
1c3831aa72 | ||
|
|
38d3be5354 | ||
|
|
d495c081cb | ||
|
|
3a5a014590 | ||
|
|
6f94bc4b1a | ||
|
|
11da788756 | ||
|
|
3a5c59d22d | ||
|
|
952f02ebc9 | ||
|
|
4c649ef750 | ||
|
|
2fe12c664f | ||
|
|
fc0a28cd20 | ||
|
|
7bf3d4c69f | ||
|
|
4b43a696be | ||
|
|
fc6f0b7da9 | ||
|
|
386a1769ba | ||
|
|
48415a4d87 | ||
|
|
52db213cea | ||
|
|
5a8f26fb5b | ||
|
|
84ec51da54 | ||
|
|
5d64fbd9af | ||
|
|
514c12db0c | ||
|
|
0bc593c3df | ||
|
|
2f243ab266 | ||
|
|
7a0fa222c4 | ||
|
|
88d036c636 | ||
|
|
3b510a6073 | ||
|
|
5cfd7cd69a | ||
|
|
d5a5a7fd17 | ||
|
|
b9989b36dc | ||
|
|
84f1f4969b | ||
|
|
1945dbdbc3 | ||
|
|
cc4a905685 | ||
|
|
7b6630512b | ||
|
|
63e0f14ad3 | ||
|
|
18054e9603 | ||
|
|
9a6c652da0 | ||
|
|
55423425d7 | ||
|
|
d436094e8c | ||
|
|
9184b038b3 | ||
|
|
aad020b9b9 | ||
|
|
64b6bbd45b | ||
|
|
58724320b6 | ||
|
|
20fbdc7130 | ||
|
|
93aed2580e | ||
|
|
5e8ceae3da | ||
|
|
2f26e555f9 | ||
|
|
48b3555e40 | ||
|
|
657852a82f | ||
|
|
dd812ca58c | ||
|
|
2c37075c22 | ||
|
|
c895de54bf | ||
|
|
3e9c2e0131 | ||
|
|
075099d217 | ||
|
|
91e614d6ea | ||
|
|
5167ebd7c4 | ||
|
|
b5ecc66ea2 | ||
|
|
f49ef8b999 | ||
|
|
6691082bb7 | ||
|
|
8956cd45c9 | ||
|
|
33178022ec | ||
|
|
e0f034c911 | ||
|
|
65183c8142 | ||
|
|
a1dce3c1e3 | ||
|
|
27381582f8 | ||
|
|
326e27f0cd | ||
|
|
f2fc6d2299 | ||
|
|
06af4a926a | ||
|
|
672236ba8f | ||
|
|
2f692a206d | ||
|
|
ac74479c3c | ||
|
|
88a1a56e9b | ||
|
|
12c4ff669a | ||
|
|
48576c8dfb | ||
|
|
6802e4a136 | ||
|
|
4be4b69d15 | ||
|
|
a10855cb4d | ||
|
|
01aa69185e | ||
|
|
aa1c50f7a7 | ||
|
|
a74e071847 | ||
|
|
67a084e597 | ||
|
|
c5b84d1fa0 | ||
|
|
d8468be21a | ||
|
|
c31b7598e4 | ||
|
|
fa3dc1add1 | ||
|
|
81a405c48c | ||
|
|
0dc54213fc | ||
|
|
7adeeaf607 | ||
|
|
c316f03b10 | ||
|
|
fa96e6dc3a | ||
|
|
bff57c695e | ||
|
|
73ad7a1923 | ||
|
|
4f0c23f6f1 | ||
|
|
e40f9ac769 | ||
|
|
11d0fe0191 | ||
|
|
ca60b9e579 | ||
|
|
f424ab3a1f | ||
|
|
a72357397e | ||
|
|
819bf7a84e | ||
|
|
b2b597542d | ||
|
|
c4608f9465 | ||
|
|
6828ee95d7 | ||
|
|
3cecde7c50 | ||
|
|
1aec2dbfb4 | ||
|
|
ba3f28cd5b | ||
|
|
b8b6a749ce | ||
|
|
1d1c64119d | ||
|
|
e93e4d03a1 | ||
|
|
1ddbb1b197 | ||
|
|
3632c3b19e | ||
|
|
25651d84dd | ||
|
|
5a59b245ce | ||
|
|
cf33f8bf74 | ||
|
|
bfb86a67da | ||
|
|
c076f7641d | ||
|
|
ff6efc7681 | ||
|
|
30a0583aab | ||
|
|
ea27a1802d | ||
|
|
9c23bbd309 | ||
|
|
a0680ffa8f | ||
|
|
94c4b723ad | ||
|
|
23ee6c2bb1 | ||
|
|
02058e523f | ||
|
|
e1951f3637 | ||
|
|
7039478ebc | ||
|
|
ff566466c8 | ||
|
|
3dae1aac2d | ||
|
|
43dad21cad | ||
|
|
9f07373e33 | ||
|
|
b09e4f3b6a | ||
|
|
be66132498 | ||
|
|
a6a70cc88e | ||
|
|
63d04b7734 | ||
|
|
90edd71274 | ||
|
|
db0252dc2c | ||
|
|
8b3e13ecba | ||
|
|
5ac96dd852 | ||
|
|
cf1ad22af1 | ||
|
|
4cf7e6888b | ||
|
|
1aa4e8bbb2 | ||
|
|
d9db327ffa | ||
|
|
6f484766ac | ||
|
|
9b6468c0b4 | ||
|
|
c5880c9096 | ||
|
|
4d588b62cb | ||
|
|
f6d2ab2e0e | ||
|
|
c52636a6e8 | ||
|
|
a24fb43ae8 | ||
|
|
8f7ead0687 | ||
|
|
39e6cc64a2 | ||
|
|
4f985776e1 | ||
|
|
b9e992f118 | ||
|
|
39e5f969e8 | ||
|
|
ee79ce4bf6 | ||
|
|
20e7a98395 | ||
|
|
c66be99be7 | ||
|
|
0bb5873fc5 | ||
|
|
50bf0b4a3b | ||
|
|
d664652b53 | ||
|
|
77d500235b | ||
|
|
a7811d9425 | ||
|
|
6c6d9d507f | ||
|
|
36ebc21d3e | ||
|
|
12f900cb6c | ||
|
|
e515bb4933 | ||
|
|
d93f46f4d6 | ||
|
|
1d4aaf04fd | ||
|
|
65469210b1 | ||
|
|
88a8bf2769 | ||
|
|
8429ff3150 | ||
|
|
890d352a65 | ||
|
|
acb85071f0 | ||
|
|
e41a60613c | ||
|
|
9001668e1b | ||
|
|
7b78f22fcc | ||
|
|
b614e6c1a4 | ||
|
|
187abcbcdf | ||
|
|
5a3a755f1a | ||
|
|
386e539148 | ||
|
|
d05375447b | ||
|
|
0fc5791b8e | ||
|
|
0e4f851098 | ||
|
|
2488378099 | ||
|
|
b906890de1 | ||
|
|
feb0236d50 | ||
|
|
22104a9bdb | ||
|
|
d0ccd9d77a | ||
|
|
dc6a7cf712 | ||
|
|
795d6bdab6 | ||
|
|
a2b41531a0 | ||
|
|
6ed4301ba4 | ||
|
|
7abab63049 | ||
|
|
b29fdd841b | ||
|
|
7e73f6f074 | ||
|
|
efc1efdfe1 | ||
|
|
11fdff952c | ||
|
|
14f90b66f2 | ||
|
|
a8d1676156 | ||
|
|
951f588a31 | ||
|
|
7081627776 | ||
|
|
391576f080 | ||
|
|
8cca3b9ef6 | ||
|
|
47c5f14eda | ||
|
|
a757b3b326 | ||
|
|
1e1475c0e9 | ||
|
|
fa68a17ea3 | ||
|
|
dc1bb0e2c1 | ||
|
|
656cfb62ff | ||
|
|
65b26a25ea | ||
|
|
6a03246234 | ||
|
|
53289b8616 | ||
|
|
349eb433ce | ||
|
|
9a98e0db24 | ||
|
|
b89e8baba0 | ||
|
|
773f276a78 | ||
|
|
1085923163 | ||
|
|
6b3ffed3e4 | ||
|
|
16a142c3c4 | ||
|
|
2b660c4d45 | ||
|
|
6283987323 | ||
|
|
fd778b0fa8 | ||
|
|
8f03d92f5b | ||
|
|
2ca624e9e2 | ||
|
|
514b00f7af | ||
|
|
05b7f6dbe9 | ||
|
|
d22eb9c85a | ||
|
|
4bd60c04a5 | ||
|
|
f361e61ce9 | ||
|
|
1e5807c585 | ||
|
|
8239b130bf | ||
|
|
09acf97c8d | ||
|
|
6e72d0bb14 | ||
|
|
34c6659703 | ||
|
|
42a067a32a | ||
|
|
f2a995ccdc | ||
|
|
463f064919 | ||
|
|
bec20e7e5d | ||
|
|
da18b35d68 | ||
|
|
842d7f453c | ||
|
|
74e63fd176 | ||
|
|
c8ec229629 | ||
|
|
d955e09268 | ||
|
|
106dfd8d47 | ||
|
|
aa4ff53d62 | ||
|
|
2a9e9932f6 | ||
|
|
df853d9867 | ||
|
|
bcd185e508 | ||
|
|
2032c30a4d | ||
|
|
2b8e217459 | ||
|
|
29948c246d | ||
|
|
901d0effe7 | ||
|
|
6a21f98d14 | ||
|
|
6eb05ce9b4 | ||
|
|
cae3414ddb | ||
|
|
3e067c9ea5 | ||
|
|
12316e8611 | ||
|
|
bf3370fad1 | ||
|
|
2cb2868d47 | ||
|
|
6ab33ba06c | ||
|
|
f826575567 | ||
|
|
498879a235 | ||
|
|
0283c5204f | ||
|
|
5bb7fea3ca | ||
|
|
593f0e7a18 | ||
|
|
1158c43430 | ||
|
|
041d53c434 | ||
|
|
1e60b41226 | ||
|
|
855d831c33 | ||
|
|
425efa412f | ||
|
|
0b5a284ceb | ||
|
|
75f1e6e569 | ||
|
|
0258316d21 | ||
|
|
b55cd42aaf | ||
|
|
8781a53f21 | ||
|
|
75a2b47abf | ||
|
|
9b531f83a6 | ||
|
|
c7c3b01805 | ||
|
|
cd5f5216bb | ||
|
|
8f87539026 | ||
|
|
c63c4c349e | ||
|
|
10f3923376 | ||
|
|
384a18fd65 | ||
|
|
c0c890302b | ||
|
|
8a3d3f5783 | ||
|
|
f322610661 | ||
|
|
a87acd6dc2 | ||
|
|
ebe7d44386 | ||
|
|
e55c25dc94 | ||
|
|
3f34745a15 | ||
|
|
f4b32ca436 | ||
|
|
8b156a87bd | ||
|
|
f6142e576b | ||
|
|
5d5905249c | ||
|
|
b9396534e5 | ||
|
|
cff40a31e5 | ||
|
|
aa908f7a61 | ||
|
|
429d62991a | ||
|
|
14bcb6ac2b | ||
|
|
5067175174 | ||
|
|
7879f17dac | ||
|
|
3be1cf2074 | ||
|
|
424f5b4794 | ||
|
|
b64583510c | ||
|
|
2e114b0cfb | ||
|
|
f56c76cf15 | ||
|
|
8b0f7148e7 | ||
|
|
c600c30eaa | ||
|
|
b2efd544dc | ||
|
|
e3a709d261 | ||
|
|
3028d6a7af | ||
|
|
0adf9df0b5 | ||
|
|
4e25774931 | ||
|
|
e8808e8d7d | ||
|
|
f4a53cfc05 | ||
|
|
0f6ff9c3a0 | ||
|
|
6ac4082bcd | ||
|
|
4d87b338e5 | ||
|
|
88ee16965b | ||
|
|
408fd4ddfa | ||
|
|
5068a3cfc1 | ||
|
|
376bc20472 | ||
|
|
dc3606b53a | ||
|
|
49cc5c060f | ||
|
|
dbe3ee555d | ||
|
|
b273c95494 | ||
|
|
a46519c964 | ||
|
|
7f9cbe6d46 | ||
|
|
b94dcabbd5 | ||
|
|
e8b2c7b470 | ||
|
|
899e5ed7ed | ||
|
|
04cf4eaa76 | ||
|
|
9ca336c47f | ||
|
|
dac818db4d | ||
|
|
21a8ea11a3 | ||
|
|
52af7c44f1 | ||
|
|
18b9bd8e4b | ||
|
|
5cdf7573ee | ||
|
|
3c415591db | ||
|
|
667fdc0163 | ||
|
|
10569b1426 | ||
|
|
2f4ddeab9f | ||
|
|
235ce4873f | ||
|
|
b26e1e12d6 | ||
|
|
ef1a2fe75e | ||
|
|
c7766c05d2 | ||
|
|
85c8b636a8 | ||
|
|
43b80f24e6 | ||
|
|
c7e6fd6a1b | ||
|
|
7ca4ad60c1 | ||
|
|
a81a31ac66 | ||
|
|
6b3eda7c4a | ||
|
|
68243ee844 | ||
|
|
6196daeead | ||
|
|
81c420c2e3 | ||
|
|
c533da896c | ||
|
|
29f5f33a12 | ||
|
|
aa7734d72b | ||
|
|
e5a2132dfd | ||
|
|
f766594ef3 | ||
|
|
78383bf9d7 | ||
|
|
45c0183f97 | ||
|
|
ce52864fbc | ||
|
|
5dae482265 | ||
|
|
cef73ca693 | ||
|
|
0ffe3037d5 | ||
|
|
af164039fa | ||
|
|
2cf30dcb2c | ||
|
|
4a99ccabd9 | ||
|
|
9c0d0d0fac | ||
|
|
f6a33bde65 | ||
|
|
3ac1d203a9 | ||
|
|
e9d78688d7 | ||
|
|
69a73cc25e | ||
|
|
aaf01f4a0a | ||
|
|
30e6c70346 | ||
|
|
7c01d81483 | ||
|
|
4ace644304 | ||
|
|
7b66e7eb41 |
26
.github/workflows/ci.yml
vendored
Normal file
26
.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
# This workflow will build a .NET project
|
||||
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-net
|
||||
|
||||
name: .NET
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "master" ]
|
||||
pull_request:
|
||||
branches: [ "master" ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: 7.0.x
|
||||
- name: Build
|
||||
run: dotnet build Radzen.Blazor/Radzen.Blazor.csproj
|
||||
- name: Test
|
||||
run: dotnet test Radzen.Blazor.Tests/Radzen.Blazor.Tests.csproj
|
||||
8
.gitignore
vendored
8
.gitignore
vendored
@@ -8,6 +8,7 @@
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
global.json
|
||||
|
||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||
*.userprefs
|
||||
@@ -333,3 +334,10 @@ issues.json
|
||||
|
||||
Radzen.Blazor/wwwroot/css/
|
||||
project.csproj
|
||||
RadzenBlazorDemos/wwwroot/docs/
|
||||
Radzen.DocFX/obj/
|
||||
Radzen.DocFX/_site/
|
||||
Radzen.DocFX/_exported_templates
|
||||
Radzen.DocFX/api/*.yml
|
||||
!Radzen.DocFX/api/index.md
|
||||
Radzen.DocFX/api/.manifest
|
||||
|
||||
@@ -5,23 +5,21 @@
|
||||
This is a set of guidelines for contributing to Radzen.Blazor.
|
||||
|
||||
## Asking questions
|
||||
|
||||
Please don't open an issue to ask a question about using Radzen.Blazor components. You can check the following resources instead:
|
||||
|
||||
- [Online demos](https://blazor.radzen.com)
|
||||
|
||||
### [Online demos](https://blazor.radzen.com)
|
||||
A showcase application that demonstrates all Radzen.Blazor components. You will find various use cases that demonstrate the component features and API. The source
|
||||
of the demos is available [here](https://github.com/radzenhq/radzen-blazor/tree/master/RadzenBlazorDemos).
|
||||
- [Documentation](https://www.radzen.com/documentation/blazor/accordion/)
|
||||
|
||||
### [Documentation](https://blazor.radzen.com/docs/)
|
||||
Technical documentation and API reference.
|
||||
- [Online forum](https://forum.radzen.com)
|
||||
|
||||
### [Community forum](https://forum.radzen.com)
|
||||
You can ask your question here. Please use the [Radzen.Blazor Components](https://forum.radzen.com/c/blazor-components/10) category.
|
||||
|
||||
- Dedicated technical support
|
||||
### Dedicated technical support
|
||||
|
||||
Radzen staff provides technical support with guaranteed response time to Radzen Professional and Enterprise subscribers. The pricing options are available [here](https://www.radzen.com/pricing/).
|
||||
Radzen staff provides technical support with guaranteed response time to Radzen Professional and Enterprise subscribers. The pricing options are available [here](https://www.radzen.com/blazor-studio/pricing/).
|
||||
|
||||
## How Can I Contribute?
|
||||
|
||||
@@ -67,7 +65,8 @@ Explain the enhancement and include additional details:
|
||||
If you want to contribute a new feature of fix a bug you can open a pull request.
|
||||
|
||||
Make sure you follow this procedure:
|
||||
|
||||
* **Important!!!** if you itent to make a lot of changes in a pull request open an issue to discuss this with us first. The Radzen Blazor Components have a lot of
|
||||
moving parts and making big changes should be done with extra precautions.
|
||||
* **Be sure that none of the existing tests** breaks after your changes. The test project is available [here](https://github.com/radzenhq/radzen-blazor/tree/master/Radzen.Blazor.Tests).
|
||||
* **If possible add new tests that verify your fix or new feature**.
|
||||
* **Follow the existing coding style** (to be described in detail later).
|
||||
|
||||
31
Dockerfile
Normal file
31
Dockerfile
Normal file
@@ -0,0 +1,31 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
FROM mono:latest
|
||||
|
||||
ENV DOCFX_VER 2.58.4
|
||||
|
||||
RUN apt-get update && apt-get install unzip wget git -y && wget -q -P /tmp https://github.com/dotnet/docfx/releases/download/v${DOCFX_VER}/docfx.zip && \
|
||||
mkdir -p /opt/docfx && \
|
||||
unzip /tmp/docfx.zip -d /opt/docfx && \
|
||||
echo '#!/bin/bash\nmono /opt/docfx/docfx.exe $@' > /usr/bin/docfx && \
|
||||
chmod +x /usr/bin/docfx && \
|
||||
rm -rf /tmp/*
|
||||
|
||||
COPY Radzen.Blazor /app/Radzen.Blazor
|
||||
COPY Radzen.DocFX /app/DocFX
|
||||
COPY RadzenBlazorDemos /app/RadzenBlazorDemos
|
||||
COPY RadzenBlazorDemos.Host /app/RadzenBlazorDemos.Host
|
||||
WORKDIR /app
|
||||
RUN docfx DocFX/docfx.json
|
||||
|
||||
FROM mcr.microsoft.com/dotnet/sdk:7.0
|
||||
|
||||
COPY --from=0 /app/RadzenBlazorDemos.Host /app/RadzenBlazorDemos.Host
|
||||
COPY --from=0 /app/RadzenBlazorDemos /app/RadzenBlazorDemos
|
||||
|
||||
WORKDIR /app/RadzenBlazorDemos.Host
|
||||
RUN dotnet publish -c Release -o out
|
||||
|
||||
ENV ASPNETCORE_URLS http://*:5000
|
||||
WORKDIR /app/RadzenBlazorDemos.Host/out
|
||||
|
||||
ENTRYPOINT ["dotnet", "RadzenBlazorDemos.Host.dll"]
|
||||
2
LICENSE
2
LICENSE
@@ -1,6 +1,6 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2018-2021 Radzen Ltd
|
||||
Copyright (c) 2018-2022 Radzen Ltd
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
116
README.md
116
README.md
@@ -1,43 +1,118 @@
|
||||
# Radzen Blazor Components
|
||||

|
||||
|
||||
The home of the [Radzen Blazor components](https://blazor.radzen.com)
|
||||
<h1 align="center">
|
||||
Radzen Blazor Components
|
||||
</h1>
|
||||
|
||||
## Commercial support
|
||||
<p align="center">
|
||||
A set of <strong>70+ free and open source</strong> native Blazor UI controls.
|
||||
</p>
|
||||
|
||||
Paid support for the Radzen Blazor Components is available as part of the [Radzen Professional subscription](https://www.radzen.com/pricing/).
|
||||
<div align="center">
|
||||
|
||||
Our flagship product Radzen provides tons of productivity features for Blazor developers:
|
||||
- The first in the industry WYSIWYG Blazor design time canvas
|
||||
[See Online Demos](https://blazor.radzen.com) or [Read the Docs](https://blazor.radzen.com/docs/)
|
||||
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/radzenhq/radzen-blazor/blob/master/LICENSE">
|
||||
<img alt="License - MIT" src="https://img.shields.io/github/license/radzenhq/radzen-blazor?logo=github&style=for-the-badge" />
|
||||
</a>
|
||||
<a href="https://www.nuget.org/packages/Radzen.Blazor">
|
||||
<img alt="Nuget Downloads" src="https://img.shields.io/nuget/dt/Radzen.Blazor?color=%232694F9&label=nuget%20downloads&logo=nuget&style=for-the-badge" />
|
||||
</a>
|
||||
<img alt="Last Commit" src="https://img.shields.io/github/last-commit/radzenhq/radzen-blazor?logo=github&style=for-the-badge" />
|
||||
<a href="https://github.com/radzenhq/radzen-blazor/graphs/contributors">
|
||||
<img alt="Github Contributors" src="https://img.shields.io/github/contributors/radzenhq/radzen-blazor?logo=github&style=for-the-badge" />
|
||||
</a>
|
||||
<a href="https://blazor.radzen.com">
|
||||
<img alt="Radzen Blazor Components - Online Demos" src="https://img.shields.io/badge/demos-online-brightgreen?color=%232694F9&logo=blazor&style=for-the-badge" />
|
||||
</a>
|
||||
<a href="https://blazor.radzen.com/docs">
|
||||
<img alt="Radzen Blazor Components - Documentation" src="https://img.shields.io/badge/docs-online-brightgreen?color=%232694F9&logo=blazor&style=for-the-badge" />
|
||||
</a>
|
||||
</p>
|
||||
|
||||
## Why choose Radzen Blazor Components?
|
||||
|
||||
### :sparkles: Free
|
||||
|
||||
Radzen Blazor Components are open source and free for commercial use. You can install them from [nuget](https://www.nuget.org/packages/Radzen.Blazor) or build your own copy from source.
|
||||
|
||||
Paid support is available as part of the [Radzen Professional subscription](https://www.radzen.com/blazor-studio/pricing/).
|
||||
|
||||
### :computer: Native
|
||||
|
||||
The components are implemented in C# and take full advantage of the Blazor framework. They do not depend on or wrap existing JavaScript frameworks or libraries.
|
||||
|
||||
Blazor Server and Blazor WebAssembly are fully supported.
|
||||
|
||||
### :seedling: Growing
|
||||
|
||||
We add new components and features on a regular basis.
|
||||
|
||||
Short development cycle. We release as soon as new stuff is available. No more quarterly releases.
|
||||
|
||||
## Support exceeding your expectations
|
||||
|
||||
### :speech_balloon: Community Support
|
||||
Everybody is welcome to visit the [Radzen Community forum](https://forum.radzen.com/). Join the growing community and participate in the discussions!
|
||||
|
||||
### :dart: Dedicated Support
|
||||
|
||||
The Radzen team monitors the forum threads, but does not guarantee a response to every question. For guaranteed responses you may consider the dedicated support option.
|
||||
|
||||
Dedicated support for the Radzen Blazor Components is available as part of the [Radzen Professional subscription](https://www.radzen.com/blazor-studio/pricing/).
|
||||
|
||||
Our flagship product [Radzen Blazor Studio](https://www.radzen.com/blazor-studio/) provides tons of productivity features for Blazor developers:
|
||||
- An industry-leading WYSIWYG Blazor design time canvas
|
||||
- Scaffolding a complete CRUD applications from a database
|
||||
- Built-in security - authentication and authorization
|
||||
- Visual Studio Code and Professional support
|
||||
- Deployment to IIS and Azure
|
||||
- Dedicated support with 24 hour guaranteed response time
|
||||
- Active community forum
|
||||
|
||||
## Get started with the Radzen Blazor Components
|
||||
## Get started with Radzen Blazor Components
|
||||
|
||||
### Install
|
||||
### 1. Install
|
||||
|
||||
Radzen Blazor Components are distributed as the Radzen.Blazor nuget package. You can add them to your project in one of the following ways
|
||||
- Install the package from command line by running dotnet add package Radzen.Blazor
|
||||
- Add the project from the Visual Nuget Package Manager
|
||||
Radzen Blazor Components are distributed as a [Radzen.Blazor nuget package](https://www.nuget.org/packages/Radzen.Blazor). You can add them to your project in one of the following ways
|
||||
- Install the package from command line by running `dotnet add package Radzen.Blazor`
|
||||
- Add the project from the Visual Nuget Package Manager
|
||||
- Manually edit the .csproj file and add a project reference
|
||||
|
||||
### Import the namespace
|
||||
### 2. Import the namespace
|
||||
|
||||
Open the `_Imports.razor` file of your Blazor application and add this line `@using Radzen.Blazor`.
|
||||
|
||||
### Include a theme
|
||||
### 3. Include a theme
|
||||
|
||||
Open the `_Host.cshtml` file (server-side Blazor) or `wwwroot/index.html` (client-side Blazor) and include a theme CSS file by adding this snippet `<link rel="stylesheet" href="_content/Radzen.Blazor/css/default.css">` or `<link rel="stylesheet" href="_content/Radzen.Blazor/css/default-base.css">` if you either include Bootstrap manually or don't use it at all.
|
||||
Radzen Blazor components come with five free themes: Material, Standard, Default, Dark, Software and Humanistic.
|
||||
|
||||
### Include Radzen.Blazor.js
|
||||
To use a theme
|
||||
1. Pick a theme. The [online demos](https://blazor.radzen.com/colors) allow you to preview the available options via the theme dropdown located in the header. The Material theme is currently selected by default.
|
||||
1. Include the theme CSS file in your Blazor application. Open `Pages\_Layout.cshtml` (Blazor Server .NET 6), `Pages\_Host.cshtml` (Blazor Server .NET 7) or `wwwroot/index.html` (Blazor WebAssembly) and include a theme CSS file by adding this snippet
|
||||
```html
|
||||
<link rel="stylesheet" href="_content/Radzen.Blazor/css/material-base.css">
|
||||
```
|
||||
|
||||
Open the `_Host.cshtml` file (server-side Blazor) or `wwwroot/index.html` (client-side Blazor) and include this snippet `<script src="_content/Radzen.Blazor/Radzen.Blazor.js"></script>`
|
||||
To include a different theme (i.e. Standard) just change the name of the CSS file:
|
||||
```
|
||||
<link rel="stylesheet" href="_content/Radzen.Blazor/css/standard-base.css">
|
||||
```
|
||||
|
||||
### Use a component
|
||||
Use any Radzen Blazor component by typing its tag name in a Blazor page e.g.
|
||||
### 4. Include Radzen.Blazor.js
|
||||
|
||||
Open `Pages\_Layout.cshtml` (Blazor Server .NET 6), `Pages\_Host.cshtml` (Blazor Server .NET 7) or `wwwroot/index.html` (Blazor WebAssembly) and include this snippet:
|
||||
|
||||
```html
|
||||
<script src="_content/Radzen.Blazor/Radzen.Blazor.js"></script>
|
||||
```
|
||||
|
||||
### 5. Use a component
|
||||
Use any Radzen Blazor component by typing its tag name in a Blazor page e.g.
|
||||
```html
|
||||
<RadzenButton Text="Hi"></RadzenButton>
|
||||
```
|
||||
@@ -62,3 +137,6 @@ Use any Radzen Blazor component by typing its tag name in a Blazor page e.g.
|
||||
}
|
||||
}
|
||||
```
|
||||
## Run demos locally
|
||||
|
||||
Use Radzen.Server.sln to open and run demos as Blazor server application or Radzen.WebAssembly.sln to open and run demos as Blazor WebAssembly application. Radzen.sln has reference to all projects including tests.
|
||||
47
Radzen.Blazor.Tests/BadgeTests.cs
Normal file
47
Radzen.Blazor.Tests/BadgeTests.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
using Bunit;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class BadgeTests
|
||||
{
|
||||
[Fact]
|
||||
public void Badge_Renders_TextParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenBadge>();
|
||||
|
||||
var text = "Test";
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Text, text));
|
||||
|
||||
Assert.Contains(text, component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Badge_Renders_ChildContent()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenBadge>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.AddChildContent("SomeContent"));
|
||||
|
||||
Assert.Contains(@$"SomeContent", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Badge_Renders_BadgeStyle()
|
||||
{
|
||||
var badgeStyle = BadgeStyle.Danger;
|
||||
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenBadge>();
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.BadgeStyle, badgeStyle));
|
||||
|
||||
Assert.Contains($"badge-{badgeStyle.ToString().ToLower()}", component.Markup);
|
||||
}
|
||||
}
|
||||
}
|
||||
77
Radzen.Blazor.Tests/BreadCrumbTests.cs
Normal file
77
Radzen.Blazor.Tests/BreadCrumbTests.cs
Normal file
@@ -0,0 +1,77 @@
|
||||
using Bunit;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class BreadCrumbTests
|
||||
{
|
||||
[Fact]
|
||||
public void BreadCrumb_Renders_Items()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenBreadCrumb>();
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add(c => c.ChildContent, builder =>
|
||||
{
|
||||
builder.OpenComponent<RadzenBreadCrumbItem>(0);
|
||||
builder.AddAttribute(1, nameof(RadzenBreadCrumbItem.Text), "Test");
|
||||
builder.CloseComponent();
|
||||
});
|
||||
});
|
||||
//@"<RadzenBreadCrumbItem Text=""Test"" />"
|
||||
Assert.Contains(@"class=""rz-breadcrumb-item", component.Markup);
|
||||
Assert.Contains(">Test</", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BreadCrumb_Renders_Icon()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenBreadCrumb>();
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add(c => c.ChildContent, builder =>
|
||||
{
|
||||
builder.OpenComponent<RadzenBreadCrumbItem>(0);
|
||||
builder.AddAttribute(1, nameof(RadzenBreadCrumbItem.Text), "Test");
|
||||
builder.AddAttribute(2, nameof(RadzenBreadCrumbItem.Icon), "add");
|
||||
builder.CloseComponent();
|
||||
});
|
||||
});
|
||||
|
||||
//@"<RadzenBreadCrumbItem Text=""Test"" />"
|
||||
Assert.Contains("<i", component.Markup);
|
||||
Assert.Contains(">add</i>", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BreadCrumb_Renders_Link()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenBreadCrumb>();
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add(c => c.ChildContent, builder =>
|
||||
{
|
||||
builder.OpenComponent<RadzenBreadCrumbItem>(0);
|
||||
builder.AddAttribute(1, nameof(RadzenBreadCrumbItem.Text), "Test");
|
||||
builder.AddAttribute(2, nameof(RadzenBreadCrumbItem.Icon), "add");
|
||||
builder.AddAttribute(3, nameof(RadzenBreadCrumbItem.Path), "/badge");
|
||||
builder.CloseComponent();
|
||||
});
|
||||
});
|
||||
|
||||
//@"<RadzenBreadCrumbItem Text=""Test"" />"
|
||||
Assert.Contains("<i", component.Markup);
|
||||
Assert.Contains(">add</i>", component.Markup);
|
||||
Assert.Contains("<a href=\"/badge", component.Markup);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -33,6 +33,28 @@ namespace Radzen.Blazor.Tests
|
||||
Assert.Contains(@$"<i class=""rz-button-icon-left rzi"">{icon}</i>", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Button_Renders_BusySpinner()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenButton>();
|
||||
|
||||
var icon = "account_circle";
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters
|
||||
.Add(p => p.Icon, icon)
|
||||
.Add(p => p.IsBusy, true)
|
||||
);
|
||||
|
||||
// does not render the actual icon when busy
|
||||
Assert.DoesNotContain(@$"<i class=""rz-button-icon-left rzi"">{icon}</i>", component.Markup);
|
||||
|
||||
// renders the icon with busy spin animation
|
||||
Assert.Contains(@"<i style=""animation: rotation", component.Markup);
|
||||
Assert.Contains(">refresh</i>", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Button_Renders_IconAndTextParameters()
|
||||
{
|
||||
@@ -43,9 +65,10 @@ namespace Radzen.Blazor.Tests
|
||||
var text = "Test";
|
||||
var icon = "account_circle";
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Text, text);
|
||||
parameters.Add(p => p.Icon, icon);
|
||||
parameters.Add(p => p.Icon, icon);
|
||||
});
|
||||
|
||||
Assert.Contains(@$"<i class=""rz-button-icon-left rzi"">{icon}</i>", component.Markup);
|
||||
@@ -76,7 +99,8 @@ namespace Radzen.Blazor.Tests
|
||||
var text = "Test";
|
||||
var image = "test.png";
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Text, text);
|
||||
parameters.Add(p => p.Image, image);
|
||||
});
|
||||
@@ -110,11 +134,11 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.ButtonStyle, ButtonStyle.Primary));
|
||||
|
||||
Assert.Contains(@$"btn-primary", component.Markup);
|
||||
Assert.Contains(@$"rz-primary", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.ButtonStyle, ButtonStyle.Secondary));
|
||||
|
||||
Assert.Contains(@$"btn-secondary", component.Markup);
|
||||
Assert.Contains(@$"rz-secondary", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
@@ -110,7 +110,7 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Change, args => { raised = true; }));
|
||||
|
||||
component.Find("div").MouseUp();
|
||||
component.Find("div.rz-chkbox-box").Click();
|
||||
|
||||
Assert.True(raised);
|
||||
}
|
||||
@@ -126,7 +126,7 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.ValueChanged, args => { raised = true; }));
|
||||
|
||||
component.Find("div").MouseUp();
|
||||
component.Find("div.rz-chkbox-box").Click();
|
||||
|
||||
Assert.True(raised);
|
||||
}
|
||||
@@ -141,21 +141,21 @@ namespace Radzen.Blazor.Tests
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.TriState, true));
|
||||
|
||||
|
||||
component.Find("div").MouseUp();
|
||||
component.Find("div.rz-chkbox-box").Click();
|
||||
|
||||
component.Render();
|
||||
|
||||
Assert.Contains(@$"rz-state-active", component.Markup);
|
||||
Assert.Contains(@$"rzi-check", component.Markup);
|
||||
|
||||
component.Find("div").MouseUp();
|
||||
component.Find("div.rz-chkbox-box").Click();
|
||||
|
||||
component.Render();
|
||||
|
||||
Assert.DoesNotContain(@$"rz-state-active", component.Markup);
|
||||
Assert.DoesNotContain(@$"rzi-check", component.Markup);
|
||||
|
||||
component.Find("div").MouseUp();
|
||||
component.Find("div.rz-chkbox-box").Click();
|
||||
|
||||
Assert.Contains(@$"rz-state-active", component.Markup);
|
||||
Assert.Contains(@$"rzi-times", component.Markup);
|
||||
|
||||
@@ -2,9 +2,7 @@ using AngleSharp.Dom;
|
||||
using Bunit;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Rendering;
|
||||
using Radzen.Blazor.Rendering;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
@@ -22,9 +20,11 @@ namespace Radzen.Blazor.Tests
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenGrid<dynamic>>(parameterBuilder => {
|
||||
var component = ctx.RenderComponent<RadzenGrid<dynamic>>(parameterBuilder =>
|
||||
{
|
||||
parameterBuilder.Add<IEnumerable<dynamic>>(p => p.Data, new[] { new { Id = 1 }, new { Id = 2 }, new { Id = 3 } });
|
||||
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder => {
|
||||
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder =>
|
||||
{
|
||||
builder.OpenComponent(0, typeof(RadzenGridColumn<dynamic>));
|
||||
builder.AddAttribute(1, "Property", "Id");
|
||||
builder.CloseComponent();
|
||||
@@ -63,20 +63,22 @@ namespace Radzen.Blazor.Tests
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenGrid<dynamic>>(parameterBuilder => {
|
||||
parameterBuilder.Add<IEnumerable<dynamic>>(p => p.Data, new[] { new { Id = 1}, new { Id = 2 }, new { Id = 3 } });
|
||||
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder => {
|
||||
var component = ctx.RenderComponent<RadzenGrid<dynamic>>(parameterBuilder =>
|
||||
{
|
||||
parameterBuilder.Add<IEnumerable<dynamic>>(p => p.Data, new[] { new { Id = 1 }, new { Id = 2 }, new { Id = 3 } });
|
||||
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder =>
|
||||
{
|
||||
builder.OpenComponent(0, typeof(RadzenGridColumn<dynamic>));
|
||||
builder.AddAttribute(1, "Property", "Id");
|
||||
builder.CloseComponent();
|
||||
});
|
||||
});
|
||||
|
||||
var markup = new Regex(@"\s\s+").Replace(component.Markup, "").Trim();
|
||||
var data = component.FindAll(".rz-cell-data");
|
||||
|
||||
Assert.Contains(@$"<span class=""rz-cell-data"">1</span>", markup);
|
||||
Assert.Contains(@$"<span class=""rz-cell-data"">2</span>", markup);
|
||||
Assert.Contains(@$"<span class=""rz-cell-data"">3</span>", markup);
|
||||
Assert.Equal("1", data[0].TextContent.Trim());
|
||||
Assert.Equal("2", data[1].TextContent.Trim());
|
||||
Assert.Equal("3", data[2].TextContent.Trim());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -86,18 +88,19 @@ namespace Radzen.Blazor.Tests
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenGrid<dynamic>>(parameterBuilder => {
|
||||
var component = ctx.RenderComponent<RadzenGrid<dynamic>>(parameterBuilder =>
|
||||
{
|
||||
parameterBuilder.Add<IEnumerable<dynamic>>(p => p.Data, new[] { new { Id = 1 }, new { Id = 2 }, new { Id = 3 } });
|
||||
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder => {
|
||||
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder =>
|
||||
{
|
||||
builder.OpenComponent(0, typeof(RadzenGridColumn<dynamic>));
|
||||
builder.AddAttribute(1, "Title", "MyId");
|
||||
builder.CloseComponent();
|
||||
});
|
||||
});
|
||||
|
||||
var markup = new Regex(@"\s\s+").Replace(component.Markup, "").Trim();
|
||||
|
||||
Assert.Contains(@$"<span class=""rz-column-title"">MyId</span>", markup);
|
||||
var title = component.Find(".rz-column-title");
|
||||
Assert.Equal("MyId", title.TextContent.Trim());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -107,20 +110,23 @@ namespace Radzen.Blazor.Tests
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenGrid<dynamic>>(parameterBuilder => {
|
||||
var component = ctx.RenderComponent<RadzenGrid<dynamic>>(parameterBuilder =>
|
||||
{
|
||||
parameterBuilder.Add<IEnumerable<dynamic>>(p => p.Data, new[] { new { Id = 1 }, new { Id = 2 }, new { Id = 3 } });
|
||||
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder => {
|
||||
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder =>
|
||||
{
|
||||
builder.OpenComponent(0, typeof(RadzenGridColumn<dynamic>));
|
||||
builder.AddAttribute(1, "Property", "Id");
|
||||
builder.AddAttribute(2, "Title", "Id");
|
||||
builder.CloseComponent();
|
||||
});
|
||||
parameterBuilder.Add<bool>(p => p.AllowSorting, true) ;
|
||||
parameterBuilder.Add<bool>(p => p.AllowSorting, true);
|
||||
});
|
||||
|
||||
Assert.Contains(@$"rz-sortable-column", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add<bool>(p => p.AllowSorting, false);
|
||||
});
|
||||
|
||||
@@ -134,9 +140,11 @@ namespace Radzen.Blazor.Tests
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenGrid<dynamic>>(parameterBuilder => {
|
||||
var component = ctx.RenderComponent<RadzenGrid<dynamic>>(parameterBuilder =>
|
||||
{
|
||||
parameterBuilder.Add<IEnumerable<dynamic>>(p => p.Data, new[] { new { Id = 1 }, new { Id = 2 }, new { Id = 3 } });
|
||||
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder => {
|
||||
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder =>
|
||||
{
|
||||
builder.OpenComponent(0, typeof(RadzenGridColumn<dynamic>));
|
||||
builder.AddAttribute(1, "Property", "Id");
|
||||
builder.AddAttribute(2, "Title", "Id");
|
||||
@@ -156,9 +164,11 @@ namespace Radzen.Blazor.Tests
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenGrid<dynamic>>(parameterBuilder => {
|
||||
var component = ctx.RenderComponent<RadzenGrid<dynamic>>(parameterBuilder =>
|
||||
{
|
||||
parameterBuilder.Add<IEnumerable<dynamic>>(p => p.Data, new[] { new { Id = 1 }, new { Id = 2 }, new { Id = 3 } });
|
||||
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder => {
|
||||
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder =>
|
||||
{
|
||||
builder.OpenComponent(0, typeof(RadzenGridColumn<dynamic>));
|
||||
builder.AddAttribute(1, "Property", "Id");
|
||||
builder.AddAttribute(2, "Title", "Id");
|
||||
@@ -169,7 +179,8 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
Assert.Contains(@$"rz-cell-filter", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add<bool>(p => p.AllowFiltering, false);
|
||||
});
|
||||
|
||||
@@ -183,9 +194,11 @@ namespace Radzen.Blazor.Tests
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenGrid<dynamic>>(parameterBuilder => {
|
||||
var component = ctx.RenderComponent<RadzenGrid<dynamic>>(parameterBuilder =>
|
||||
{
|
||||
parameterBuilder.Add<IEnumerable<dynamic>>(p => p.Data, new[] { new { Id = 1 }, new { Id = 2 }, new { Id = 3 } });
|
||||
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder => {
|
||||
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder =>
|
||||
{
|
||||
builder.OpenComponent(0, typeof(RadzenGridColumn<dynamic>));
|
||||
builder.AddAttribute(1, "Property", "Id");
|
||||
builder.AddAttribute(2, "Title", "Id");
|
||||
@@ -205,9 +218,11 @@ namespace Radzen.Blazor.Tests
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenGrid<dynamic>>(parameterBuilder => {
|
||||
var component = ctx.RenderComponent<RadzenGrid<dynamic>>(parameterBuilder =>
|
||||
{
|
||||
parameterBuilder.Add<IEnumerable<dynamic>>(p => p.Data, new[] { new { Id = 1 }, new { Id = 2 }, new { Id = 3 } });
|
||||
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder => {
|
||||
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder =>
|
||||
{
|
||||
builder.OpenComponent(0, typeof(RadzenGridColumn<dynamic>));
|
||||
builder.AddAttribute(1, "Property", "Id");
|
||||
builder.AddAttribute(2, "Title", "Id");
|
||||
@@ -219,7 +234,8 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
Assert.Contains(@$"rz-grid-filter", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add<FilterMode>(p => p.FilterMode, FilterMode.Simple);
|
||||
});
|
||||
|
||||
@@ -233,9 +249,11 @@ namespace Radzen.Blazor.Tests
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenGrid<int>>(parameterBuilder => {
|
||||
var component = ctx.RenderComponent<RadzenGrid<int>>(parameterBuilder =>
|
||||
{
|
||||
parameterBuilder.Add<IEnumerable<int>>(p => p.Data, new[] { 1, 2, 3 });
|
||||
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder => {
|
||||
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder =>
|
||||
{
|
||||
builder.OpenComponent(0, typeof(RadzenGridColumn<int>));
|
||||
|
||||
builder.AddAttribute(1, "HeaderTemplate", (RenderFragment)delegate (RenderTreeBuilder b)
|
||||
@@ -257,9 +275,11 @@ namespace Radzen.Blazor.Tests
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenGrid<int>>(parameterBuilder => {
|
||||
var component = ctx.RenderComponent<RadzenGrid<int>>(parameterBuilder =>
|
||||
{
|
||||
parameterBuilder.Add<IEnumerable<int>>(p => p.Data, new[] { 1, 2, 3 });
|
||||
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder => {
|
||||
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder =>
|
||||
{
|
||||
builder.OpenComponent(0, typeof(RadzenGridColumn<int>));
|
||||
|
||||
builder.AddAttribute(1, "FooterTemplate", (RenderFragment)delegate (RenderTreeBuilder b)
|
||||
@@ -284,9 +304,11 @@ namespace Radzen.Blazor.Tests
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenGrid<dynamic>>(parameterBuilder => {
|
||||
var component = ctx.RenderComponent<RadzenGrid<dynamic>>(parameterBuilder =>
|
||||
{
|
||||
parameterBuilder.Add<IEnumerable<dynamic>>(p => p.Data, Enumerable.Range(0, 100).Select(i => new { Id = i }));
|
||||
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder => {
|
||||
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder =>
|
||||
{
|
||||
builder.OpenComponent(0, typeof(RadzenGridColumn<dynamic>));
|
||||
builder.AddAttribute(1, "Property", "Id");
|
||||
builder.AddAttribute(2, "Title", "Id");
|
||||
@@ -328,9 +350,10 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
var component = ctx.RenderComponent<RadzenGrid<int>>(parameterBuilder => parameterBuilder.Add<IEnumerable<int>>(p => p.Data, Enumerable.Range(0, 100)));
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add<bool>(p => p.AllowPaging, true);
|
||||
parameters.Add<PagerPosition>(p => p.PagerPosition, PagerPosition.Top);
|
||||
parameters.Add<PagerPosition>(p => p.PagerPosition, PagerPosition.Top);
|
||||
});
|
||||
|
||||
Assert.Contains(@$"rz-paginator", component.Markup);
|
||||
@@ -346,7 +369,8 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
var component = ctx.RenderComponent<RadzenGrid<int>>(parameterBuilder => parameterBuilder.Add<IEnumerable<int>>(p => p.Data, Enumerable.Range(0, 100)));
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add<bool>(p => p.AllowPaging, true);
|
||||
parameters.Add<PagerPosition>(p => p.PagerPosition, PagerPosition.TopAndBottom);
|
||||
});
|
||||
@@ -355,6 +379,57 @@ namespace Radzen.Blazor.Tests
|
||||
Assert.Contains(@$"rz-paginator-bottom", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DataGrid_Renders_DefaultEmptyText()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenGrid<int>>(parameterBuilder => parameterBuilder.Add<IEnumerable<int>>(p => p.Data, Array.Empty<int>()));
|
||||
component.Render();
|
||||
|
||||
Assert.Contains("No records to display.", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DataGrid_Renders_EmptyText()
|
||||
{
|
||||
string emptyText = "Lorem Ipsum";
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenGrid<int>>(parameterBuilder => parameterBuilder.Add<IEnumerable<int>>(p => p.Data, Array.Empty<int>()));
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.EmptyText, emptyText);
|
||||
});
|
||||
|
||||
Assert.Contains(emptyText, component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DataGrid_Renders_EmptyTemplate()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenGrid<int>>(parameterBuilder => parameterBuilder.Add<IEnumerable<int>>(p => p.Data, Array.Empty<int>()));
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add<RenderFragment>(p => p.EmptyTemplate, builder =>
|
||||
{
|
||||
builder.OpenElement(0, "p");
|
||||
builder.AddContent(0, "Lorem Ipsum");
|
||||
builder.CloseElement();
|
||||
});
|
||||
});
|
||||
|
||||
Assert.Contains("<p>Lorem Ipsum</p>", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DataGrid_Raises_LoadDataEventOnNextPageClick()
|
||||
{
|
||||
@@ -367,7 +442,8 @@ namespace Radzen.Blazor.Tests
|
||||
var raised = false;
|
||||
LoadDataArgs newArgs = null;
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add<bool>(p => p.AllowPaging, true);
|
||||
parameters.Add<LoadDataArgs>(p => p.LoadData, args => { raised = true; newArgs = args; });
|
||||
});
|
||||
@@ -391,7 +467,8 @@ namespace Radzen.Blazor.Tests
|
||||
var raised = false;
|
||||
LoadDataArgs newArgs = null;
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add<bool>(p => p.AllowPaging, true);
|
||||
parameters.Add<LoadDataArgs>(p => p.LoadData, args => { raised = true; newArgs = args; });
|
||||
});
|
||||
@@ -415,7 +492,8 @@ namespace Radzen.Blazor.Tests
|
||||
var raised = false;
|
||||
LoadDataArgs newArgs = null;
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add<bool>(p => p.AllowPaging, true);
|
||||
parameters.Add<LoadDataArgs>(p => p.LoadData, args => { raised = true; newArgs = args; });
|
||||
});
|
||||
@@ -440,7 +518,8 @@ namespace Radzen.Blazor.Tests
|
||||
var raised = false;
|
||||
LoadDataArgs newArgs = null;
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add<bool>(p => p.AllowPaging, true);
|
||||
parameters.Add<LoadDataArgs>(p => p.LoadData, args => { raised = true; newArgs = args; });
|
||||
});
|
||||
@@ -464,7 +543,8 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
var raised = false;
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add<bool>(p => p.AllowPaging, true);
|
||||
parameters.Add<LoadDataArgs>(p => p.LoadData, args => { raised = true; });
|
||||
});
|
||||
@@ -485,7 +565,8 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
var raised = false;
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add<bool>(p => p.AllowPaging, true);
|
||||
parameters.Add<LoadDataArgs>(p => p.LoadData, args => { raised = true; });
|
||||
});
|
||||
@@ -506,13 +587,15 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
var raised = false;
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add<bool>(p => p.AllowPaging, true);
|
||||
});
|
||||
|
||||
component.Find(".rz-paginator-last").Click();
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add<LoadDataArgs>(p => p.LoadData, args => { raised = true; });
|
||||
});
|
||||
|
||||
@@ -532,13 +615,15 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
var raised = false;
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add<bool>(p => p.AllowPaging, true);
|
||||
});
|
||||
|
||||
component.Find(".rz-paginator-last").Click();
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add<LoadDataArgs>(p => p.LoadData, args => { raised = true; });
|
||||
});
|
||||
|
||||
@@ -559,7 +644,8 @@ namespace Radzen.Blazor.Tests
|
||||
var raised = false;
|
||||
LoadDataArgs newArgs = null;
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add<bool>(p => p.AllowPaging, true);
|
||||
parameters.Add<int>(p => p.PageSize, 20);
|
||||
parameters.Add<LoadDataArgs>(p => p.LoadData, args => { raised = true; newArgs = args; });
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
using Bunit;
|
||||
using Radzen.Blazor.Rendering;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
@@ -49,7 +49,7 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>();
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
component.SetParametersAndRender(parameters => {
|
||||
parameters.Add<bool>(p => p.ShowTime, true);
|
||||
parameters.Add<bool>(p => p.ShowSeconds, true);
|
||||
});
|
||||
@@ -93,7 +93,7 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
parameters.Add(p => p.DateFormat, format);
|
||||
parameters.Add<object>(p => p.Value, DateTime.Now);
|
||||
parameters.Add<object>(p => p.Value, DateTime.Now);
|
||||
});
|
||||
|
||||
Assert.Contains(@$"value=""{string.Format("{0:" + format + "}", DateTime.Now)}""", component.Markup);
|
||||
@@ -146,7 +146,7 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
parameters.Add<object>(p => p.Value, DateTime.Now);
|
||||
parameters.Add<bool>(p => p.AllowClear, true);
|
||||
parameters.Add<bool>(p => p.AllowClear, true);
|
||||
});
|
||||
|
||||
Assert.Contains(@$"<i class=""rz-dropdown-clear-icon rzi rzi-times""", component.Markup);
|
||||
@@ -230,7 +230,7 @@ namespace Radzen.Blazor.Tests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DatePicker_Raises_ChangeEventOnNextMonth()
|
||||
public void DatePicker_NotRaises_ChangeEventOnNextMonth()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
@@ -247,12 +247,11 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
component.Find(".rz-datepicker-next-icon").Click();
|
||||
|
||||
Assert.True(raised);
|
||||
Assert.True(((DateTime)newValue) > DateTime.Now);
|
||||
Assert.False(raised);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DatePicker_Raises_ValueChangedEventOnNextMonth()
|
||||
public void DatePicker_NotRaises_ValueChangedEventOnNextMonth()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
@@ -269,12 +268,11 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
component.Find(".rz-datepicker-next-icon").Click();
|
||||
|
||||
Assert.True(raised);
|
||||
Assert.True(((DateTime)newValue) > DateTime.Now);
|
||||
Assert.False(raised);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DatePicker_Raises_ChangeEventOnPrevMonth()
|
||||
public void DatePicker_NotRaises_ChangeEventOnPrevMonth()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
@@ -291,12 +289,11 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
component.Find(".rz-datepicker-prev-icon").Click();
|
||||
|
||||
Assert.True(raised);
|
||||
Assert.True(((DateTime)newValue) < DateTime.Now);
|
||||
Assert.False(raised);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DatePicker_Raises_ValueChangedEventOnPrevMonth()
|
||||
public void DatePicker_NotRaises_ValueChangedEventOnPrevMonth()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
@@ -313,8 +310,200 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
component.Find(".rz-datepicker-prev-icon").Click();
|
||||
|
||||
Assert.False(raised);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DatePicker_Raises_ValueChangedEvent_Returns_PreviousDateOnInputOnDisabledDates()
|
||||
{
|
||||
IEnumerable<DateTime> dates = new DateTime[] { DateTime.Today };
|
||||
DateTime previousDay = DateTime.Today.AddDays(-1);
|
||||
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>();
|
||||
|
||||
var raised = false;
|
||||
object newValue = null;
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
parameters.Add(p => p.ValueChanged, args => { raised = true; newValue = args; })
|
||||
.Add(p => p.DateRender, args => { args.Disabled = dates.Contains(args.Date); });
|
||||
});
|
||||
|
||||
var inputElement = component.Find(".rz-inputtext");
|
||||
|
||||
// initialize DateTimeValue
|
||||
ctx.JSInterop.Setup<string>("Radzen.getInputValue", invocation => true).SetResult(previousDay.ToShortDateString());
|
||||
inputElement.Change(previousDay.AddDays(-1));
|
||||
|
||||
// try to enter disabled date
|
||||
ctx.JSInterop.Setup<string>("Radzen.getInputValue", invocation => true).SetResult(DateTime.Today.ToShortDateString());
|
||||
inputElement.Change(DateTime.Today);
|
||||
|
||||
Assert.True(raised);
|
||||
Assert.True(((DateTime)newValue) < DateTime.Now);
|
||||
Assert.Equal(previousDay, (DateTime)newValue);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DatePicker_Clears_InputOnDisabledDates()
|
||||
{
|
||||
IEnumerable<DateTime> dates = new DateTime[] { DateTime.Today };
|
||||
DateTime previousDay = DateTime.Today.AddDays(-1);
|
||||
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDatePicker<DateTime?>>();
|
||||
|
||||
var raised = false;
|
||||
object newValue = null;
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
parameters.Add(p => p.ValueChanged, args => { raised = true; newValue = args; })
|
||||
.Add(p => p.DateRender, args => { args.Disabled = dates.Contains(args.Date); });
|
||||
});
|
||||
|
||||
var inputElement = component.Find(".rz-inputtext");
|
||||
|
||||
// initialize DateTimeValue
|
||||
ctx.JSInterop.Setup<string>("Radzen.getInputValue", invocation => true).SetResult(previousDay.ToShortDateString());
|
||||
inputElement.Change(previousDay.AddDays(-1));
|
||||
|
||||
// try to enter disabled date
|
||||
ctx.JSInterop.Setup<string>("Radzen.getInputValue", invocation => true).SetResult(DateTime.Today.ToShortDateString());
|
||||
inputElement.Change(DateTime.Today);
|
||||
|
||||
Assert.True(raised);
|
||||
Assert.Null(newValue);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DatePicker_Respects_DateTimeMaxValue()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Value, DateTime.MaxValue);
|
||||
});
|
||||
|
||||
Assert.Contains(DateTime.MaxValue.ToString(component.Instance.DateFormat), component.Markup);
|
||||
|
||||
var exception = Record.Exception(() => component.Find(".rz-datepicker-next-icon")
|
||||
.Click());
|
||||
Assert.Null(exception);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DatePicker_Respects_DateTimeMinValue()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Value, DateTime.MinValue);
|
||||
});
|
||||
|
||||
Assert.Contains(DateTime.MinValue.ToString(component.Instance.DateFormat), component.Markup);
|
||||
|
||||
var exception = Record.Exception(() => component.Find(".rz-datepicker-prev-icon")
|
||||
.Click());
|
||||
Assert.Null(exception);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(DateTimeKind.Local)]
|
||||
[InlineData(DateTimeKind.Unspecified)]
|
||||
[InlineData(DateTimeKind.Utc)]
|
||||
public void DatePicker_Respects_DateTimeKind(DateTimeKind kind)
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>(parameters =>
|
||||
{
|
||||
parameters.Add(x => x.Kind, kind);
|
||||
parameters.Add(x => x.ShowTime, true);
|
||||
});
|
||||
|
||||
var raised = false;
|
||||
object newValue = null;
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Change, args => { raised = true; newValue = args; });
|
||||
});
|
||||
|
||||
component.Find(".rz-datepicker-next-icon").Click();
|
||||
component.FindAll(".rz-button-text").First(x => x.TextContent == "Ok").Click();
|
||||
|
||||
Assert.True(raised);
|
||||
Assert.Equal(kind, ((DateTime)newValue).Kind);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DatePicker_Renders_FooterTemplate()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
string actionsTemplate = "<input type=\"button\" value=\"Test\" />";
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Value, DateTime.MinValue);
|
||||
parameters.Add(p => p.FooterTemplate, actionsTemplate);
|
||||
});
|
||||
|
||||
Assert.Contains(actionsTemplate, component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DatePicker_Converts_DateTimeOffSet_FromUtc_ToLocal()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var valueUtc = DateTimeOffset.UtcNow;
|
||||
var kind = DateTimeKind.Local;
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDatePicker<DateTimeOffset>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Kind, kind);
|
||||
parameters.Add(p => p.Value, valueUtc);
|
||||
});
|
||||
|
||||
Assert.Equal(kind, (component.Instance.Value as DateTime?)?.Kind);
|
||||
Assert.Equal(valueUtc.LocalDateTime.ToString(CultureInfo.InvariantCulture), (component.Instance.Value as DateTime?)?.ToString(CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DatePicker_Converts_DateTimeOffSet_Local_ToUtc()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var valueUtc = DateTimeOffset.Now;
|
||||
var kind = DateTimeKind.Utc;
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDatePicker<DateTimeOffset>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Kind, kind);
|
||||
parameters.Add(p => p.Value, valueUtc);
|
||||
});
|
||||
|
||||
Assert.Equal(kind, (component.Instance.Value as DateTime?)?.Kind);
|
||||
Assert.Equal(valueUtc.UtcDateTime.ToString(CultureInfo.InvariantCulture), (component.Instance.Value as DateTime?)?.ToString(CultureInfo.InvariantCulture));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
126
Radzen.Blazor.Tests/DropDownTests.cs
Normal file
126
Radzen.Blazor.Tests/DropDownTests.cs
Normal file
@@ -0,0 +1,126 @@
|
||||
using System;
|
||||
using Bunit;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class DropDownTests
|
||||
{
|
||||
class DataItem
|
||||
{
|
||||
public string Text { get; set; }
|
||||
public int Id { get; set; }
|
||||
}
|
||||
|
||||
private static IRenderedComponent<RadzenDropDown<T>> DropDown<T>(TestContext ctx, Action<ComponentParameterCollectionBuilder<RadzenDropDown<T>>> configure = null)
|
||||
{
|
||||
var data = new [] {
|
||||
new DataItem { Text = "Item 1", Id = 1 },
|
||||
new DataItem { Text = "Item 2", Id = 2 },
|
||||
};
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDropDown<T>>();
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
parameters.Add(p => p.Data, data);
|
||||
parameters.Add(p => p.TextProperty, nameof(DataItem.Text));
|
||||
|
||||
if (configure != null)
|
||||
{
|
||||
configure.Invoke(parameters);
|
||||
}
|
||||
else
|
||||
{
|
||||
parameters.Add(p => p.ValueProperty, nameof(DataItem.Id));
|
||||
}
|
||||
});
|
||||
|
||||
return component;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DropDown_RendersItems()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
|
||||
var component = DropDown<int>(ctx);
|
||||
|
||||
var items = component.FindAll(".rz-dropdown-item");
|
||||
|
||||
Assert.Equal(2, items.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DropDown_AppliesSelectionStyleForIntValue()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
|
||||
var component = DropDown<int>(ctx);
|
||||
|
||||
var items = component.FindAll(".rz-dropdown-item");
|
||||
|
||||
items[0].Click();
|
||||
|
||||
component.Render();
|
||||
|
||||
items = component.FindAll(".rz-dropdown-item");
|
||||
|
||||
Assert.Contains("rz-state-highlight", items[0].ClassList);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DropDown_AppliesSelectionStyleForStringValue()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
|
||||
var component = DropDown<string>(ctx, parameters => {
|
||||
parameters.Add(p => p.ValueProperty, nameof(DataItem.Text));
|
||||
});
|
||||
|
||||
var items = component.FindAll(".rz-dropdown-item");
|
||||
|
||||
items[0].Click();
|
||||
|
||||
component.Render();
|
||||
|
||||
items = component.FindAll(".rz-dropdown-item");
|
||||
|
||||
Assert.Contains("rz-state-highlight", items[0].ClassList);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DropDown_AppliesSelectionStyleWhenMultipleSelectionIsEnabled()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
|
||||
var component = DropDown<string>(ctx, parameters => {
|
||||
parameters.Add(p => p.ValueProperty, nameof(DataItem.Text));
|
||||
parameters.Add(p => p.Multiple, true);
|
||||
});
|
||||
|
||||
var items = component.FindAll(".rz-multiselect-item");
|
||||
|
||||
items[0].Click();
|
||||
|
||||
component.Render();
|
||||
|
||||
items = component.FindAll(".rz-multiselect-item");
|
||||
|
||||
items[1].Click();
|
||||
|
||||
component.Render();
|
||||
|
||||
var selectedItems = component.FindAll(".rz-state-highlight");
|
||||
|
||||
Assert.Equal(2, selectedItems.Count);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
using Bunit;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using System.Linq;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
@@ -15,7 +17,6 @@ namespace Radzen.Blazor.Tests
|
||||
component.Render();
|
||||
|
||||
Assert.Contains(@$"rz-fieldset", component.Markup);
|
||||
Assert.Contains(@$"rz-fieldset-legend", component.Markup);
|
||||
Assert.Contains(@$"rz-fieldset-content-wrapper", component.Markup);
|
||||
Assert.Contains(@$"rz-fieldset-content", component.Markup);
|
||||
}
|
||||
@@ -145,7 +146,8 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
var raised = false;
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add<bool>(p => p.AllowCollapse, true);
|
||||
parameters.Add(p => p.Collapse, args => { raised = true; });
|
||||
});
|
||||
@@ -160,5 +162,57 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
component.Find("a").Click();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Fieldset_Renders_SummaryWhenCollapsed()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenFieldset>();
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add<bool>(p => p.AllowCollapse, true);
|
||||
parameters.Add<bool>(p => p.Collapsed, true);
|
||||
parameters.Add<RenderFragment>(p => p.SummaryTemplate, builder =>
|
||||
{
|
||||
builder.OpenElement(0, "p");
|
||||
builder.AddContent(0, "SummaryContent");
|
||||
builder.CloseElement();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
Assert.Contains("SummaryContent", component.Markup);
|
||||
Assert.Equal(
|
||||
"",
|
||||
component.Find(".rz-fieldset-content-summary").ParentElement.Attributes.First(attr => attr.Name == "style").Value
|
||||
);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Fieldset_DontRenders_SummaryWhenOpen()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenFieldset>();
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add<bool>(p => p.AllowCollapse, true);
|
||||
parameters.Add<bool>(p => p.Collapsed, false);
|
||||
parameters.Add<RenderFragment>(p => p.SummaryTemplate, builder =>
|
||||
{
|
||||
builder.OpenElement(0, "p");
|
||||
builder.AddContent(0, "SummaryContent");
|
||||
builder.CloseElement();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
Assert.Contains("SummaryContent", component.Markup);
|
||||
Assert.Equal(
|
||||
"display: none",
|
||||
component.Find(".rz-fieldset-content-summary").ParentElement.Attributes.First(attr => attr.Name == "style").Value
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace Radzen.Blazor.Tests
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Icon, icon));
|
||||
|
||||
Assert.Contains(@$">{icon}</i>", component.Markup);
|
||||
Assert.Contains(@$"<i class=""rzi d-inline-flex justify-content-center align-items-center""", component.Markup);
|
||||
Assert.Contains(@$"<i class=""rzi""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -45,5 +45,29 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
Assert.Contains(@$"autofocus", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Icon_Renders_IconStyleClass()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenIcon>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(icon => icon.IconStyle, IconStyle.Primary));
|
||||
|
||||
Assert.Contains(@$"rzi-primary", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Icon_NotRenders_IconStyleClass_WhenNull()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenIcon>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(icon => icon.IconStyle, null));
|
||||
|
||||
Assert.DoesNotContain(@$"rzi-primary", component.Markup);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,8 +30,10 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Text, text));
|
||||
|
||||
Assert.Contains(@$">{text}</span>", component.Markup);
|
||||
Assert.Contains(@$"class=""rz-link-text""", component.Markup);
|
||||
var textElement = component.Find(".rz-link-text");
|
||||
|
||||
Assert.NotNull(textElement);
|
||||
Assert.Equal(text, textElement.TextContent.Trim());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
@@ -26,7 +26,12 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
var component = ctx.RenderComponent<RadzenLogin>();
|
||||
|
||||
Assert.Contains(@$"<label class=""col-sm-3 col-form-label"" for=""username"">Username</label>", component.Markup);
|
||||
component.SetParametersAndRender(p => {
|
||||
p.AddUnmatched("id", "login");
|
||||
});
|
||||
|
||||
var label = component.Find($@"label[for=""login-username""]");
|
||||
Assert.NotNull(label);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -36,7 +41,7 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
var component = ctx.RenderComponent<RadzenLogin>();
|
||||
|
||||
Assert.Contains(@$"<input name=""userName"" class=""rz-textbox""", component.Markup);
|
||||
Assert.Contains(@$"<input name=""Username""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -63,7 +68,7 @@ namespace Radzen.Blazor.Tests
|
||||
component.SetParametersAndRender(parameters => {
|
||||
parameters.Add(p => p.Username, "user");
|
||||
parameters.Add(p => p.Password, "pwd");
|
||||
parameters.Add(p => p.Login, args => { clicked = true; });
|
||||
parameters.Add(p => p.Login, args => { clicked = true; });
|
||||
});
|
||||
|
||||
component.Find("button").Click();
|
||||
@@ -89,30 +94,6 @@ namespace Radzen.Blazor.Tests
|
||||
Assert.True(!clicked);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Login_Validates_UsernameParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenLogin>();
|
||||
|
||||
component.Find("button").Click();
|
||||
|
||||
Assert.Contains(@$"Username is required", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Login_Validates_PasswordParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenLogin>();
|
||||
|
||||
component.Find("button").Click();
|
||||
|
||||
Assert.Contains(@$"Password is required", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Login_Renders_LoginTextParameter()
|
||||
{
|
||||
@@ -138,7 +119,7 @@ namespace Radzen.Blazor.Tests
|
||||
parameters.Add(p => p.AllowResetPassword, true);
|
||||
});
|
||||
|
||||
Assert.Contains(@$"Forgot password</a>", component.Markup);
|
||||
Assert.Contains(@$"Forgot password?</a>", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -214,7 +195,7 @@ namespace Radzen.Blazor.Tests
|
||||
parameters.Add(p => p.Register, args => { clicked = true; });
|
||||
});
|
||||
|
||||
component.Find(".btn-secondary").Click();
|
||||
component.Find(".rz-secondary").Click();
|
||||
|
||||
Assert.True(clicked);
|
||||
}
|
||||
@@ -240,7 +221,7 @@ namespace Radzen.Blazor.Tests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Login_NotRaises_ResetPasswordEvent_WhenEmptyUsername()
|
||||
public void Login_Raises_ResetPasswordEvent_WhenEmptyUsername()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
@@ -255,19 +236,7 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
component.Find("a").Click();
|
||||
|
||||
Assert.True(!clicked);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Login_Validates_UsernameParameter_OnResetPasswordEvent()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenLogin>();
|
||||
|
||||
component.Find("a").Click();
|
||||
|
||||
Assert.Contains(@$"Username is required", component.Markup);
|
||||
Assert.True(clicked);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@ namespace Radzen.Blazor.Tests
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Change, args => { raised = true; }));
|
||||
parameters.Add<double>(p => p.Value, minValue);
|
||||
parameters.Add<decimal?>(p => p.Min, minValue);
|
||||
});
|
||||
|
||||
@@ -331,5 +332,23 @@ namespace Radzen.Blazor.Tests
|
||||
Assert.DoesNotContain(@$"rz-spinner-up", component.Markup);
|
||||
Assert.DoesNotContain(@$"rz-spinner-down", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Numeric_Formatted()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
double valueToTest = 100.234;
|
||||
string format = "0.00";
|
||||
|
||||
var component = ctx.RenderComponent<RadzenNumeric<double>>(
|
||||
ComponentParameter.CreateParameter(nameof(RadzenNumeric<double>.Format), format),
|
||||
ComponentParameter.CreateParameter(nameof(RadzenNumeric<double>.Value), valueToTest)
|
||||
);
|
||||
|
||||
component.Render();
|
||||
|
||||
Assert.Contains($" value=\"{valueToTest.ToString(format)}\"", component.Markup);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
80
Radzen.Blazor.Tests/PagerTests.cs
Normal file
80
Radzen.Blazor.Tests/PagerTests.cs
Normal file
@@ -0,0 +1,80 @@
|
||||
using Bunit;
|
||||
using Bunit.JSInterop;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class PagerTests
|
||||
{
|
||||
[Fact]
|
||||
public void RadzenPager_AutoHide_If_Count_Is_Less_Than_PageSize()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenPager>(parameters =>
|
||||
{
|
||||
parameters.Add<int>(p => p.PageSize, 20);
|
||||
parameters.Add<int>(p => p.Count, 100);
|
||||
});
|
||||
|
||||
component.Render();
|
||||
|
||||
Assert.Contains(@$"rz-paginator", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add<int>(p => p.PageSize, 101);
|
||||
parameters.Add<int>(p => p.Count, 100);
|
||||
});
|
||||
Assert.DoesNotContain(@$"rz-paginator", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RadzenPager_Dont_AutoHide_If_PageSizeOptions_Specified()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenPager>(parameters =>
|
||||
{
|
||||
parameters.Add<int>(p => p.PageSize, 101);
|
||||
parameters.Add<int>(p => p.Count, 100);
|
||||
parameters.Add<IEnumerable<int>>(p => p.PageSizeOptions, new int[] { 3, 7, 15 });
|
||||
});
|
||||
|
||||
component.Render();
|
||||
|
||||
Assert.Contains(@$"rz-paginator", component.Markup);
|
||||
Assert.Contains(@$"rz-dropdown-trigger", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async void RadzenPager_Renders_Summary() {
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenPager>(parameters => {
|
||||
parameters.Add<int>(p => p.PageSize, 10);
|
||||
parameters.Add<int>(p => p.Count, 100);
|
||||
parameters.Add<bool>(p => p.ShowPagingSummary, true);
|
||||
});
|
||||
await component.Instance.GoToPage(2);
|
||||
component.Render();
|
||||
|
||||
Assert.Contains(@$"rz-paginator-summary", component.Markup);
|
||||
Assert.Contains(@$"Page 3 of 10 (100 items)", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
parameters.Add<bool>(p => p.ShowPagingSummary, false);
|
||||
});
|
||||
Assert.DoesNotContain(@$"rz-paginator-summary", component.Markup);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
98
Radzen.Blazor.Tests/PanelMenuTests.cs
Normal file
98
Radzen.Blazor.Tests/PanelMenuTests.cs
Normal file
@@ -0,0 +1,98 @@
|
||||
using Bunit;
|
||||
using Bunit.TestDoubles;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Routing;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class PanelMenuTests
|
||||
{
|
||||
class TestNavigationManager : NavigationManager
|
||||
{
|
||||
public TestNavigationManager(string uri)
|
||||
{
|
||||
Initialize("http://www.example.com/", uri);
|
||||
}
|
||||
|
||||
protected override void NavigateToCore(string uri, bool forceLoad)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private static string CreatePanelMenu(string currentAbsoluteUrl, NavLinkMatch match, params string[] urls)
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
ctx.Services.RemoveAll<NavigationManager>();
|
||||
ctx.Services.TryAddSingleton<NavigationManager>(new TestNavigationManager(currentAbsoluteUrl));
|
||||
|
||||
var component = ctx.RenderComponent<RadzenPanelMenu>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Match, match).AddChildContent(builder =>
|
||||
{
|
||||
foreach (var url in urls)
|
||||
{
|
||||
builder.OpenComponent<RadzenPanelMenuItem>(0);
|
||||
builder.AddAttribute(1, nameof(RadzenPanelMenuItem.Path), url);
|
||||
builder.CloseComponent();
|
||||
}
|
||||
}));
|
||||
|
||||
return component.Markup;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RadzenPanelMenu_SetsOneActiveMenuItem()
|
||||
{
|
||||
var component = CreatePanelMenu("http://www.example.com/datagrid-dynamic", NavLinkMatch.All, "/datagrid", "/datagrid-dynamic");
|
||||
|
||||
var firstIndex = component.IndexOf("rz-navigation-item-wrapper-active");
|
||||
var lastIndex = component.LastIndexOf("rz-navigation-item-wrapper-active");
|
||||
|
||||
Assert.NotEqual(-1, firstIndex);
|
||||
Assert.Equal(firstIndex, lastIndex);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RadzenPanelMenu_MatchesQueryStringParameters()
|
||||
{
|
||||
var component = CreatePanelMenu("http://www.example.com/foo?bar", NavLinkMatch.Prefix, "/foo");
|
||||
|
||||
Assert.Contains("rz-navigation-item-wrapper-active", component);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RadzenPanelMenu_DoesNotMatchQueryStringParametersWhenExactMatchIsSpecified()
|
||||
{
|
||||
var component = CreatePanelMenu("http://www.example.com/foo?bar", NavLinkMatch.All, "/foo");
|
||||
|
||||
Assert.DoesNotContain("rz-navigation-item-wrapper-active", component);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RadzenPanelMenu_DoesNotMatchRootWithEverything()
|
||||
{
|
||||
var component = CreatePanelMenu("http://www.example.com/foo", NavLinkMatch.Prefix, "/");
|
||||
|
||||
Assert.DoesNotContain("rz-navigation-item-wrapper-active", component);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RadzenPanelMenu_MatchesRoot()
|
||||
{
|
||||
var component = CreatePanelMenu("http://www.example.com/", NavLinkMatch.Prefix, "/");
|
||||
|
||||
Assert.Contains("rz-navigation-item-wrapper-active", component);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RadzenPanelMenu_MatchesRootWithoutTrailingSlash()
|
||||
{
|
||||
var component = CreatePanelMenu("http://www.example.com", NavLinkMatch.Prefix, "/");
|
||||
|
||||
Assert.Contains("rz-navigation-item-wrapper-active", component);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
using Bunit;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using System.Linq;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
@@ -159,7 +161,8 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
var raised = false;
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add<bool>(p => p.AllowCollapse, true);
|
||||
parameters.Add(p => p.Collapse, args => { raised = true; });
|
||||
});
|
||||
@@ -174,5 +177,57 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
component.Find("a").Click();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Panel_Renders_SummaryWhenCollapsed()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenPanel>();
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add<bool>(p => p.AllowCollapse, true);
|
||||
parameters.Add<bool>(p => p.Collapsed, true);
|
||||
parameters.Add<RenderFragment>(p => p.SummaryTemplate, builder =>
|
||||
{
|
||||
builder.OpenElement(0, "p");
|
||||
builder.AddContent(0, "SummaryContent");
|
||||
builder.CloseElement();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
Assert.Contains("SummaryContent", component.Markup);
|
||||
Assert.Equal(
|
||||
"display: block",
|
||||
component.Find(".rz-panel-content-summary").ParentElement.Attributes.First(attr => attr.Name == "style").Value
|
||||
);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Panel_DontRenders_SummaryWhenOpen()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenPanel>();
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add<bool>(p => p.AllowCollapse, true);
|
||||
parameters.Add<bool>(p => p.Collapsed, false);
|
||||
parameters.Add<RenderFragment>(p => p.SummaryTemplate, builder =>
|
||||
{
|
||||
builder.OpenElement(0, "p");
|
||||
builder.AddContent(0, "SummaryContent");
|
||||
builder.CloseElement();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
Assert.Contains("SummaryContent", component.Markup);
|
||||
Assert.Equal(
|
||||
"display: none",
|
||||
component.Find(".rz-panel-content-summary").ParentElement.Attributes.First(attr => attr.Name == "style").Value
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,9 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<double>(p => p.Value, value));
|
||||
|
||||
Assert.Contains(@$"<div class=""rz-progressbar-label"">{value}", component.Markup);
|
||||
|
||||
Assert.Contains(@$"<div class=""rz-progressbar-label"">", component.Markup);
|
||||
Assert.Contains(@$"{value}%", component.Markup);
|
||||
Assert.Contains(@$"aria-valuenow=""{value}""", component.Markup);
|
||||
Assert.Contains(@$"aria-valuemin=""0""", component.Markup);
|
||||
}
|
||||
@@ -50,13 +52,13 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
component.Render();
|
||||
|
||||
Assert.Contains(@$"%</div>", component.Markup);
|
||||
Assert.Contains(@$"0%", component.Markup);
|
||||
|
||||
var value = "mm";
|
||||
var unit = "mm";
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Unit, value));
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Unit, unit));
|
||||
|
||||
Assert.Contains(@$"{value}</div>", component.Markup);
|
||||
Assert.Contains(@$"0{unit}", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -118,5 +120,27 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
Assert.Contains(@$"style=""width: {Math.Min(value / max * 100, 100).ToInvariantString()}%;""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProgressBar_Renders_ProgressBarStyle()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenProgressBar>();
|
||||
|
||||
component.SetParametersAndRender(parameters=>parameters.Add(p=>p.ProgressBarStyle, ProgressBarStyle.Success));
|
||||
Assert.Contains(@$"rz-progressbar-determinate-success", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.ProgressBarStyle, ProgressBarStyle.Info));
|
||||
Assert.Contains(@$"rz-progressbar-determinate-info", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.ProgressBarStyle, ProgressBarStyle.Success));
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Mode, ProgressBarMode.Indeterminate));
|
||||
Assert.Contains(@$"rz-progressbar-indeterminate-success", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.ProgressBarStyle, ProgressBarStyle.Info));
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Mode, ProgressBarMode.Indeterminate));
|
||||
Assert.Contains(@$"rz-progressbar-indeterminate-info", component.Markup);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
96
Radzen.Blazor.Tests/PropertyAccessTests.cs
Normal file
96
Radzen.Blazor.Tests/PropertyAccessTests.cs
Normal file
@@ -0,0 +1,96 @@
|
||||
using AngleSharp.Css;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Dynamic.Core;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class PropertyAccessTests
|
||||
{
|
||||
[Fact]
|
||||
public void Getter_Resolves_Property_On_Simple_Object()
|
||||
{
|
||||
var o = new SimpleObject() { Prop1 = "TestString" };
|
||||
var getter = PropertyAccess.Getter<SimpleObject, string>("Prop1");
|
||||
var value = getter(o);
|
||||
Assert.Equal("TestString", value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Getter_Resolves_Property_On_Simple_Object_QueryableType()
|
||||
{
|
||||
var _data = new List<SimpleObject>()
|
||||
{
|
||||
new SimpleObject() { Prop1 = "TestString" },
|
||||
};
|
||||
|
||||
Func<object, object> getter = PropertyAccess.Getter<object, object>("Prop1");
|
||||
|
||||
var value = getter(_data[0]);
|
||||
Assert.Equal("TestString", value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Getter_Resolves_Property_On_Nested_Object()
|
||||
{
|
||||
var o = new NestedObject() { Obj = new SimpleObject { Prop1 = "TestString" } };
|
||||
var getter = PropertyAccess.Getter<NestedObject, string>("Obj.Prop1");
|
||||
var value = getter(o);
|
||||
Assert.Equal("TestString", value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Getter_Resolves_Property_From_Array()
|
||||
{
|
||||
var o = new ArrayObject() { Values = new string[] { "1", "2", "3" } };
|
||||
var getter = PropertyAccess.Getter<ArrayObject, string>("Values[1]");
|
||||
var value = getter(o);
|
||||
Assert.Equal("2", value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Getter_Resolves_Property_From_Nested_Array()
|
||||
{
|
||||
var o = new NestedArrayObject() { Obj = new ArrayObject() { Values = new string[] { "1", "2", "3" } } };
|
||||
var getter = PropertyAccess.Getter<NestedArrayObject, string>("Obj.Values[2]");
|
||||
var value = getter(o);
|
||||
Assert.Equal("3", value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Getter_Resolves_Property_From_List()
|
||||
{
|
||||
var o = new ListObject() { Values = new List<string>() { "1", "2", "3" } };
|
||||
var getter = PropertyAccess.Getter<ListObject, string>("Values[1]");
|
||||
var value = getter(o);
|
||||
Assert.Equal("2", value);
|
||||
}
|
||||
|
||||
public class SimpleObject
|
||||
{
|
||||
public string Prop1 { get; set; }
|
||||
}
|
||||
|
||||
public class NestedObject
|
||||
{
|
||||
public SimpleObject Obj { get; set; }
|
||||
}
|
||||
|
||||
public class ArrayObject
|
||||
{
|
||||
public string[] Values { get; set; }
|
||||
}
|
||||
|
||||
public class NestedArrayObject
|
||||
{
|
||||
public ArrayObject Obj { get; set; }
|
||||
}
|
||||
|
||||
public class ListObject
|
||||
{
|
||||
public List<string> Values { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,14 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net7</TargetFramework>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />
|
||||
<PackageReference Include="bunit.web" Version="1.0.0-preview-01" />
|
||||
<PackageReference Include="bunit.xunit" Version="1.0.0-preview-01" />
|
||||
<PackageReference Include="bunit.web" Version="1.2.49" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
|
||||
@@ -38,8 +38,8 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<int>(p => p.Value, value));
|
||||
|
||||
Assert.Contains(@$"style=""width: {(value / max * 100).ToInvariantString()}%;""", component.Markup);
|
||||
Assert.Contains(@$"style=""left: {(value / max * 100).ToInvariantString()}%;""", component.Markup);
|
||||
Assert.Contains(@$"style=""width: {Math.Round((value / max * 100)).ToInvariantString()}%;""", component.Markup);
|
||||
Assert.Contains(@$"style=""left: {Math.Round((value / max * 100)).ToInvariantString()}%;""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -55,9 +55,9 @@ namespace Radzen.Blazor.Tests
|
||||
parameters.Add<IEnumerable<int>>(p => p.Value, new int[] { 4, 30 });
|
||||
});
|
||||
|
||||
Assert.Contains(@$"left: 4.00%", component.Markup);
|
||||
Assert.Contains(@$"left: 30.0%", component.Markup);
|
||||
Assert.Contains(@$"left: 4.00%; width: 26.00%;", component.Markup);
|
||||
Assert.Contains(@$"left: 4%", component.Markup);
|
||||
Assert.Contains(@$"left: 30%", component.Markup);
|
||||
Assert.Contains(@$"left: 4%; width: 26%;", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
@@ -127,6 +127,8 @@ namespace Radzen.Blazor.Tests
|
||||
public void SplitButton_Raises_ClickEvent()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenSplitButton>();
|
||||
|
||||
|
||||
@@ -110,7 +110,7 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Change, args => { raised = true; newValue = args; }));
|
||||
|
||||
component.Find("div").MouseUp();
|
||||
component.Find("div").Click();
|
||||
|
||||
Assert.True(raised);
|
||||
Assert.True(object.Equals(value, !(bool)newValue));
|
||||
@@ -129,7 +129,7 @@ namespace Radzen.Blazor.Tests
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.ValueChanged, args => { raised = true; newValue = args; }));
|
||||
|
||||
component.Find("div").MouseUp();
|
||||
component.Find("div").Click();
|
||||
|
||||
Assert.True(raised);
|
||||
Assert.True(object.Equals(value, !(bool)newValue));
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"version": 1,
|
||||
"isRoot": true,
|
||||
"tools": {
|
||||
"excubo.webcompiler": {
|
||||
"version": "2.6.0",
|
||||
"commands": [
|
||||
"webcompiler"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,55 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an appointment in <see cref="RadzenScheduler{TItem}" />
|
||||
/// </summary>
|
||||
public class AppointmentData
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the start of the appointment.
|
||||
/// </summary>
|
||||
/// <value>The start.</value>
|
||||
public DateTime Start { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the end of the appointment.
|
||||
/// </summary>
|
||||
/// <value>The end.</value>
|
||||
public DateTime End { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the text of the appointment.
|
||||
/// </summary>
|
||||
/// <value>The text.</value>
|
||||
public string Text { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the data associated with the appointment
|
||||
/// </summary>
|
||||
/// <value>The data.</value>
|
||||
public object Data { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the specified object is equal to this instance. Used to check if two appointments are equal.
|
||||
/// </summary>
|
||||
/// <param name="obj">The object to compare with this instance.</param>
|
||||
/// <returns><c>true</c> if the specified is equal to this instance; otherwise, <c>false</c>.</returns>
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is AppointmentData data &&
|
||||
Start == data.Start &&
|
||||
End == data.End &&
|
||||
Text == data.Text &&
|
||||
EqualityComparer<object>.Default.Equals(Data, data.Data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a hash code for this instance.
|
||||
/// </summary>
|
||||
/// <returns>A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.</returns>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return HashCode.Combine(Start, End, Text, Data);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,45 +3,106 @@ using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class for an axis in <see cref="RadzenChart" />.
|
||||
/// </summary>
|
||||
public abstract class AxisBase : RadzenChartComponentBase, IChartAxis
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the stroke (line color) of the axis.
|
||||
/// </summary>
|
||||
/// <value>The stroke.</value>
|
||||
[Parameter]
|
||||
public string Stroke { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the pixel width of axis.
|
||||
/// </summary>
|
||||
/// <value>The width of the stroke.</value>
|
||||
[Parameter]
|
||||
public double StrokeWidth { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the child content.
|
||||
/// </summary>
|
||||
/// <value>The child content.</value>
|
||||
[Parameter]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the format string used to display the axis values.
|
||||
/// </summary>
|
||||
/// <value>The format string.</value>
|
||||
[Parameter]
|
||||
public string FormatString { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a formatter function that formats the axis values.
|
||||
/// </summary>
|
||||
/// <value>The formatter.</value>
|
||||
[Parameter]
|
||||
public Func<object, string> Formatter { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the type of the line used to display the axis.
|
||||
/// </summary>
|
||||
/// <value>The type of the line.</value>
|
||||
[Parameter]
|
||||
public LineType LineType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the grid lines configuration of the current axis.
|
||||
/// </summary>
|
||||
/// <value>The grid lines.</value>
|
||||
public RadzenGridLines GridLines { get; set; } = new RadzenGridLines();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the title configuration.
|
||||
/// </summary>
|
||||
/// <value>The title.</value>
|
||||
public RadzenAxisTitle Title { get; set; } = new RadzenAxisTitle();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the ticks configuration.
|
||||
/// </summary>
|
||||
/// <value>The ticks.</value>
|
||||
public RadzenTicks Ticks { get; set; } = new RadzenTicks();
|
||||
|
||||
internal int TickDistance { get; set; } = 100;
|
||||
/// <summary>
|
||||
/// Gets or sets the pixel distance between axis ticks. It is used to calculate the number of visible ticks depending on the available space. Set to 100 by default;
|
||||
/// Setting <see cref="Step" /> will override this value.
|
||||
/// </summary>
|
||||
/// <value>The desired pixel distance between ticks.</value>
|
||||
[Parameter]
|
||||
public int TickDistance { get; set; } = 100;
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the minimum value of the axis.
|
||||
/// </summary>
|
||||
/// <value>The minimum.</value>
|
||||
[Parameter]
|
||||
public object Min { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the maximum value of the axis.
|
||||
/// </summary>
|
||||
/// <value>The maximum.</value>
|
||||
[Parameter]
|
||||
public object Max { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the step of the axis.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public object Step { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this <see cref="AxisBase"/> is visible.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if visible; otherwise, <c>false</c>.</value>
|
||||
[Parameter]
|
||||
public bool Visible { get; set; } = true;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override bool ShouldRefreshChart(ParameterView parameters)
|
||||
{
|
||||
return DidParameterChange(parameters, nameof(Min), Min) ||
|
||||
|
||||
@@ -5,12 +5,22 @@ using System.Linq;
|
||||
using System.Linq.Dynamic.Core;
|
||||
using Radzen.Blazor.Rendering;
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections;
|
||||
using Microsoft.AspNetCore.Components.Rendering;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class of <see cref="RadzenChart" /> series.
|
||||
/// </summary>
|
||||
/// <typeparam name="TItem">The type of the series data.</typeparam>
|
||||
public abstract class CartesianSeries<TItem> : RadzenChartComponentBase, IChartSeries, IDisposable
|
||||
{
|
||||
protected Func<TItem, double> Category(ScaleBase scale)
|
||||
/// <summary>
|
||||
/// Creates a getter function that returns a value from the specified category scale for the specified data item.
|
||||
/// </summary>
|
||||
/// <param name="scale">The scale.</param>
|
||||
internal Func<TItem, double> Category(ScaleBase scale)
|
||||
{
|
||||
if (IsNumeric(CategoryProperty))
|
||||
{
|
||||
@@ -34,16 +44,28 @@ namespace Radzen.Blazor
|
||||
return (item) => Items.IndexOf(item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper function. Used internally.
|
||||
/// </summary>
|
||||
protected Func<TItem, double> ComposeCategory(ScaleBase scale)
|
||||
{
|
||||
return scale.Compose(Category(scale));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper function. Used internally.
|
||||
/// </summary>
|
||||
protected Func<TItem, double> ComposeValue(ScaleBase scale)
|
||||
{
|
||||
return scale.Compose(Value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the property with the specified name is <see cref="DateTime" />
|
||||
/// </summary>
|
||||
/// <param name="propertyName">Name of the property.</param>
|
||||
/// <returns><c>true</c> if the specified property name is date; otherwise, <c>false</c>.</returns>
|
||||
/// <exception cref="ArgumentException">Property {propertyName} does not exist</exception>
|
||||
protected bool IsDate(string propertyName)
|
||||
{
|
||||
if (String.IsNullOrEmpty(propertyName))
|
||||
@@ -61,6 +83,12 @@ namespace Radzen.Blazor
|
||||
return PropertyAccess.IsDate(property);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the property with the specified name is numeric.
|
||||
/// </summary>
|
||||
/// <param name="propertyName">Name of the property.</param>
|
||||
/// <returns><c>true</c> if the specified property name is numeric; otherwise, <c>false</c>.</returns>
|
||||
/// <exception cref="ArgumentException">Property {propertyName} does not exist</exception>
|
||||
protected bool IsNumeric(string propertyName)
|
||||
{
|
||||
if (String.IsNullOrEmpty(propertyName))
|
||||
@@ -78,46 +106,118 @@ namespace Radzen.Blazor
|
||||
return PropertyAccess.IsNumeric(property);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[Parameter]
|
||||
public string Title { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the child content.
|
||||
/// </summary>
|
||||
/// <value>The child content.</value>
|
||||
[Parameter]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the tooltip template.
|
||||
/// </summary>
|
||||
/// <value>The tooltip template.</value>
|
||||
[Parameter]
|
||||
public RenderFragment<TItem> TooltipTemplate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the list of overlays.
|
||||
/// </summary>
|
||||
/// <value>The Overlays list.</value>
|
||||
public IList<IChartSeriesOverlay> Overlays { get; } = new List<IChartSeriesOverlay>();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the coordinate system of the series.
|
||||
/// </summary>
|
||||
/// <value>Coordinate system enum value.</value>
|
||||
public virtual CoordinateSystem CoordinateSystem => CoordinateSystem.Cartesian;
|
||||
|
||||
/// <summary>
|
||||
/// The name of the property of <typeparamref name="TItem" /> that provides the X axis (a.k.a. category axis) values.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string CategoryProperty { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this <see cref="CartesianSeries{TItem}"/> is visible.
|
||||
/// Invisible series do not appear in the legend and cannot be shown by the user.
|
||||
/// Use the <c>Visible</c> property to programatically show or hide a series.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if visible; otherwise, <c>false</c>.</value>
|
||||
[Parameter]
|
||||
public bool Visible { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this <see cref="CartesianSeries{TItem}"/> is hidden.
|
||||
/// Hidden series are initially invisible and the user can show them by clicking on their label in the legend.
|
||||
/// Use the <c>Hidden</c> property to hide certain series from your users but still allow them to see them.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if hidden; otherwise, <c>false</c>.</value>
|
||||
[Parameter]
|
||||
public bool Hidden { get; set; }
|
||||
|
||||
bool IsVisible { get; set; } = true;
|
||||
|
||||
bool IChartSeries.Visible
|
||||
{
|
||||
get
|
||||
{
|
||||
return IsVisible;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool ShowInLegend { get => Visible; }
|
||||
|
||||
/// <summary>
|
||||
/// The name of the property of <typeparamref name="TItem" /> that provides the Y axis (a.k.a. value axis) values.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string ValueProperty { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
[Parameter]
|
||||
public int RenderingOrder { get; set; }
|
||||
|
||||
protected Func<TItem, double> Value
|
||||
/// <summary>
|
||||
/// Creates a getter function that returns a value from the specified data item. Uses <see cref="ValueProperty" />.
|
||||
/// </summary>
|
||||
/// <value>The value.</value>
|
||||
/// <exception cref="ArgumentException">ValueProperty should not be empty</exception>
|
||||
internal Func<TItem, double> Value
|
||||
{
|
||||
get
|
||||
{
|
||||
if (String.IsNullOrEmpty(ValueProperty))
|
||||
{
|
||||
throw new ArgumentException("ValueProperty shoud not be empty");
|
||||
throw new ArgumentException("ValueProperty should not be empty");
|
||||
}
|
||||
|
||||
return PropertyAccess.Getter<TItem, double>(ValueProperty);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the data of the series. The data is enumerated and its items are displayed by the series.
|
||||
/// </summary>
|
||||
/// <value>The data.</value>
|
||||
[Parameter]
|
||||
public IEnumerable<TItem> Data { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Stores <see cref="Data" /> as an IList of <typeparamref name="TItem"/>.
|
||||
/// </summary>
|
||||
/// <value>The items.</value>
|
||||
protected IList<TItem> Items { get; set; } = new List<TItem>();
|
||||
|
||||
/// <inheritdoc />
|
||||
public RadzenMarkers Markers { get; set; } = new RadzenMarkers();
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual MarkerType MarkerType
|
||||
{
|
||||
get
|
||||
@@ -142,6 +242,17 @@ namespace Radzen.Blazor
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the category values
|
||||
/// </summary>
|
||||
protected virtual IList<object> GetCategories()
|
||||
{
|
||||
Func<TItem, object> category = String.IsNullOrEmpty(CategoryProperty) ? (item) => string.Empty : PropertyAccess.Getter<TItem, object>(CategoryProperty);
|
||||
|
||||
return Items.Select(category).ToList();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual ScaleBase TransformCategoryScale(ScaleBase scale)
|
||||
{
|
||||
if (Items == null)
|
||||
@@ -168,9 +279,7 @@ namespace Radzen.Blazor
|
||||
};
|
||||
}
|
||||
|
||||
Func<TItem, object> category = String.IsNullOrEmpty(CategoryProperty) ? (item) => string.Empty : PropertyAccess.Getter<TItem, object>(CategoryProperty);
|
||||
|
||||
var data = Items.Select(category).ToList();
|
||||
var data = GetCategories();
|
||||
|
||||
if (scale is OrdinalScale ordinal)
|
||||
{
|
||||
@@ -199,6 +308,7 @@ namespace Radzen.Blazor
|
||||
};
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual ScaleBase TransformValueScale(ScaleBase scale)
|
||||
{
|
||||
if (Items != null)
|
||||
@@ -212,18 +322,55 @@ namespace Radzen.Blazor
|
||||
return scale;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public abstract RenderFragment Render(ScaleBase categoryScale, ScaleBase valueScale);
|
||||
|
||||
/// <inheritdoc />
|
||||
public RenderFragment RenderOverlays(ScaleBase categoryScale, ScaleBase valueScale)
|
||||
{
|
||||
return new RenderFragment(builder =>
|
||||
{
|
||||
builder.OpenRegion(0);
|
||||
foreach (var overlay in Overlays)
|
||||
{
|
||||
if (overlay.Visible)
|
||||
{
|
||||
builder.AddContent(1, overlay.Render(categoryScale, valueScale));
|
||||
}
|
||||
}
|
||||
builder.CloseRegion();
|
||||
});
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public abstract string Color { get; }
|
||||
|
||||
double MinValue { get; set; }
|
||||
double MaxValue { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override async Task SetParametersAsync(ParameterView parameters)
|
||||
{
|
||||
var shouldRefresh = parameters.DidParameterChange(nameof(Data), Data);
|
||||
var visibleChanged = parameters.DidParameterChange(nameof(Visible), Visible);
|
||||
var hiddenChanged = parameters.DidParameterChange(nameof(Hidden), Hidden);
|
||||
|
||||
await base.SetParametersAsync(parameters);
|
||||
|
||||
if (hiddenChanged)
|
||||
{
|
||||
IsVisible = !Hidden;
|
||||
shouldRefresh = true;
|
||||
}
|
||||
|
||||
if (visibleChanged)
|
||||
{
|
||||
IsVisible = Visible;
|
||||
shouldRefresh = true;
|
||||
}
|
||||
|
||||
if (Data != null && Data.Count() != Items.Count)
|
||||
{
|
||||
shouldRefresh = true;
|
||||
}
|
||||
|
||||
if (shouldRefresh)
|
||||
{
|
||||
if (Data != null)
|
||||
@@ -241,33 +388,36 @@ namespace Radzen.Blazor
|
||||
{
|
||||
Items = Items.AsQueryable().OrderBy(CategoryProperty).ToList();
|
||||
}
|
||||
|
||||
if (Items.Any())
|
||||
{
|
||||
MinValue = Items.Min(Value);
|
||||
MaxValue = Items.Max(Value);
|
||||
}
|
||||
}
|
||||
|
||||
Chart.Refresh(false);
|
||||
await Chart.Refresh(false);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Initialize()
|
||||
{
|
||||
Chart.AddSeries(this);
|
||||
}
|
||||
|
||||
public virtual bool Contains(double x, double y)
|
||||
/// <inheritdoc />
|
||||
public virtual bool Contains(double x, double y, double tolerance)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual double MeasureLegend()
|
||||
{
|
||||
return TextMeasurer.TextWidth(GetTitle());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if the provided point is inside the provided polygon.
|
||||
/// </summary>
|
||||
/// <param name="point">The point.</param>
|
||||
/// <param name="polygon">The polygon.</param>
|
||||
/// <returns><c>true</c> if the polygon contains the point, <c>false</c> otherwise.</returns>
|
||||
protected bool InsidePolygon(Point point, Point[] polygon)
|
||||
{
|
||||
var minX = polygon[0].X;
|
||||
@@ -303,6 +453,7 @@ namespace Radzen.Blazor
|
||||
return inside;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual RenderFragment RenderTooltip(object data, double marginLeft, double marginTop)
|
||||
{
|
||||
var item = (TItem)data;
|
||||
@@ -316,10 +467,7 @@ namespace Radzen.Blazor
|
||||
builder.AddAttribute(1, nameof(ChartTooltip.X), x + marginLeft);
|
||||
builder.AddAttribute(2, nameof(ChartTooltip.Y), y + marginTop);
|
||||
|
||||
if (TooltipTemplate != null)
|
||||
{
|
||||
builder.AddAttribute(3, nameof(ChartTooltip.ChildContent), TooltipTemplate(item));
|
||||
}
|
||||
builder.AddAttribute(3, nameof(ChartTooltip.ChildContent), TooltipTemplate == null ? null : TooltipTemplate(item));
|
||||
|
||||
builder.AddAttribute(4, nameof(ChartTooltip.Title), TooltipTitle(item));
|
||||
builder.AddAttribute(5, nameof(ChartTooltip.Label), TooltipLabel(item));
|
||||
@@ -330,21 +478,30 @@ namespace Radzen.Blazor
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the tooltip inline style.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
protected virtual string TooltipStyle(TItem item)
|
||||
{
|
||||
return Chart.Tooltip.Style;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the tooltip CSS class.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
protected virtual string TooltipClass(TItem item)
|
||||
{
|
||||
return $"rz-series-{Chart.Series.IndexOf(this)}-tooltip";
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual RenderFragment RenderLegendItem()
|
||||
{
|
||||
var style = new List<string>();
|
||||
|
||||
if (Visible == false)
|
||||
if (IsVisible == false)
|
||||
{
|
||||
style.Add("text-decoration: line-through");
|
||||
}
|
||||
@@ -363,6 +520,7 @@ namespace Radzen.Blazor
|
||||
};
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public double MarkerSize
|
||||
{
|
||||
get
|
||||
@@ -378,62 +536,210 @@ namespace Radzen.Blazor
|
||||
}
|
||||
}
|
||||
|
||||
private void OnLegendItemClick()
|
||||
/// <inheritdoc />
|
||||
public double GetMedian()
|
||||
{
|
||||
Chart.ToggleSeries(this);
|
||||
return Data.Select(e => Value(e)).OrderBy(e => e).Skip(Data.Count() / 2).FirstOrDefault();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public double GetMean()
|
||||
{
|
||||
return Data.Select(e => Value(e)).Average();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public double GetMode()
|
||||
{
|
||||
return Data.GroupBy(e => Value(e)).Select(g => new { Value = g.Key, Count = g.Count() }).OrderByDescending(e => e.Count).FirstOrDefault().Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// https://en.wikipedia.org/wiki/Simple_linear_regression#Fitting_the_regression_line
|
||||
/// </summary>
|
||||
public (double a, double b) GetTrend()
|
||||
{
|
||||
double a, b;
|
||||
|
||||
Func<TItem, double> X;
|
||||
Func<TItem, double> Y;
|
||||
if (Chart.ShouldInvertAxes())
|
||||
{
|
||||
X = e => Chart.CategoryScale.Scale(Value(e));
|
||||
Y = e => Chart.ValueScale.Scale(Category(Chart.ValueScale)(e));
|
||||
}
|
||||
else
|
||||
{
|
||||
X = e => Chart.CategoryScale.Scale(Category(Chart.CategoryScale)(e));
|
||||
Y = e => Chart.ValueScale.Scale(Value(e));
|
||||
}
|
||||
|
||||
var avgX = Data.Select(e => X(e)).Average();
|
||||
var avgY = Data.Select(e => Y(e)).Average();
|
||||
var sumXY = Data.Sum(e => (X(e) - avgX) * (Y(e) - avgY));
|
||||
if (Chart.ShouldInvertAxes())
|
||||
{
|
||||
var sumYSq = Data.Sum(e => (Y(e) - avgY) * (Y(e) - avgY));
|
||||
b = sumXY / sumYSq;
|
||||
a = avgX - b * avgY;
|
||||
}
|
||||
else
|
||||
{
|
||||
var sumXSq = Data.Sum(e => (X(e) - avgX) * (X(e) - avgX));
|
||||
b = sumXY / sumXSq;
|
||||
a = avgY - b * avgX;
|
||||
}
|
||||
|
||||
return (a, b);
|
||||
}
|
||||
|
||||
private async Task OnLegendItemClick()
|
||||
{
|
||||
IsVisible = !IsVisible;
|
||||
|
||||
if (Chart.LegendClick.HasDelegate)
|
||||
{
|
||||
var args = new LegendClickEventArgs
|
||||
{
|
||||
Data = this.Data,
|
||||
Title = GetTitle(),
|
||||
IsVisible = IsVisible,
|
||||
};
|
||||
|
||||
await Chart.LegendClick.InvokeAsync(args);
|
||||
|
||||
IsVisible = args.IsVisible;
|
||||
}
|
||||
|
||||
await Chart.Refresh();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string GetTitle()
|
||||
{
|
||||
return String.IsNullOrEmpty(Title) ? $"Series {Chart.Series.IndexOf(this) + 1}" : Title;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the label of the tooltip displayed for this item.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
protected virtual string TooltipLabel(TItem item)
|
||||
{
|
||||
return GetTitle();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the title of the tooltip displayed for this item.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
protected virtual string TooltipTitle(TItem item)
|
||||
{
|
||||
var category = Category(Chart.CategoryScale);
|
||||
return Chart.CategoryAxis.Format(Chart.CategoryScale, Chart.CategoryScale.Value(category(item)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the tooltip displayed for this item.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <returns>System.String.</returns>
|
||||
protected virtual string TooltipValue(TItem item)
|
||||
{
|
||||
return Chart.ValueAxis.Format(Chart.ValueScale, Chart.ValueScale.Value(Value(item)));
|
||||
}
|
||||
|
||||
protected virtual double TooltipX(TItem item)
|
||||
/// <summary>
|
||||
/// Gets the X coordinate of the tooltip of the specified item.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
internal virtual double TooltipX(TItem item)
|
||||
{
|
||||
var category = Category(Chart.CategoryScale);
|
||||
return Chart.CategoryScale.Scale(category(item), true);
|
||||
}
|
||||
|
||||
protected virtual double TooltipY(TItem item)
|
||||
/// <summary>
|
||||
/// Gets the Y coordinate of the tooltip of the specified item.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
internal virtual double TooltipY(TItem item)
|
||||
{
|
||||
return Chart.ValueScale.Scale(Value(item), true);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual object DataAt(double x, double y)
|
||||
{
|
||||
var first = Items.FirstOrDefault();
|
||||
var last = Items.LastOrDefault();
|
||||
if (Items.Any())
|
||||
{
|
||||
return Items.Select(item =>
|
||||
{
|
||||
var distance = Math.Abs(TooltipX(item) - x);
|
||||
return new { Item = item, Distance = distance };
|
||||
}).Aggregate((a, b) => a.Distance < b.Distance ? a : b).Item;
|
||||
}
|
||||
|
||||
var category = Category(Chart.CategoryScale);
|
||||
|
||||
var startX = Chart.CategoryScale.Scale(category(first), true);
|
||||
var endX = Chart.CategoryScale.Scale(category(last), true);
|
||||
|
||||
var count = Math.Max(Items.Count() - 1, 1);
|
||||
var index = Convert.ToInt32((x - startX) / ((endX - startX) / count));
|
||||
|
||||
return Items.ElementAtOrDefault(index);
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual IEnumerable<ChartDataLabel> GetDataLabels(double offsetX, double offsetY)
|
||||
{
|
||||
var list = new List<ChartDataLabel>();
|
||||
|
||||
foreach (var d in Data)
|
||||
{
|
||||
list.Add(new ChartDataLabel
|
||||
{
|
||||
Position = new Point { X = TooltipX(d) + offsetX, Y = TooltipY(d) + offsetY },
|
||||
TextAnchor = "middle",
|
||||
Text = Chart.ValueAxis.Format(Chart.ValueScale, Value(d))
|
||||
});
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a color from the specified list of colors. Rotates colors.
|
||||
/// </summary>
|
||||
/// <param name="index">The index.</param>
|
||||
/// <param name="colors">The colors.</param>
|
||||
/// <param name="defaultValue">The default value.</param>
|
||||
protected string PickColor(int index, IEnumerable<string> colors, string defaultValue = null)
|
||||
{
|
||||
if (colors == null || !colors.Any())
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
return colors.ElementAt(index % colors.Count());
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
Chart?.RemoveSeries(this);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task InvokeClick(EventCallback<SeriesClickEventArgs> handler, object data)
|
||||
{
|
||||
var category = Category(Chart.CategoryScale);
|
||||
|
||||
await handler.InvokeAsync(new SeriesClickEventArgs
|
||||
{
|
||||
Data = data,
|
||||
Title = GetTitle(),
|
||||
Category = PropertyAccess.GetValue(data, CategoryProperty),
|
||||
Value = PropertyAccess.GetValue(data, ValueProperty),
|
||||
Point = new SeriesPoint
|
||||
{
|
||||
Category = category((TItem)data),
|
||||
Value = Value((TItem)data)
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,25 @@
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies the <see cref="RadzenChart" /> color schemes used when rendering the series.
|
||||
/// </summary>
|
||||
public enum ColorScheme
|
||||
{
|
||||
/// <summary>
|
||||
/// Pastel color scheme.
|
||||
/// </summary>
|
||||
Pastel,
|
||||
/// <summary>
|
||||
/// Palette color scheme.
|
||||
/// </summary>
|
||||
Palette,
|
||||
/// <summary>
|
||||
/// Divergent color scheme.
|
||||
/// </summary>
|
||||
Divergent,
|
||||
/// <summary>
|
||||
/// Monochrome color scheme
|
||||
/// </summary>
|
||||
Monochrome
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,10 +7,48 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace Radzen
|
||||
{
|
||||
/// <summary>
|
||||
/// Class ContextMenuService. Contains various methods with options to open and close context menus.
|
||||
/// Should be added as scoped service in the application services and RadzenContextMenu should be added in application main layout.
|
||||
/// Implements the <see cref="IDisposable" />
|
||||
/// </summary>
|
||||
/// <seealso cref="IDisposable" />
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// @inject ContextMenuService ContextMenuService
|
||||
/// <RadzenButton Text="Show context menu" ContextMenu=@(args => ShowContextMenuWithContent(args)) />
|
||||
/// @code {
|
||||
/// void ShowContextMenuWithContent(MouseEventArgs args) => ContextMenuService.Open(args, ds =>
|
||||
/// @<RadzenMenu Click="OnMenuItemClick">
|
||||
/// <RadzenMenuItem Text="Item1" Value="1"></RadzenMenuItem>
|
||||
/// <RadzenMenuItem Text="Item2" Value="2"></RadzenMenuItem>
|
||||
/// <RadzenMenuItem Text="More items" Value="3">
|
||||
/// <RadzenMenuItem Text="More sub items" Value="4">
|
||||
/// <RadzenMenuItem Text="Item1" Value="5"></RadzenMenuItem>
|
||||
/// <RadzenMenuItem Text="Item2" Value="6"></RadzenMenuItem>
|
||||
/// </RadzenMenuItem>
|
||||
/// </RadzenMenuItem>
|
||||
/// </RadzenMenu>);
|
||||
///
|
||||
/// void OnMenuItemClick(MenuItemEventArgs args)
|
||||
/// {
|
||||
/// Console.WriteLine($"Menu item with Value={args.Value} clicked");
|
||||
/// }
|
||||
/// }
|
||||
/// </code>
|
||||
/// </example>
|
||||
public class ContextMenuService : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the navigation manager.
|
||||
/// </summary>
|
||||
/// <value>The navigation manager.</value>
|
||||
NavigationManager navigationManager { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ContextMenuService"/> class.
|
||||
/// </summary>
|
||||
/// <param name="uriHelper">The URI helper.</param>
|
||||
public ContextMenuService(NavigationManager uriHelper)
|
||||
{
|
||||
navigationManager = uriHelper;
|
||||
@@ -21,6 +59,11 @@ namespace Radzen
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the OnLocationChanged event of the UriHelper control.
|
||||
/// </summary>
|
||||
/// <param name="sender">The source of the event.</param>
|
||||
/// <param name="e">The <see cref="Microsoft.AspNetCore.Components.Routing.LocationChangedEventArgs"/> instance containing the event data.</param>
|
||||
private void UriHelper_OnLocationChanged(object sender, Microsoft.AspNetCore.Components.Routing.LocationChangedEventArgs e)
|
||||
{
|
||||
if (this.OnNavigate != null)
|
||||
@@ -29,12 +72,27 @@ namespace Radzen
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when [on navigate].
|
||||
/// </summary>
|
||||
public event Action OnNavigate;
|
||||
|
||||
/// <summary>
|
||||
/// Raises the Close event.
|
||||
/// </summary>
|
||||
public event Action OnClose;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when [on open].
|
||||
/// </summary>
|
||||
public event Action<MouseEventArgs, ContextMenuOptions> OnOpen;
|
||||
|
||||
/// <summary>
|
||||
/// Opens the specified arguments.
|
||||
/// </summary>
|
||||
/// <param name="args">The <see cref="MouseEventArgs"/> instance containing the event data.</param>
|
||||
/// <param name="items">The items.</param>
|
||||
/// <param name="click">The click.</param>
|
||||
public void Open(MouseEventArgs args, IEnumerable<ContextMenuItem> items, Action<MenuItemEventArgs> click = null)
|
||||
{
|
||||
var options = new ContextMenuOptions();
|
||||
@@ -45,6 +103,11 @@ namespace Radzen
|
||||
OpenTooltip(args, options);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens the specified arguments.
|
||||
/// </summary>
|
||||
/// <param name="args">The <see cref="MouseEventArgs"/> instance containing the event data.</param>
|
||||
/// <param name="childContent">Content of the child.</param>
|
||||
public void Open(MouseEventArgs args, RenderFragment<ContextMenuService> childContent)
|
||||
{
|
||||
var options = new ContextMenuOptions();
|
||||
@@ -54,39 +117,87 @@ namespace Radzen
|
||||
OpenTooltip(args, options);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens the tooltip.
|
||||
/// </summary>
|
||||
/// <param name="args">The <see cref="MouseEventArgs"/> instance containing the event data.</param>
|
||||
/// <param name="options">The options.</param>
|
||||
private void OpenTooltip(MouseEventArgs args, ContextMenuOptions options)
|
||||
{
|
||||
OnOpen?.Invoke(args, options);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Closes this instance.
|
||||
/// </summary>
|
||||
public void Close()
|
||||
{
|
||||
OnClose?.Invoke();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disposes this instance.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
navigationManager.LocationChanged -= UriHelper_OnLocationChanged;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Class ContextMenuOptions.
|
||||
/// </summary>
|
||||
public class ContextMenuOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the child content.
|
||||
/// </summary>
|
||||
/// <value>The child content.</value>
|
||||
public RenderFragment<ContextMenuService> ChildContent { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the items.
|
||||
/// </summary>
|
||||
/// <value>The items.</value>
|
||||
public IEnumerable<ContextMenuItem> Items { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the click.
|
||||
/// </summary>
|
||||
/// <value>The click.</value>
|
||||
public Action<MenuItemEventArgs> Click { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Class ContextMenu.
|
||||
/// </summary>
|
||||
public class ContextMenu
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the options.
|
||||
/// </summary>
|
||||
/// <value>The options.</value>
|
||||
public ContextMenuOptions Options { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the mouse event arguments.
|
||||
/// </summary>
|
||||
/// <value>The mouse event arguments.</value>
|
||||
public MouseEventArgs MouseEventArgs { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Class ContextMenuItem.
|
||||
/// </summary>
|
||||
public class ContextMenuItem
|
||||
{
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the text.
|
||||
/// </summary>
|
||||
/// <value>The text.</value>
|
||||
public string Text { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the value.
|
||||
/// </summary>
|
||||
/// <value>The value.</value>
|
||||
public object Value { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,37 +8,85 @@ using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Forms;
|
||||
using Radzen.Blazor;
|
||||
using Radzen.Blazor.Rendering;
|
||||
|
||||
namespace Radzen
|
||||
{
|
||||
/// <summary>
|
||||
/// Class DataBoundFormComponent.
|
||||
/// Implements the <see cref="Radzen.RadzenComponent" />
|
||||
/// Implements the <see cref="Radzen.IRadzenFormComponent" />
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <seealso cref="Radzen.RadzenComponent" />
|
||||
/// <seealso cref="Radzen.IRadzenFormComponent" />
|
||||
public class DataBoundFormComponent<T> : RadzenComponent, IRadzenFormComponent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the index of the tab.
|
||||
/// </summary>
|
||||
/// <value>The index of the tab.</value>
|
||||
[Parameter]
|
||||
public int TabIndex { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the filter case sensitivity.
|
||||
/// </summary>
|
||||
/// <value>The filter case sensitivity.</value>
|
||||
[Parameter]
|
||||
public FilterCaseSensitivity FilterCaseSensitivity { get; set; } = FilterCaseSensitivity.Default;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the filter operator.
|
||||
/// </summary>
|
||||
/// <value>The filter operator.</value>
|
||||
[Parameter]
|
||||
public StringFilterOperator FilterOperator { get; set; } = StringFilterOperator.Contains;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name.
|
||||
/// </summary>
|
||||
/// <value>The name.</value>
|
||||
[Parameter]
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the placeholder.
|
||||
/// </summary>
|
||||
/// <value>The placeholder.</value>
|
||||
[Parameter]
|
||||
public string Placeholder { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this <see cref="DataBoundFormComponent{T}"/> is disabled.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if disabled; otherwise, <c>false</c>.</value>
|
||||
[Parameter]
|
||||
public bool Disabled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the change.
|
||||
/// </summary>
|
||||
/// <value>The change.</value>
|
||||
[Parameter]
|
||||
public EventCallback<object> Change { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the load data.
|
||||
/// </summary>
|
||||
/// <value>The load data.</value>
|
||||
[Parameter]
|
||||
public EventCallback<Radzen.LoadDataArgs> LoadData { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The form
|
||||
/// </summary>
|
||||
IRadzenForm _form;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the form.
|
||||
/// </summary>
|
||||
/// <value>The form.</value>
|
||||
[CascadingParameter]
|
||||
public IRadzenForm Form
|
||||
{
|
||||
@@ -48,15 +96,19 @@ namespace Radzen
|
||||
}
|
||||
set
|
||||
{
|
||||
if (_form != value && value != null)
|
||||
{
|
||||
_form = value;
|
||||
_form.AddComponent(this);
|
||||
}
|
||||
_form = value;
|
||||
_form?.AddComponent(this);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The value
|
||||
/// </summary>
|
||||
object _value;
|
||||
/// <summary>
|
||||
/// Gets or sets the value.
|
||||
/// </summary>
|
||||
/// <value>The value.</value>
|
||||
[Parameter]
|
||||
public object Value
|
||||
{
|
||||
@@ -73,9 +125,17 @@ namespace Radzen
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the value changed.
|
||||
/// </summary>
|
||||
/// <value>The value changed.</value>
|
||||
[Parameter]
|
||||
public EventCallback<T> ValueChanged { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this instance is bound.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance is bound; otherwise, <c>false</c>.</value>
|
||||
public bool IsBound
|
||||
{
|
||||
get
|
||||
@@ -83,7 +143,11 @@ namespace Radzen
|
||||
return ValueChanged.HasDelegate;
|
||||
}
|
||||
}
|
||||
public bool HasValue
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this instance has value.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance has value; otherwise, <c>false</c>.</value>
|
||||
public virtual bool HasValue
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -95,10 +159,21 @@ namespace Radzen
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the text property.
|
||||
/// </summary>
|
||||
/// <value>The text property.</value>
|
||||
[Parameter]
|
||||
public string TextProperty { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The data
|
||||
/// </summary>
|
||||
IEnumerable _data = null;
|
||||
/// <summary>
|
||||
/// Gets or sets the data.
|
||||
/// </summary>
|
||||
/// <value>The data.</value>
|
||||
[Parameter]
|
||||
public virtual IEnumerable Data
|
||||
{
|
||||
@@ -113,17 +188,23 @@ namespace Radzen
|
||||
_view = null;
|
||||
_value = null;
|
||||
_data = value;
|
||||
OnDataChanged();
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void OnDataChanged()
|
||||
/// <summary>
|
||||
/// Called when [data changed].
|
||||
/// </summary>
|
||||
protected virtual async Task OnDataChanged()
|
||||
{
|
||||
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the query.
|
||||
/// </summary>
|
||||
/// <value>The query.</value>
|
||||
protected virtual IQueryable Query
|
||||
{
|
||||
get
|
||||
@@ -132,9 +213,19 @@ namespace Radzen
|
||||
}
|
||||
}
|
||||
|
||||
protected string searchText;
|
||||
/// <summary>
|
||||
/// The search text
|
||||
/// </summary>
|
||||
internal string searchText;
|
||||
|
||||
/// <summary>
|
||||
/// The view
|
||||
/// </summary>
|
||||
protected IQueryable _view = null;
|
||||
/// <summary>
|
||||
/// Gets the view.
|
||||
/// </summary>
|
||||
/// <value>The view.</value>
|
||||
protected virtual IEnumerable View
|
||||
{
|
||||
get
|
||||
@@ -171,15 +262,38 @@ namespace Radzen
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the edit context.
|
||||
/// </summary>
|
||||
/// <value>The edit context.</value>
|
||||
[CascadingParameter]
|
||||
public EditContext EditContext { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the field identifier.
|
||||
/// </summary>
|
||||
/// <value>The field identifier.</value>
|
||||
public FieldIdentifier FieldIdentifier { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the value expression.
|
||||
/// </summary>
|
||||
/// <value>The value expression.</value>
|
||||
[Parameter]
|
||||
public Expression<Func<T>> ValueExpression { get; set; }
|
||||
public override Task SetParametersAsync(ParameterView parameters)
|
||||
/// <summary>
|
||||
/// Set parameters as an asynchronous operation.
|
||||
/// </summary>
|
||||
/// <param name="parameters">The parameters.</param>
|
||||
/// <returns>A Task representing the asynchronous operation.</returns>
|
||||
public override async Task SetParametersAsync(ParameterView parameters)
|
||||
{
|
||||
var dataChanged = parameters.DidParameterChange(nameof(Data), Data);
|
||||
if (dataChanged)
|
||||
{
|
||||
await OnDataChanged();
|
||||
}
|
||||
|
||||
var result = base.SetParametersAsync(parameters);
|
||||
|
||||
if (EditContext != null && ValueExpression != null && FieldIdentifier.Model != EditContext.Model)
|
||||
@@ -188,14 +302,22 @@ namespace Radzen
|
||||
EditContext.OnValidationStateChanged += ValidationStateChanged;
|
||||
}
|
||||
|
||||
return result;
|
||||
await result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validations the state changed.
|
||||
/// </summary>
|
||||
/// <param name="sender">The sender.</param>
|
||||
/// <param name="e">The <see cref="ValidationStateChangedEventArgs"/> instance containing the event data.</param>
|
||||
private void ValidationStateChanged(object sender, ValidationStateChangedEventArgs e)
|
||||
{
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disposes this instance.
|
||||
/// </summary>
|
||||
public override void Dispose()
|
||||
{
|
||||
base.Dispose();
|
||||
@@ -208,9 +330,23 @@ namespace Radzen
|
||||
Form?.RemoveComponent(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value.
|
||||
/// </summary>
|
||||
/// <returns>System.Object.</returns>
|
||||
public object GetValue()
|
||||
{
|
||||
return Value;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets the class list.
|
||||
/// </summary>
|
||||
/// <param name="className">Name of the class.</param>
|
||||
/// <returns>ClassList.</returns>
|
||||
protected ClassList GetClassList(string className) => ClassList.Create(className)
|
||||
.AddDisabled(Disabled)
|
||||
.Add(FieldIdentifier, EditContext);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.JSInterop;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@@ -6,13 +7,66 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace Radzen
|
||||
{
|
||||
/// <summary>
|
||||
/// Class DialogService. Contains various methods with options to open and close dialogs.
|
||||
/// Should be added as scoped service in the application services and RadzenDialog should be added in application main layout.
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// @inject DialogService DialogService
|
||||
/// <RadzenButton Text="Show dialog with inline Blazor content" Click=@ShowInlineDialog />
|
||||
/// @code {
|
||||
/// async Task ShowInlineDialog()
|
||||
/// {
|
||||
/// var result = await DialogService.OpenAsync("Simple Dialog", ds =>
|
||||
/// @<div>
|
||||
/// <p Style="margin-bottom: 1rem">Confirm?</p>
|
||||
/// <div class="row">
|
||||
/// <div class="col-md-12">
|
||||
/// <RadzenButton Text="Ok" Click="() => ds.Close(true)" Style="margin-bottom: 10px; width: 150px" />
|
||||
/// <RadzenButton Text="Cancel" Click="() => ds.Close(false)" ButtonStyle="ButtonStyle.Secondary" Style="margin-bottom: 10px; width: 150px"/>
|
||||
/// <RadzenButton Text="Refresh" Click="(() => { orderID = 10249; ds.Refresh(); })" ButtonStyle="ButtonStyle.Info" Style="margin-bottom: 10px; width: 150px"/>
|
||||
/// Order ID: @orderID
|
||||
/// </div>
|
||||
/// </div>
|
||||
/// </div>);
|
||||
/// Console.WriteLine($"Dialog result: {result}");
|
||||
/// }
|
||||
/// }
|
||||
/// </code>
|
||||
/// </example>
|
||||
public class DialogService : IDisposable
|
||||
{
|
||||
NavigationManager UriHelper { get; set; }
|
||||
private DotNetObjectReference<DialogService> reference;
|
||||
internal DotNetObjectReference<DialogService> Reference
|
||||
{
|
||||
get
|
||||
{
|
||||
if (reference == null)
|
||||
{
|
||||
reference = DotNetObjectReference.Create(this);
|
||||
}
|
||||
|
||||
public DialogService(NavigationManager uriHelper)
|
||||
return reference;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the URI helper.
|
||||
/// </summary>
|
||||
/// <value>The URI helper.</value>
|
||||
NavigationManager UriHelper { get; set; }
|
||||
IJSRuntime JSRuntime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DialogService"/> class.
|
||||
/// </summary>
|
||||
/// <param name="uriHelper">The URI helper.</param>
|
||||
/// <param name="jsRuntime">IJSRuntime instance.</param>
|
||||
public DialogService(NavigationManager uriHelper, IJSRuntime jsRuntime)
|
||||
{
|
||||
UriHelper = uriHelper;
|
||||
JSRuntime = jsRuntime;
|
||||
|
||||
if (UriHelper != null)
|
||||
{
|
||||
@@ -24,28 +78,58 @@ namespace Radzen
|
||||
{
|
||||
if (dialogs.Count > 0)
|
||||
{
|
||||
this.Close();
|
||||
Close();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the Close event.
|
||||
/// </summary>
|
||||
public event Action<dynamic> OnClose;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when [on refresh].
|
||||
/// </summary>
|
||||
public event Action OnRefresh;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when a new dialog is open.
|
||||
/// </summary>
|
||||
public event Action<string, Type, Dictionary<string, object>, DialogOptions> OnOpen;
|
||||
|
||||
/// <summary>
|
||||
/// Opens a dialog with the specified arguments.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the Blazor component which will be displayed in a dialog.</typeparam>
|
||||
/// <param name="title">The text displayed in the title bar of the dialog.</param>
|
||||
/// <param name="parameters">The dialog parameters. Passed as property values of <typeparamref name="T" />.</param>
|
||||
/// <param name="options">The dialog options.</param>
|
||||
public void Open<T>(string title, Dictionary<string, object> parameters = null, DialogOptions options = null) where T : ComponentBase
|
||||
{
|
||||
OpenDialog<T>(title, parameters, options);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invokes <see cref="OnRefresh" />.
|
||||
/// </summary>
|
||||
public void Refresh()
|
||||
{
|
||||
OnRefresh?.Invoke();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The tasks
|
||||
/// </summary>
|
||||
protected List<TaskCompletionSource<dynamic>> tasks = new List<TaskCompletionSource<dynamic>>();
|
||||
|
||||
/// <summary>
|
||||
/// Opens a dialog with the specified arguments.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the Blazor component which will be displayed in a dialog.</typeparam>
|
||||
/// <param name="title">The text displayed in the title bar of the dialog.</param>
|
||||
/// <param name="parameters">The dialog parameters. Passed as property values of <typeparamref name="T" />.</param>
|
||||
/// <param name="options">The dialog options.</param>
|
||||
/// <returns>The value passed as argument to <see cref="Close" />.</returns>
|
||||
public Task<dynamic> OpenAsync<T>(string title, Dictionary<string, object> parameters = null, DialogOptions options = null) where T : ComponentBase
|
||||
{
|
||||
var task = new TaskCompletionSource<dynamic>();
|
||||
@@ -55,6 +139,14 @@ namespace Radzen
|
||||
|
||||
return task.Task;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens a dialog with the specified content.
|
||||
/// </summary>
|
||||
/// <param name="title">The text displayed in the title bar of the dialog.</param>
|
||||
/// <param name="childContent">The content displayed in the dialog.</param>
|
||||
/// <param name="options">The dialog options.</param>
|
||||
/// <returns>The value passed as argument to <see cref="Close" />.</returns>
|
||||
public Task<dynamic> OpenAsync(string title, RenderFragment<DialogService> childContent, DialogOptions options = null)
|
||||
{
|
||||
var task = new TaskCompletionSource<dynamic>();
|
||||
@@ -69,6 +161,12 @@ namespace Radzen
|
||||
return task.Task;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens a dialog with the specified content.
|
||||
/// </summary>
|
||||
/// <param name="title">The text displayed in the title bar of the dialog.</param>
|
||||
/// <param name="childContent">The content displayed in the dialog.</param>
|
||||
/// <param name="options">The dialog options.</param>
|
||||
public void Open(string title, RenderFragment<DialogService> childContent, DialogOptions options = null)
|
||||
{
|
||||
options = options ?? new DialogOptions();
|
||||
@@ -78,7 +176,11 @@ namespace Radzen
|
||||
OpenDialog<object>(title, null, options);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The dialogs
|
||||
/// </summary>
|
||||
protected List<object> dialogs = new List<object>();
|
||||
|
||||
private void OpenDialog<T>(string title, Dictionary<string, object> parameters, DialogOptions options)
|
||||
{
|
||||
dialogs.Add(new object());
|
||||
@@ -87,105 +189,295 @@ namespace Radzen
|
||||
Width = options != null && !string.IsNullOrEmpty(options.Width) ? options.Width : "600px",
|
||||
Left = options != null && !string.IsNullOrEmpty(options.Left) ? options.Left : "",
|
||||
Top = options != null && !string.IsNullOrEmpty(options.Top) ? options.Top : "",
|
||||
Bottom = options != null && !string.IsNullOrEmpty(options.Bottom) ? options.Bottom : "",
|
||||
Height = options != null && !string.IsNullOrEmpty(options.Height) ? options.Height : "",
|
||||
ShowTitle = options != null ? options.ShowTitle : true,
|
||||
ShowClose = options != null ? options.ShowClose : true,
|
||||
ChildContent = options?.ChildContent
|
||||
Resizable = options != null ? options.Resizable : false,
|
||||
Draggable = options != null ? options.Draggable : false,
|
||||
ChildContent = options?.ChildContent,
|
||||
Style = options != null ? options.Style : "",
|
||||
AutoFocusFirstElement = options != null ? options.AutoFocusFirstElement : true,
|
||||
CloseDialogOnOverlayClick = options != null ? options.CloseDialogOnOverlayClick : false,
|
||||
CloseDialogOnEsc = options != null ? options.CloseDialogOnEsc : true,
|
||||
CssClass = options != null ? options.CssClass : "",
|
||||
});
|
||||
}
|
||||
|
||||
public void Close(dynamic result = null)
|
||||
/// <summary>
|
||||
/// Closes the last opened dialog with optional result.
|
||||
/// </summary>
|
||||
/// <param name="result">The result.</param>
|
||||
[JSInvokable("DialogService.Close")]
|
||||
public virtual void Close(dynamic result = null)
|
||||
{
|
||||
OnClose?.Invoke(result);
|
||||
|
||||
var dialog = dialogs.LastOrDefault();
|
||||
|
||||
if (dialog != null)
|
||||
{
|
||||
OnClose?.Invoke(result);
|
||||
dialogs.Remove(dialog);
|
||||
}
|
||||
|
||||
var task = tasks.LastOrDefault();
|
||||
if (task != null && task.Task != null && !task.Task.IsCompleted)
|
||||
{
|
||||
task.SetResult(result);
|
||||
tasks.Remove(task);
|
||||
task.SetResult(result);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
reference?.Dispose();
|
||||
reference = null;
|
||||
|
||||
UriHelper.LocationChanged -= UriHelper_OnLocationChanged;
|
||||
}
|
||||
|
||||
public async Task<bool?> Confirm(string message = "Confirm?", string title = "Confirm", ConfirmOptions options = null) => await OpenAsync(title, ds => {
|
||||
RenderFragment content = b =>
|
||||
{
|
||||
var i = 0;
|
||||
b.OpenElement(i++, "div");
|
||||
b.OpenElement(i++, "p");
|
||||
b.AddAttribute(i++, "style", "margin-bottom: 20px;");
|
||||
b.AddContent(i++, message);
|
||||
b.CloseElement();
|
||||
|
||||
b.OpenElement(i++, "div");
|
||||
b.AddAttribute(i++, "class", "row");
|
||||
b.OpenElement(i++, "div");
|
||||
b.AddAttribute(i++, "class", "col-md-12");
|
||||
|
||||
b.OpenComponent<Blazor.RadzenButton>(i++);
|
||||
b.AddAttribute(i++, "Text", options != null ? options.OkButtonText : "Ok");
|
||||
b.AddAttribute(i++, "Style", "margin-bottom: 10px; width: 150px");
|
||||
b.AddAttribute(i++, "Click", EventCallback.Factory.Create<Microsoft.AspNetCore.Components.Web.MouseEventArgs>(this, () => ds.Close(true)));
|
||||
b.CloseComponent();
|
||||
|
||||
b.OpenComponent<Blazor.RadzenButton>(i++);
|
||||
b.AddAttribute(i++, "Text", options != null ? options.CancelButtonText : "Cancel");
|
||||
b.AddAttribute(i++, "ButtonStyle", ButtonStyle.Secondary);
|
||||
b.AddAttribute(i++, "Style", "margin-bottom: 10px; margin-left: 10px; width: 150px");
|
||||
b.AddAttribute(i++, "Click", EventCallback.Factory.Create<Microsoft.AspNetCore.Components.Web.MouseEventArgs>(this, () => ds.Close(false)));
|
||||
b.CloseComponent();
|
||||
|
||||
b.CloseElement();
|
||||
b.CloseElement();
|
||||
b.CloseElement();
|
||||
};
|
||||
return content;
|
||||
}, new DialogOptions()
|
||||
/// <summary>
|
||||
/// Displays a confirmation dialog.
|
||||
/// </summary>
|
||||
/// <param name="message">The message displayed to the user.</param>
|
||||
/// <param name="title">The text displayed in the title bar of the dialog.</param>
|
||||
/// <param name="options">The options.</param>
|
||||
/// <returns><c>true</c> if the user clicked the OK button, <c>false</c> otherwise.</returns>
|
||||
public async Task<bool?> Confirm(string message = "Confirm?", string title = "Confirm", ConfirmOptions options = null)
|
||||
{
|
||||
Width = options != null ? !string.IsNullOrEmpty(options.Width) ? options.Width : "355px" : "355px",
|
||||
Height = options != null ? options.Height : null,
|
||||
Left = options != null ? options.Left : null,
|
||||
Top = options != null ? options.Top : null,
|
||||
Bottom = options != null ? options.Bottom : null,
|
||||
ChildContent = options != null ? options.ChildContent : null,
|
||||
ShowTitle = options != null ? options.ShowTitle : true,
|
||||
ShowClose = options != null ? options.ShowClose : true
|
||||
});
|
||||
var dialogOptions = new DialogOptions()
|
||||
{
|
||||
Width = options != null ? !string.IsNullOrEmpty(options.Width) ? options.Width : "" : "",
|
||||
Height = options != null ? options.Height : null,
|
||||
Left = options != null ? options.Left : null,
|
||||
Top = options != null ? options.Top : null,
|
||||
Bottom = options != null ? options.Bottom : null,
|
||||
ChildContent = options != null ? options.ChildContent : null,
|
||||
ShowTitle = options != null ? options.ShowTitle : true,
|
||||
ShowClose = options != null ? options.ShowClose : true,
|
||||
Resizable = options != null ? options.Resizable : false,
|
||||
Draggable = options != null ? options.Draggable : false,
|
||||
Style = options != null ? options.Style : "",
|
||||
AutoFocusFirstElement = options != null ? options.AutoFocusFirstElement : true,
|
||||
CloseDialogOnOverlayClick = options != null ? options.CloseDialogOnOverlayClick : false,
|
||||
CloseDialogOnEsc = options != null ? options.CloseDialogOnEsc : true,
|
||||
CssClass = options != null ? $"rz-dialog-confirm {options.CssClass}" : "rz-dialog-confirm",
|
||||
};
|
||||
|
||||
return await OpenAsync(title, ds =>
|
||||
{
|
||||
RenderFragment content = b =>
|
||||
{
|
||||
var i = 0;
|
||||
b.OpenElement(i++, "p");
|
||||
b.AddAttribute(i++, "class", "rz-dialog-confirm-message");
|
||||
b.AddContent(i++, message);
|
||||
b.CloseElement();
|
||||
|
||||
b.OpenElement(i++, "div");
|
||||
b.AddAttribute(i++, "class", "rz-dialog-confirm-buttons");
|
||||
|
||||
b.OpenComponent<Blazor.RadzenButton>(i++);
|
||||
b.AddAttribute(i++, "Text", options != null ? options.OkButtonText : "Ok");
|
||||
b.AddAttribute(i++, "Click", EventCallback.Factory.Create<Microsoft.AspNetCore.Components.Web.MouseEventArgs>(this, () => ds.Close(true)));
|
||||
b.CloseComponent();
|
||||
|
||||
b.OpenComponent<Blazor.RadzenButton>(i++);
|
||||
b.AddAttribute(i++, "Text", options != null ? options.CancelButtonText : "Cancel");
|
||||
b.AddAttribute(i++, "ButtonStyle", ButtonStyle.Secondary);
|
||||
b.AddAttribute(i++, "Click", EventCallback.Factory.Create<Microsoft.AspNetCore.Components.Web.MouseEventArgs>(this, () => ds.Close(false)));
|
||||
b.CloseComponent();
|
||||
|
||||
b.CloseElement();
|
||||
};
|
||||
return content;
|
||||
}, dialogOptions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Displays a alert dialog.
|
||||
/// </summary>
|
||||
/// <param name="message">The message displayed to the user.</param>
|
||||
/// <param name="title">The text displayed in the title bar of the dialog.</param>
|
||||
/// <param name="options">The options.</param>
|
||||
/// <returns><c>true</c> if the user clicked the OK button, <c>false</c> otherwise.</returns>
|
||||
public async Task<bool?> Alert(string message = "", string title = "Message", AlertOptions options = null)
|
||||
{
|
||||
var dialogOptions = new DialogOptions()
|
||||
{
|
||||
Width = options != null ? !string.IsNullOrEmpty(options.Width) ? options.Width : "" : "",
|
||||
Height = options != null ? options.Height : null,
|
||||
Left = options != null ? options.Left : null,
|
||||
Top = options != null ? options.Top : null,
|
||||
Bottom = options != null ? options.Bottom : null,
|
||||
ChildContent = options != null ? options.ChildContent : null,
|
||||
ShowTitle = options != null ? options.ShowTitle : true,
|
||||
ShowClose = options != null ? options.ShowClose : true,
|
||||
Resizable = options != null ? options.Resizable : false,
|
||||
Draggable = options != null ? options.Draggable : false,
|
||||
Style = options != null ? options.Style : "",
|
||||
AutoFocusFirstElement = options != null ? options.AutoFocusFirstElement : true,
|
||||
CloseDialogOnOverlayClick = options != null ? options.CloseDialogOnOverlayClick : false,
|
||||
CloseDialogOnEsc = options != null ? options.CloseDialogOnEsc : true,
|
||||
CssClass = options != null ? $"rz-dialog-alert {options.CssClass}" : "rz-dialog-alert",
|
||||
};
|
||||
|
||||
return await OpenAsync(title, ds =>
|
||||
{
|
||||
RenderFragment content = b =>
|
||||
{
|
||||
var i = 0;
|
||||
b.OpenElement(i++, "p");
|
||||
b.AddAttribute(i++, "class", "rz-dialog-alert-message");
|
||||
b.AddContent(i++, message);
|
||||
b.CloseElement();
|
||||
|
||||
b.OpenElement(i++, "div");
|
||||
b.AddAttribute(i++, "class", "rz-dialog-alert-buttons");
|
||||
|
||||
b.OpenComponent<Blazor.RadzenButton>(i++);
|
||||
b.AddAttribute(i++, "Text", options != null ? options.OkButtonText : "Ok");
|
||||
b.AddAttribute(i++, "Click", EventCallback.Factory.Create<Microsoft.AspNetCore.Components.Web.MouseEventArgs>(this, () => ds.Close(true)));
|
||||
b.CloseComponent();
|
||||
|
||||
b.CloseElement();
|
||||
};
|
||||
return content;
|
||||
}, dialogOptions);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Class DialogOptions.
|
||||
/// </summary>
|
||||
public class DialogOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to show the title bar. Set to <c>true</c> by default.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if title bar is shown; otherwise, <c>false</c>.</value>
|
||||
public bool ShowTitle { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to show the close button. Set to <c>true</c> by default.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if the close button is shown; otherwise, <c>false</c>.</value>
|
||||
public bool ShowClose { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the dialog is resizable. Set to <c>false</c> by default.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if resizable; otherwise, <c>false</c>.</value>
|
||||
public bool Resizable { get; set; } = false;
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the dialog is draggable. Set to <c>false</c> by default.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if draggable; otherwise, <c>false</c>.</value>
|
||||
public bool Draggable { get; set; } = false;
|
||||
/// <summary>
|
||||
/// Gets or sets the X coordinate of the dialog. Maps to the <c>left</c> CSS attribute.
|
||||
/// </summary>
|
||||
/// <value>The left.</value>
|
||||
public string Left { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the Y coordinate of the dialog. Maps to the <c>top</c> CSS attribute.
|
||||
/// </summary>
|
||||
/// <value>The top.</value>
|
||||
public string Top { get; set; }
|
||||
/// <summary>
|
||||
/// Specifies the <c>bottom</c> CSS attribute.
|
||||
/// </summary>
|
||||
/// <value>The bottom.</value>
|
||||
public string Bottom { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the width of the dialog.
|
||||
/// </summary>
|
||||
/// <value>The width.</value>
|
||||
public string Width { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the height of the dialog.
|
||||
/// </summary>
|
||||
/// <value>The height.</value>
|
||||
public string Height { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the CSS style of the dialog
|
||||
/// </summary>
|
||||
/// <value>The style.</value>
|
||||
public string Style { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the child content.
|
||||
/// </summary>
|
||||
/// <value>The child content.</value>
|
||||
public RenderFragment<DialogService> ChildContent { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to focus the first focusable HTML element. Set to <c>true</c> by default.
|
||||
/// </summary>
|
||||
public bool AutoFocusFirstElement { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the dialog should be closed by clicking the overlay.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if closeable; otherwise, <c>false</c>.</value>
|
||||
public bool CloseDialogOnOverlayClick { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the dialog should be closed on ESC key press.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if closeable; otherwise, <c>false</c>.</value>
|
||||
public bool CloseDialogOnEsc { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets dialog box custom class
|
||||
/// </summary>
|
||||
public string CssClass { get; set; }
|
||||
}
|
||||
|
||||
public class ConfirmOptions : DialogOptions
|
||||
/// <summary>
|
||||
/// Class ConfirmOptions.
|
||||
/// </summary>
|
||||
public class AlertOptions : DialogOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the text of the OK button.
|
||||
/// </summary>
|
||||
public string OkButtonText { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Class ConfirmOptions.
|
||||
/// </summary>
|
||||
public class ConfirmOptions : AlertOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the text of the Cancel button.
|
||||
/// </summary>
|
||||
public string CancelButtonText { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Class Dialog.
|
||||
/// </summary>
|
||||
public class Dialog
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the title.
|
||||
/// </summary>
|
||||
/// <value>The title.</value>
|
||||
public string Title { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the type.
|
||||
/// </summary>
|
||||
/// <value>The type.</value>
|
||||
public Type Type { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the parameters.
|
||||
/// </summary>
|
||||
/// <value>The parameters.</value>
|
||||
public Dictionary<string, object> Parameters { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the options.
|
||||
/// </summary>
|
||||
/// <value>The options.</value>
|
||||
public DialogOptions Options { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
35
Radzen.Blazor/Extensions.cs
Normal file
35
Radzen.Blazor/Extensions.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// Class EnumExtensions.
|
||||
/// </summary>
|
||||
public static class EnumExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets enum description.
|
||||
/// </summary>
|
||||
public static string GetDisplayDescription(this Enum enumValue)
|
||||
{
|
||||
var enumValueAsString = enumValue.ToString();
|
||||
var val = enumValue.GetType().GetMember(enumValueAsString).FirstOrDefault();
|
||||
|
||||
return val?.GetCustomAttribute<DisplayAttribute>()?.GetDescription() ?? enumValueAsString;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts Enum to IEnumerable of Value/Text.
|
||||
/// </summary>
|
||||
public static IEnumerable<object> EnumAsKeyValuePair(Type enumType)
|
||||
{
|
||||
return Enum.GetValues(enumType).Cast<Enum>().Distinct().Select(val => new { Value = Convert.ToInt32(val), Text = val.GetDisplayDescription() });
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,28 +5,64 @@ using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Forms;
|
||||
using Microsoft.AspNetCore.Components.Web;
|
||||
using Radzen.Blazor.Rendering;
|
||||
|
||||
namespace Radzen
|
||||
{
|
||||
/// <summary>
|
||||
/// Class FormComponent.
|
||||
/// Implements the <see cref="Radzen.RadzenComponent" />
|
||||
/// Implements the <see cref="Radzen.IRadzenFormComponent" />
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <seealso cref="Radzen.RadzenComponent" />
|
||||
/// <seealso cref="Radzen.IRadzenFormComponent" />
|
||||
public class FormComponent<T> : RadzenComponent, IRadzenFormComponent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the name.
|
||||
/// </summary>
|
||||
/// <value>The name.</value>
|
||||
[Parameter]
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the index of the tab.
|
||||
/// </summary>
|
||||
/// <value>The index of the tab.</value>
|
||||
[Parameter]
|
||||
public int TabIndex { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the placeholder.
|
||||
/// </summary>
|
||||
/// <value>The placeholder.</value>
|
||||
[Parameter]
|
||||
public string Placeholder { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this <see cref="FormComponent{T}"/> is disabled.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if disabled; otherwise, <c>false</c>.</value>
|
||||
[Parameter]
|
||||
public bool Disabled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The form
|
||||
/// </summary>
|
||||
IRadzenForm _form;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the edit context.
|
||||
/// </summary>
|
||||
/// <value>The edit context.</value>
|
||||
[CascadingParameter]
|
||||
public EditContext EditContext { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the form.
|
||||
/// </summary>
|
||||
/// <value>The form.</value>
|
||||
[CascadingParameter]
|
||||
public IRadzenForm Form
|
||||
{
|
||||
@@ -36,17 +72,22 @@ namespace Radzen
|
||||
}
|
||||
set
|
||||
{
|
||||
if (_form != value && value != null)
|
||||
{
|
||||
_form = value;
|
||||
_form.AddComponent(this);
|
||||
}
|
||||
_form = value;
|
||||
_form?.AddComponent(this);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the value changed.
|
||||
/// </summary>
|
||||
/// <value>The value changed.</value>
|
||||
[Parameter]
|
||||
public EventCallback<T> ValueChanged { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this instance has value.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance has value; otherwise, <c>false</c>.</value>
|
||||
public virtual bool HasValue
|
||||
{
|
||||
get
|
||||
@@ -59,6 +100,10 @@ namespace Radzen
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this instance is bound.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance is bound; otherwise, <c>false</c>.</value>
|
||||
public bool IsBound
|
||||
{
|
||||
get
|
||||
@@ -67,8 +112,15 @@ namespace Radzen
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The value
|
||||
/// </summary>
|
||||
protected T _value;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the value.
|
||||
/// </summary>
|
||||
/// <value>The value.</value>
|
||||
[Parameter]
|
||||
public virtual T Value
|
||||
{
|
||||
@@ -86,11 +138,28 @@ namespace Radzen
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the change.
|
||||
/// </summary>
|
||||
/// <value>The change.</value>
|
||||
[Parameter]
|
||||
public EventCallback<T> Change { get; set; }
|
||||
/// <summary>
|
||||
/// Gets the field identifier.
|
||||
/// </summary>
|
||||
/// <value>The field identifier.</value>
|
||||
public FieldIdentifier FieldIdentifier { get; private set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the value expression.
|
||||
/// </summary>
|
||||
/// <value>The value expression.</value>
|
||||
[Parameter]
|
||||
public Expression<Func<T>> ValueExpression { get; set; }
|
||||
/// <summary>
|
||||
/// Sets the parameters asynchronous.
|
||||
/// </summary>
|
||||
/// <param name="parameters">The parameters.</param>
|
||||
/// <returns>Task.</returns>
|
||||
public override Task SetParametersAsync(ParameterView parameters)
|
||||
{
|
||||
var result = base.SetParametersAsync(parameters);
|
||||
@@ -98,17 +167,26 @@ namespace Radzen
|
||||
if (EditContext != null && ValueExpression != null && FieldIdentifier.Model != EditContext.Model)
|
||||
{
|
||||
FieldIdentifier = FieldIdentifier.Create(ValueExpression);
|
||||
EditContext.OnValidationStateChanged -= ValidationStateChanged;
|
||||
EditContext.OnValidationStateChanged += ValidationStateChanged;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validations the state changed.
|
||||
/// </summary>
|
||||
/// <param name="sender">The sender.</param>
|
||||
/// <param name="e">The <see cref="ValidationStateChangedEventArgs"/> instance containing the event data.</param>
|
||||
private void ValidationStateChanged(object sender, ValidationStateChangedEventArgs e)
|
||||
{
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disposes this instance.
|
||||
/// </summary>
|
||||
public override void Dispose()
|
||||
{
|
||||
base.Dispose();
|
||||
@@ -121,11 +199,20 @@ namespace Radzen
|
||||
Form?.RemoveComponent(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value.
|
||||
/// </summary>
|
||||
/// <returns>System.Object.</returns>
|
||||
public object GetValue()
|
||||
{
|
||||
return Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the <see cref="E:ContextMenu" /> event.
|
||||
/// </summary>
|
||||
/// <param name="args">The <see cref="MouseEventArgs"/> instance containing the event data.</param>
|
||||
/// <returns>Task.</returns>
|
||||
public override Task OnContextMenu(MouseEventArgs args)
|
||||
{
|
||||
if (!Disabled)
|
||||
@@ -135,5 +222,14 @@ namespace Radzen
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the class list.
|
||||
/// </summary>
|
||||
/// <param name="className">Name of the class.</param>
|
||||
/// <returns>ClassList.</returns>
|
||||
protected ClassList GetClassList(string className) => ClassList.Create(className)
|
||||
.AddDisabled(Disabled)
|
||||
.Add(FieldIdentifier, EditContext);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,21 +6,49 @@ using Radzen.Blazor.Rendering;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// Class GaugeBase.
|
||||
/// Implements the <see cref="Radzen.RadzenComponent" />
|
||||
/// </summary>
|
||||
/// <seealso cref="Radzen.RadzenComponent" />
|
||||
public abstract class GaugeBase : RadzenComponent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the child content.
|
||||
/// </summary>
|
||||
/// <value>The child content.</value>
|
||||
[Parameter]
|
||||
public RenderFragment ChildContent
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the width.
|
||||
/// </summary>
|
||||
/// <value>The width.</value>
|
||||
public double? Width { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the height.
|
||||
/// </summary>
|
||||
/// <value>The height.</value>
|
||||
public double? Height { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The width and height are set
|
||||
/// </summary>
|
||||
bool widthAndHeightAreSet = false;
|
||||
/// <summary>
|
||||
/// The first render
|
||||
/// </summary>
|
||||
bool firstRender = true;
|
||||
|
||||
/// <summary>
|
||||
/// On after render as an asynchronous operation.
|
||||
/// </summary>
|
||||
/// <param name="firstRender">if set to <c>true</c> [first render].</param>
|
||||
/// <returns>A Task representing the asynchronous operation.</returns>
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
this.firstRender = firstRender;
|
||||
@@ -43,6 +71,9 @@ namespace Radzen.Blazor
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when [initialized].
|
||||
/// </summary>
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
base.OnInitialized();
|
||||
@@ -50,6 +81,11 @@ namespace Radzen.Blazor
|
||||
Initialize();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resizes the specified width.
|
||||
/// </summary>
|
||||
/// <param name="width">The width.</param>
|
||||
/// <param name="height">The height.</param>
|
||||
[JSInvokable]
|
||||
public void Resize(double width, double height)
|
||||
{
|
||||
@@ -73,6 +109,9 @@ namespace Radzen.Blazor
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes this instance.
|
||||
/// </summary>
|
||||
private void Initialize()
|
||||
{
|
||||
double width = 0;
|
||||
@@ -107,8 +146,16 @@ namespace Radzen.Blazor
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The visible changed
|
||||
/// </summary>
|
||||
private bool visibleChanged = false;
|
||||
|
||||
/// <summary>
|
||||
/// Set parameters as an asynchronous operation.
|
||||
/// </summary>
|
||||
/// <param name="parameters">The parameters.</param>
|
||||
/// <returns>A Task representing the asynchronous operation.</returns>
|
||||
public override async Task SetParametersAsync(ParameterView parameters)
|
||||
{
|
||||
bool shouldRefresh = parameters.DidParameterChange(nameof(Style), Style);
|
||||
@@ -131,6 +178,9 @@ namespace Radzen.Blazor
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disposes this instance.
|
||||
/// </summary>
|
||||
public override void Dispose()
|
||||
{
|
||||
base.Dispose();
|
||||
@@ -141,6 +191,9 @@ namespace Radzen.Blazor
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reloads this instance.
|
||||
/// </summary>
|
||||
public void Reload()
|
||||
{
|
||||
StateHasChanged();
|
||||
|
||||
@@ -1,9 +1,21 @@
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// Enum GaugeTickPosition
|
||||
/// </summary>
|
||||
public enum GaugeTickPosition
|
||||
{
|
||||
/// <summary>
|
||||
/// The inside
|
||||
/// </summary>
|
||||
Inside,
|
||||
/// <summary>
|
||||
/// The outside
|
||||
/// </summary>
|
||||
Outside,
|
||||
/// <summary>
|
||||
/// The none
|
||||
/// </summary>
|
||||
None
|
||||
}
|
||||
}
|
||||
@@ -7,8 +7,21 @@ using System.Xml.Linq;
|
||||
|
||||
namespace Radzen
|
||||
{
|
||||
/// <summary>
|
||||
/// Class HttpResponseMessageExtensions.
|
||||
/// </summary>
|
||||
public static class HttpResponseMessageExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Read as an asynchronous operation.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="response">The response.</param>
|
||||
/// <returns>A Task<T> representing the asynchronous operation.</returns>
|
||||
/// <exception cref="Exception">Unable to parse the response.</exception>
|
||||
/// <exception cref="Exception"></exception>
|
||||
/// <exception cref="Exception">Unable to parse the response.</exception>
|
||||
/// <exception cref="Exception"></exception>
|
||||
public static async Task<T> ReadAsync<T>(this HttpResponseMessage response)
|
||||
{
|
||||
try
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// Common axis API of <see cref="RadzenChart" />
|
||||
/// </summary>
|
||||
public interface IChartAxis
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the grid lines configuration of this axis.
|
||||
/// </summary>
|
||||
RadzenGridLines GridLines { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,14 @@
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// Marker interface for <see cref="RadzenBarSeries{TItem}" />.
|
||||
/// </summary>
|
||||
public interface IChartBarSeries
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the count.
|
||||
/// </summary>
|
||||
/// <value>The count.</value>
|
||||
int Count { get; }
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,14 @@
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// Marker interface for <see cref="RadzenColumnSeries{TItem}" />.
|
||||
/// </summary>
|
||||
public interface IChartColumnSeries
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the count.
|
||||
/// </summary>
|
||||
/// <value>The count.</value>
|
||||
int Count { get; }
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,17 @@ using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// Marker interface for <see cref="RadzenColumnSeries{TItem}" />.
|
||||
/// </summary>
|
||||
public interface IChartDonutSeries
|
||||
{
|
||||
RenderFragment RenderTitle(double x, double y);
|
||||
/// <summary>
|
||||
/// Renders the title.
|
||||
/// </summary>
|
||||
/// <param name="x">The x.</param>
|
||||
/// <param name="y">The y.</param>
|
||||
/// <returns>RenderFragment.</returns>
|
||||
RenderFragment RenderTitle(double x, double y);
|
||||
}
|
||||
}
|
||||
@@ -1,24 +1,149 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Radzen.Blazor.Rendering;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies the common API that <see cref="RadzenChart" /> series must implement.
|
||||
/// </summary>
|
||||
public interface IChartSeries
|
||||
{
|
||||
/// <summary>
|
||||
/// Transforms a category scale to new one.
|
||||
/// </summary>
|
||||
/// <param name="scale">The scale.</param>
|
||||
ScaleBase TransformCategoryScale(ScaleBase scale);
|
||||
/// <summary>
|
||||
/// Transforms a category scale to new one.
|
||||
/// </summary>
|
||||
/// <param name="scale">The scale.</param>
|
||||
ScaleBase TransformValueScale(ScaleBase scale);
|
||||
/// <summary>
|
||||
/// Gets or sets the series marker configuration.
|
||||
/// </summary>
|
||||
RadzenMarkers Markers { get; set; }
|
||||
/// <summary>
|
||||
/// Gets the series marker type.
|
||||
/// </summary>
|
||||
/// <value>The type of the marker.</value>
|
||||
MarkerType MarkerType { get; }
|
||||
/// <summary>
|
||||
/// Gets the size of the marker.
|
||||
/// </summary>
|
||||
/// <value>The size of the marker.</value>
|
||||
double MarkerSize { get; }
|
||||
/// <summary>
|
||||
/// Renders the series with the specified category and value scales.
|
||||
/// </summary>
|
||||
/// <param name="categoryScale">The category scale.</param>
|
||||
/// <param name="valueScale">The value scale.</param>
|
||||
/// <returns>RenderFragment.</returns>
|
||||
RenderFragment Render(ScaleBase categoryScale, ScaleBase valueScale);
|
||||
/// <summary>
|
||||
/// Renders the series overlays with the specified category and value scales.
|
||||
/// </summary>
|
||||
/// <param name="categoryScale">The category scale.</param>
|
||||
/// <param name="valueScale">The value scale.</param>
|
||||
/// <returns>RenderFragment.</returns>
|
||||
RenderFragment RenderOverlays(ScaleBase categoryScale, ScaleBase valueScale);
|
||||
/// <summary>
|
||||
/// Renders the series tooltip.
|
||||
/// </summary>
|
||||
/// <param name="data">The data.</param>
|
||||
/// <param name="marginLeft">The left margin.</param>
|
||||
/// <param name="marginTop">The right margin.</param>
|
||||
/// <returns>RenderFragment.</returns>
|
||||
RenderFragment RenderTooltip(object data, double marginLeft, double marginTop);
|
||||
/// <summary>
|
||||
/// Renders the legend item.
|
||||
/// </summary>
|
||||
/// <returns>RenderFragment.</returns>
|
||||
RenderFragment RenderLegendItem();
|
||||
/// <summary>
|
||||
/// Gets the color.
|
||||
/// </summary>
|
||||
/// <value>The color.</value>
|
||||
string Color { get; }
|
||||
bool Visible { get; set; }
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this <see cref="IChartSeries"/> is visible.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if visible; otherwise, <c>false</c>.</value>
|
||||
bool Visible { get; }
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this series should appear in the legend.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if the series appears in the legend; otherwise, <c>false</c>.</value>
|
||||
bool ShowInLegend { get; }
|
||||
/// <summary>
|
||||
/// Gets or sets the rendering order.
|
||||
/// </summary>
|
||||
/// <value>The rendering order.</value>
|
||||
int RenderingOrder { get; set; }
|
||||
bool Contains(double x, double y);
|
||||
/// <summary>
|
||||
/// Determines if the series contains the specified coordinates with a given tolerance.
|
||||
/// </summary>
|
||||
/// <param name="x">The x.</param>
|
||||
/// <param name="y">The y.</param>
|
||||
/// <param name="tolerance">The tolerance.</param>
|
||||
/// <returns><c>true</c> if the series contains the coordinates; otherwise, <c>false</c>.</returns>
|
||||
bool Contains(double x, double y, double tolerance);
|
||||
/// <summary>
|
||||
/// Returns the data at the specified coordinates;
|
||||
/// </summary>
|
||||
/// <param name="x">The x.</param>
|
||||
/// <param name="y">The y.</param>
|
||||
object DataAt(double x, double y);
|
||||
/// <summary>
|
||||
/// Returns data chart position
|
||||
/// </summary>
|
||||
IEnumerable<ChartDataLabel> GetDataLabels(double offsetX, double offsetY);
|
||||
/// <summary>
|
||||
/// Returns series median
|
||||
/// </summary>
|
||||
double GetMedian();
|
||||
/// <summary>
|
||||
/// Returns series mean
|
||||
/// </summary>
|
||||
double GetMean();
|
||||
/// <summary>
|
||||
/// Returns series mode
|
||||
/// </summary>
|
||||
double GetMode();
|
||||
/// <summary>
|
||||
/// Returns series trend
|
||||
/// </summary>
|
||||
(double a, double b) GetTrend();
|
||||
/// <summary>
|
||||
/// Series coordinate system
|
||||
/// </summary>
|
||||
CoordinateSystem CoordinateSystem { get; }
|
||||
/// <summary>
|
||||
/// Series overlays
|
||||
/// </summary>
|
||||
IList<IChartSeriesOverlay> Overlays{ get; }
|
||||
/// <summary>
|
||||
/// Gets or sets the title of the series. The title is displayed in tooltips and the legend.
|
||||
/// </summary>
|
||||
/// <value>The title.</value>
|
||||
string Title { get; set; }
|
||||
/// <summary>
|
||||
/// Gets the title.
|
||||
/// </summary>
|
||||
string GetTitle();
|
||||
/// <summary>
|
||||
/// Measures the legend.
|
||||
/// </summary>
|
||||
/// <returns>System.Double.</returns>
|
||||
double MeasureLegend();
|
||||
/// <summary>
|
||||
/// Invokes the click handler with the provided data item.
|
||||
/// </summary>
|
||||
/// <param name="handler">The handler.</param>
|
||||
/// <param name="data">The data.</param>
|
||||
Task InvokeClick(EventCallback<SeriesClickEventArgs> handler, object data);
|
||||
}
|
||||
}
|
||||
|
||||
33
Radzen.Blazor/IChartSeriesOverlay.cs
Normal file
33
Radzen.Blazor/IChartSeriesOverlay.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface for chart overlays
|
||||
/// </summary>
|
||||
public interface IChartSeriesOverlay
|
||||
{
|
||||
/// <summary>
|
||||
/// Render overlay
|
||||
/// </summary>
|
||||
/// <param name="categoryScale"></param>
|
||||
/// <param name="valueScale"></param>
|
||||
/// <returns>RenderFragment</returns>
|
||||
RenderFragment Render(ScaleBase categoryScale, ScaleBase valueScale);
|
||||
|
||||
/// <summary>
|
||||
/// Gets overlay visibility state
|
||||
/// </summary>
|
||||
bool Visible { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Hit test
|
||||
/// </summary>
|
||||
bool Contains(double mouseX, double mouseY, int tolerance);
|
||||
|
||||
/// <summary>
|
||||
/// Renders tooltip
|
||||
/// </summary>
|
||||
RenderFragment RenderTooltip(double mouseX, double mouseY, double marginLeft, double marginTop);
|
||||
}
|
||||
}
|
||||
@@ -1,23 +1,95 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// The common <see cref="RadzenScheduler{TItem}" /> API injected as a cascading parameter to is views.
|
||||
/// </summary>
|
||||
public interface IScheduler
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the appointments in the specified range.
|
||||
/// </summary>
|
||||
/// <param name="start">The start of the range.</param>
|
||||
/// <param name="end">The end of the range.</param>
|
||||
/// <returns>A collection of appointments within the specified range.</returns>
|
||||
IEnumerable<AppointmentData> GetAppointmentsInRange(DateTime start, DateTime end);
|
||||
/// <summary>
|
||||
/// Determines whether an appointment is within the specified range.
|
||||
/// </summary>
|
||||
/// <param name="item">The appointment to check.</param>
|
||||
/// <param name="start">The start of the range.</param>
|
||||
/// <param name="end">The end of the range.</param>
|
||||
/// <returns><c>true</c> if the appointment is within the specified range; otherwise, <c>false</c>.</returns>
|
||||
bool IsAppointmentInRange(AppointmentData item, DateTime start, DateTime end);
|
||||
/// <summary>
|
||||
/// Adds a view. Must be called when a <see cref="ISchedulerView" /> is initialized.
|
||||
/// </summary>
|
||||
/// <param name="view">The view to add.</param>
|
||||
Task AddView(ISchedulerView view);
|
||||
/// <summary>
|
||||
/// Removes a view. Must be called when a <see cref="ISchedulerView" /> is disposed.
|
||||
/// </summary>
|
||||
/// <param name="view">The view to remove.</param>
|
||||
void RemoveView(ISchedulerView view);
|
||||
/// <summary>
|
||||
/// Determines whether the specified view is selected.
|
||||
/// </summary>
|
||||
/// <param name="view">The view.</param>
|
||||
/// <returns><c>true</c> if the specified view is selected; otherwise, <c>false</c>.</returns>
|
||||
bool IsSelected(ISchedulerView view);
|
||||
/// <summary>
|
||||
/// Gets or sets the current date.
|
||||
/// </summary>
|
||||
/// <value>The current date.</value>
|
||||
DateTime CurrentDate { get; set; }
|
||||
/// <summary>
|
||||
/// Selects the specified appointment.
|
||||
/// </summary>
|
||||
/// <param name="data">The appointment to select.</param>
|
||||
Task SelectAppointment(AppointmentData data);
|
||||
/// <summary>
|
||||
/// Selects the specified slot.
|
||||
/// </summary>
|
||||
/// <param name="start">The start.</param>
|
||||
/// <param name="end">The end.</param>
|
||||
Task SelectSlot(DateTime start, DateTime end);
|
||||
/// <summary>
|
||||
/// Gets the appointment HTML attributes.
|
||||
/// </summary>
|
||||
/// <param name="item">The appointment.</param>
|
||||
/// <returns>A dictionary containing the HTML attributes for the specified appointment.</returns>
|
||||
IDictionary<string, object> GetAppointmentAttributes(AppointmentData item);
|
||||
/// <summary>
|
||||
/// Gets the slot HTML attributes.
|
||||
/// </summary>
|
||||
/// <param name="start">The start of the slot.</param>
|
||||
/// <param name="end">The end of the slot.</param>
|
||||
/// <returns>A dictionary containing the HTML attributes for the specified slot.</returns>
|
||||
IDictionary<string, object> GetSlotAttributes(DateTime start, DateTime end);
|
||||
/// <summary>
|
||||
/// Renders the appointment.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <returns>RenderFragment.</returns>
|
||||
RenderFragment RenderAppointment(AppointmentData item);
|
||||
/// <summary>
|
||||
/// Reloads this instance.
|
||||
/// </summary>
|
||||
Task Reload();
|
||||
/// <summary>
|
||||
/// Gets the height.
|
||||
/// </summary>
|
||||
/// <value>The height.</value>
|
||||
double Height { get; }
|
||||
/// <summary>
|
||||
/// Gets or sets the culture.
|
||||
/// </summary>
|
||||
/// <value>The culture.</value>
|
||||
CultureInfo Culture { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -3,18 +3,51 @@ using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface that has to be implemented by a view in order to by supported by <see cref="RadzenScheduler{TItem}" />.
|
||||
/// </summary>
|
||||
public interface ISchedulerView
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the icon of the view. It is displayed in the view switching UI.
|
||||
/// </summary>
|
||||
string Icon { get; }
|
||||
/// <summary>
|
||||
/// Gets the title of the view. It is displayed in the RadzenScheduler title area.
|
||||
/// </summary>
|
||||
/// <value>The title.</value>
|
||||
string Title { get; }
|
||||
/// <summary>
|
||||
/// Gets the text of the view. It is displayed in the view switching UI.
|
||||
/// </summary>
|
||||
/// <value>The text.</value>
|
||||
string Text { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new date when the user clicks the next button of RadzenScheduler.
|
||||
/// </summary>
|
||||
/// <returns>The next date. For example a day view will return the next day, a week view will return the next week.</returns>
|
||||
DateTime Next();
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new date when the user clicks the previous button of RadzenScheduler.
|
||||
/// </summary>
|
||||
/// <returns>The previous date. For example a day view will return the previous day, a week view will return the previous week.</returns>
|
||||
DateTime Prev();
|
||||
|
||||
/// <summary>
|
||||
/// Renders this instance.
|
||||
/// </summary>
|
||||
/// <returns>RenderFragment.</returns>
|
||||
RenderFragment Render();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the start date.
|
||||
/// </summary>
|
||||
DateTime StartDate { get; }
|
||||
/// <summary>
|
||||
/// Gets the end date.
|
||||
/// </summary>
|
||||
DateTime EndDate { get; }
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2018-2021 Radzen Ltd
|
||||
Copyright (c) 2018-2022 Radzen Ltd
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -1,10 +1,25 @@
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies the legend position in a <see cref="RadzenChart" />.
|
||||
/// </summary>
|
||||
public enum LegendPosition
|
||||
{
|
||||
/// <summary>
|
||||
/// The legend is at the right side of the series.
|
||||
/// </summary>
|
||||
Right,
|
||||
/// <summary>
|
||||
/// The legend is at the left side of the series.
|
||||
/// </summary>
|
||||
Left,
|
||||
/// <summary>
|
||||
/// The legend is above the series.
|
||||
/// </summary>
|
||||
Top,
|
||||
/// <summary>
|
||||
/// The legend is below the series.
|
||||
/// </summary>
|
||||
Bottom
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,21 @@
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// Specified the line drawing style.
|
||||
/// </summary>
|
||||
public enum LineType
|
||||
{
|
||||
/// <summary>
|
||||
/// Solid lines.
|
||||
/// </summary>
|
||||
Solid,
|
||||
/// <summary>
|
||||
/// Dashed lines.
|
||||
/// </summary>
|
||||
Dashed,
|
||||
/// <summary>
|
||||
/// Dotted lines.
|
||||
/// </summary>
|
||||
Dotted
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,7 +65,13 @@ namespace Radzen.Blazor
|
||||
if (start == end)
|
||||
{
|
||||
start = 0;
|
||||
end = end + NiceNumber(end/ticks, false);
|
||||
end += NiceNumber(end / ticks, false);
|
||||
}
|
||||
|
||||
if (Round && end < 0)
|
||||
{
|
||||
end = 0;
|
||||
start += NiceNumber(start / ticks, false);
|
||||
}
|
||||
|
||||
var range = end - start;
|
||||
|
||||
@@ -1,12 +1,33 @@
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies the type of marker that <see cref="RadzenChart" /> displays for data points.
|
||||
/// </summary>
|
||||
public enum MarkerType
|
||||
{
|
||||
/// <summary>
|
||||
/// Do not display a marker for data points.
|
||||
/// </summary>
|
||||
None,
|
||||
/// <summary>
|
||||
/// Cycle between markers.
|
||||
/// </summary>
|
||||
Auto,
|
||||
/// <summary>
|
||||
/// Use a circle marker.
|
||||
/// </summary>
|
||||
Circle,
|
||||
/// <summary>
|
||||
/// Use a triangle marker.
|
||||
/// </summary>
|
||||
Triangle,
|
||||
/// <summary>
|
||||
/// Use a square marker.
|
||||
/// </summary>
|
||||
Square,
|
||||
/// <summary>
|
||||
/// Use a diamond marker.
|
||||
/// </summary>
|
||||
Diamond
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,34 @@
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Radzen.Blazor;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Text;
|
||||
|
||||
namespace Radzen
|
||||
{
|
||||
/// <summary>
|
||||
/// Class NotificationService. Contains various methods with options to open notifications.
|
||||
/// Should be added as scoped service in the application services and RadzenNotification should be added in application main layout.
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// @inject NotificationService NotificationService
|
||||
/// <RadzenButton Text="Show info notification" Click=@(args => NotificationService.Notify(new NotificationMessage { Severity = NotificationSeverity.Info, Summary = "Info Summary", Detail = "Info Detail", Duration = 4000 })) / >
|
||||
/// </code>
|
||||
/// </example>
|
||||
public class NotificationService
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the messages.
|
||||
/// </summary>
|
||||
/// <value>The messages.</value>
|
||||
public ObservableCollection<NotificationMessage> Messages { get; private set; } = new ObservableCollection<NotificationMessage>();
|
||||
|
||||
/// <summary>
|
||||
/// Notifies the specified message.
|
||||
/// </summary>
|
||||
/// <param name="message">The message.</param>
|
||||
public void Notify(NotificationMessage message)
|
||||
{
|
||||
var newMessage = new NotificationMessage()
|
||||
@@ -17,7 +37,10 @@ namespace Radzen
|
||||
Severity = message.Severity,
|
||||
Summary = message.Summary,
|
||||
Detail = message.Detail,
|
||||
Style = message.Style
|
||||
Style = message.Style,
|
||||
Click = message.Click,
|
||||
CloseOnClick = message.CloseOnClick,
|
||||
Payload = message.Payload
|
||||
};
|
||||
|
||||
if (!Messages.Contains(newMessage))
|
||||
@@ -26,14 +49,27 @@ namespace Radzen
|
||||
}
|
||||
}
|
||||
|
||||
public void Notify(NotificationSeverity severity = NotificationSeverity.Info, string summary = "", string detail = "", double duration = 3000)
|
||||
/// <summary>
|
||||
/// Notifies the specified severity.
|
||||
/// </summary>
|
||||
/// <param name="severity">The severity.</param>
|
||||
/// <param name="summary">The summary.</param>
|
||||
/// <param name="detail">The detail.</param>
|
||||
/// <param name="duration">The duration.</param>
|
||||
/// <param name="click">The click event.</param>
|
||||
/// <param name="closeOnClick">If true, then the notification will be closed when clicked on.</param>
|
||||
/// <param name="payload">Used to store a custom payload that can be retreived later in the click event handler.</param>
|
||||
public void Notify(NotificationSeverity severity = NotificationSeverity.Info, string summary = "", string detail = "", double duration = 3000, Action<NotificationMessage> click = null, bool closeOnClick = false, object payload = null)
|
||||
{
|
||||
var newMessage = new NotificationMessage()
|
||||
{
|
||||
Duration = duration,
|
||||
Severity = severity,
|
||||
Summary = summary,
|
||||
Detail = detail
|
||||
Detail = detail,
|
||||
Click = click,
|
||||
CloseOnClick = closeOnClick,
|
||||
Payload = payload
|
||||
};
|
||||
|
||||
if (!Messages.Contains(newMessage))
|
||||
@@ -43,12 +79,50 @@ namespace Radzen
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Class NotificationMessage.
|
||||
/// </summary>
|
||||
public class NotificationMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the duration.
|
||||
/// </summary>
|
||||
/// <value>The duration.</value>
|
||||
public double? Duration { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the severity.
|
||||
/// </summary>
|
||||
/// <value>The severity.</value>
|
||||
public NotificationSeverity Severity { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the summary.
|
||||
/// </summary>
|
||||
/// <value>The summary.</value>
|
||||
public string Summary { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the detail.
|
||||
/// </summary>
|
||||
/// <value>The detail.</value>
|
||||
public string Detail { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the style.
|
||||
/// </summary>
|
||||
/// <value>The style.</value>
|
||||
public string Style { get; set; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets or sets the click event.
|
||||
/// </summary>
|
||||
/// <value>This event handler is called when the notification is clicked on.</value>
|
||||
public Action<NotificationMessage> Click { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets click on close action.
|
||||
/// </summary>
|
||||
/// <value>If true, then the notification will be closed when clicked on.</value>
|
||||
public bool CloseOnClick { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets notification payload.
|
||||
/// </summary>
|
||||
/// <value>Used to store a custom payload that can be retreived later in the click event handler.</value>
|
||||
public object Payload { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,35 +8,76 @@ using System.Web;
|
||||
|
||||
namespace Radzen
|
||||
{
|
||||
/// <summary>
|
||||
/// Class ODataEnumerable.
|
||||
/// Implements the <see cref="IEnumerable{T}" />
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <seealso cref="IEnumerable{T}" />
|
||||
public class ODataEnumerable<T> : IEnumerable<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// The source
|
||||
/// </summary>
|
||||
IEnumerable<T> source;
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ODataEnumerable{T}"/> class.
|
||||
/// </summary>
|
||||
/// <param name="source">The source.</param>
|
||||
public ODataEnumerable(IEnumerable<T> source)
|
||||
{
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the enumerator.
|
||||
/// </summary>
|
||||
/// <returns>IEnumerator<T>.</returns>
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
return source.GetEnumerator();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the enumerator.
|
||||
/// </summary>
|
||||
/// <returns>IEnumerator.</returns>
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return source.GetEnumerator();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Class ODataServiceResult.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public class ODataServiceResult<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the count.
|
||||
/// </summary>
|
||||
/// <value>The count.</value>
|
||||
[JsonPropertyName("@odata.count")]
|
||||
public int Count { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the value.
|
||||
/// </summary>
|
||||
/// <value>The value.</value>
|
||||
public IEnumerable<T> Value { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Class ODataJsonSerializer.
|
||||
/// </summary>
|
||||
public static class ODataJsonSerializer
|
||||
{
|
||||
/// <summary>
|
||||
/// Determines whether the specified type is complex.
|
||||
/// </summary>
|
||||
/// <param name="type">The type.</param>
|
||||
/// <returns><c>true</c> if the specified type is complex; otherwise, <c>false</c>.</returns>
|
||||
static bool IsComplex(Type type)
|
||||
{
|
||||
var underlyingType = type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>) ? Nullable.GetUnderlyingType(type) : type;
|
||||
@@ -47,11 +88,23 @@ namespace Radzen
|
||||
type != typeof(string) && type != typeof(decimal) && type.IsClass;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the specified type is enumerable.
|
||||
/// </summary>
|
||||
/// <param name="type">The type.</param>
|
||||
/// <returns><c>true</c> if the specified type is enumerable; otherwise, <c>false</c>.</returns>
|
||||
static bool IsEnumerable(Type type)
|
||||
{
|
||||
return !typeof(string).IsAssignableFrom(type) && (typeof(IEnumerable<>).IsAssignableFrom(type) || typeof(IEnumerable).IsAssignableFrom(type));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Serializes the specified value.
|
||||
/// </summary>
|
||||
/// <typeparam name="TValue">The type of the t value.</typeparam>
|
||||
/// <param name="value">The value.</param>
|
||||
/// <param name="options">The options.</param>
|
||||
/// <returns>System.String.</returns>
|
||||
public static string Serialize<TValue>(TValue value, JsonSerializerOptions options = null)
|
||||
{
|
||||
if (options == null)
|
||||
@@ -70,19 +123,45 @@ namespace Radzen
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Class ComplexPropertiesConverter.
|
||||
/// Implements the <see cref="JsonConverter{T}" />
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <seealso cref="JsonConverter{T}" />
|
||||
public class ComplexPropertiesConverter<T> : JsonConverter<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// The complex properties
|
||||
/// </summary>
|
||||
IEnumerable<string> complexProperties;
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ComplexPropertiesConverter{T}"/> class.
|
||||
/// </summary>
|
||||
/// <param name="complexProperties">The complex properties.</param>
|
||||
public ComplexPropertiesConverter(IEnumerable<string> complexProperties)
|
||||
{
|
||||
this.complexProperties = complexProperties;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the specified reader.
|
||||
/// </summary>
|
||||
/// <param name="reader">The reader.</param>
|
||||
/// <param name="typeToConvert">The type to convert.</param>
|
||||
/// <param name="options">The options.</param>
|
||||
/// <returns>T.</returns>
|
||||
public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
return JsonSerializer.Deserialize<T>(ref reader, options);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the specified writer.
|
||||
/// </summary>
|
||||
/// <param name="writer">The writer.</param>
|
||||
/// <param name="value">The value.</param>
|
||||
/// <param name="options">The options.</param>
|
||||
public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options)
|
||||
{
|
||||
writer.WriteStartObject();
|
||||
@@ -105,21 +184,54 @@ namespace Radzen
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Class DateTimeConverterUsingDateTimeParse.
|
||||
/// Implements the <see cref="JsonConverter{DateTime}" />
|
||||
/// </summary>
|
||||
/// <seealso cref="JsonConverter{DateTime}" />
|
||||
public class DateTimeConverterUsingDateTimeParse : JsonConverter<DateTime>
|
||||
{
|
||||
/// <summary>
|
||||
/// Reads the specified reader.
|
||||
/// </summary>
|
||||
/// <param name="reader">The reader.</param>
|
||||
/// <param name="typeToConvert">The type to convert.</param>
|
||||
/// <param name="options">The options.</param>
|
||||
/// <returns>DateTime.</returns>
|
||||
public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
return DateTime.Parse(reader.GetString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the specified writer.
|
||||
/// </summary>
|
||||
/// <param name="writer">The writer.</param>
|
||||
/// <param name="value">The value.</param>
|
||||
/// <param name="options">The options.</param>
|
||||
public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
|
||||
{
|
||||
writer.WriteStringValue(value.ToString("yyyy-MM-ddTHH:mm:ss.fffZ"));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Class ODataExtensions.
|
||||
/// </summary>
|
||||
public static class ODataExtensions
|
||||
{
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the o data URI.
|
||||
/// </summary>
|
||||
/// <param name="uri">The URI.</param>
|
||||
/// <param name="filter">The filter.</param>
|
||||
/// <param name="top">The top.</param>
|
||||
/// <param name="skip">The skip.</param>
|
||||
/// <param name="orderby">The orderby.</param>
|
||||
/// <param name="expand">The expand.</param>
|
||||
/// <param name="select">The select.</param>
|
||||
/// <param name="count">if set to <c>true</c> [count].</param>
|
||||
/// <returns>Uri.</returns>
|
||||
public static Uri GetODataUri(this Uri uri, string filter = null, int? top = null, int? skip = null, string orderby = null, string expand = null, string select = null, bool? count = null)
|
||||
{
|
||||
var uriBuilder = new UriBuilder(uri);
|
||||
|
||||
@@ -8,29 +8,93 @@ using Radzen.Blazor;
|
||||
|
||||
namespace Radzen
|
||||
{
|
||||
/// <summary>
|
||||
/// Base classes of components that support paging.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the data item</typeparam>
|
||||
public class PagedDataBoundComponent<T> : RadzenComponent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the pager position. Set to <c>PagerPosition.Bottom</c> by default.
|
||||
/// </summary>
|
||||
/// <value>The pager position.</value>
|
||||
[Parameter]
|
||||
public PagerPosition PagerPosition { get; set; } = PagerPosition.Bottom;
|
||||
|
||||
/// <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 PagerAlwaysVisible { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the horizontal align.
|
||||
/// </summary>
|
||||
/// <value>The horizontal align.</value>
|
||||
[Parameter]
|
||||
public HorizontalAlign PagerHorizontalAlign { get; set; } = HorizontalAlign.Justify;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether paging is allowed. Set to <c>false</c> by default.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if paging is allowed; otherwise, <c>false</c>.</value>
|
||||
[Parameter]
|
||||
public bool AllowPaging { get; set; }
|
||||
|
||||
int _PageSize = 10;
|
||||
/// <summary>
|
||||
/// Gets or sets the size of the page.
|
||||
/// </summary>
|
||||
/// <value>The size of the page.</value>
|
||||
[Parameter]
|
||||
public int PageSize { get; set; } = 10;
|
||||
public int PageSize
|
||||
{
|
||||
get
|
||||
{
|
||||
return pageSize ?? _PageSize;
|
||||
}
|
||||
set
|
||||
{
|
||||
_PageSize = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the page numbers count.
|
||||
/// </summary>
|
||||
/// <value>The page numbers count.</value>
|
||||
[Parameter]
|
||||
public int PageNumbersCount { get; set; } = 5;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the count.
|
||||
/// </summary>
|
||||
/// <value>The count.</value>
|
||||
[Parameter]
|
||||
public int Count { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the current page.
|
||||
/// </summary>
|
||||
/// <value>The current page.</value>
|
||||
public int CurrentPage { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the template.
|
||||
/// </summary>
|
||||
/// <value>The template.</value>
|
||||
[Parameter]
|
||||
public RenderFragment<T> Template { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The data
|
||||
/// </summary>
|
||||
IEnumerable<T> _data;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the data.
|
||||
/// </summary>
|
||||
/// <value>The data.</value>
|
||||
[Parameter]
|
||||
public IEnumerable<T> Data
|
||||
{
|
||||
@@ -49,19 +113,55 @@ namespace Radzen
|
||||
}
|
||||
}
|
||||
|
||||
protected IQueryable<T> _view = null;
|
||||
/// <summary>
|
||||
/// Gets or sets the page size options.
|
||||
/// </summary>
|
||||
/// <value>The page size options.</value>
|
||||
[Parameter]
|
||||
public IEnumerable<int> PageSizeOptions { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the page size description text.
|
||||
/// </summary>
|
||||
/// <value>The page size description text.</value>
|
||||
[Parameter]
|
||||
public string PageSizeText { get; set; } = "items per page";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the pager summary visibility.
|
||||
/// </summary>
|
||||
/// <value>The pager summary visibility.</value>
|
||||
[Parameter]
|
||||
public bool ShowPagingSummary { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the pager summary format.
|
||||
/// </summary>
|
||||
/// <value>The pager summary format.</value>
|
||||
[Parameter]
|
||||
public string PagingSummaryFormat { get; set; } = "Page {0} of {1} ({2} items)";
|
||||
|
||||
internal IQueryable<T> _view = null;
|
||||
/// <summary>
|
||||
/// Gets the paged view.
|
||||
/// </summary>
|
||||
/// <value>The paged view.</value>
|
||||
public virtual IQueryable<T> PagedView
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_view == null)
|
||||
{
|
||||
_view = (AllowPaging ? View.Skip(skip).Take(PageSize) : View).ToList().AsQueryable();
|
||||
_view = (AllowPaging && !LoadData.HasDelegate ? View.Skip(skip).Take(PageSize) : View).ToList().AsQueryable();
|
||||
}
|
||||
return _view;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the view.
|
||||
/// </summary>
|
||||
/// <value>The view.</value>
|
||||
public virtual IQueryable<T> View
|
||||
{
|
||||
get
|
||||
@@ -70,9 +170,16 @@ namespace Radzen
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the load data.
|
||||
/// </summary>
|
||||
/// <value>The load data.</value>
|
||||
[Parameter]
|
||||
public EventCallback<Radzen.LoadDataArgs> LoadData { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Reloads this instance.
|
||||
/// </summary>
|
||||
public async virtual Task Reload()
|
||||
{
|
||||
_view = null;
|
||||
@@ -92,11 +199,36 @@ namespace Radzen
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when [data changed].
|
||||
/// </summary>
|
||||
protected virtual void OnDataChanged()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set parameters as an asynchronous operation.
|
||||
/// </summary>
|
||||
/// <param name="parameters">The parameters.</param>
|
||||
/// <returns>A Task representing the asynchronous operation.</returns>
|
||||
public override async Task SetParametersAsync(ParameterView parameters)
|
||||
{
|
||||
bool pageSizeChanged = parameters.DidParameterChange(nameof(PageSize), PageSize) &&
|
||||
PageSize != pageSize;
|
||||
|
||||
await base.SetParametersAsync(parameters);
|
||||
|
||||
if (pageSizeChanged && !firstRender)
|
||||
{
|
||||
await InvokeAsync(Reload);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when [parameters set asynchronous].
|
||||
/// </summary>
|
||||
/// <returns>Task.</returns>
|
||||
protected override Task OnParametersSetAsync()
|
||||
{
|
||||
if (Visible && !LoadData.HasDelegate)
|
||||
@@ -111,70 +243,146 @@ namespace Radzen
|
||||
return base.OnParametersSetAsync();
|
||||
}
|
||||
|
||||
protected override Task OnAfterRenderAsync(bool firstRender)
|
||||
/// <summary>
|
||||
/// The first render
|
||||
/// </summary>
|
||||
bool firstRender = true;
|
||||
/// <summary>
|
||||
/// Called when [after render asynchronous].
|
||||
/// </summary>
|
||||
/// <param name="firstRender">if set to <c>true</c> [first render].</param>
|
||||
/// <returns>Task.</returns>
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
this.firstRender = firstRender;
|
||||
|
||||
if (firstRender)
|
||||
{
|
||||
await ReloadOnFirstRender();
|
||||
}
|
||||
|
||||
await base.OnAfterRenderAsync(firstRender);
|
||||
}
|
||||
|
||||
internal virtual async Task ReloadOnFirstRender()
|
||||
{
|
||||
if (firstRender && Visible && (LoadData.HasDelegate && Data == null))
|
||||
{
|
||||
InvokeAsync(Reload);
|
||||
await InvokeAsync(Reload);
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
return base.OnAfterRenderAsync(firstRender);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The skip
|
||||
/// </summary>
|
||||
protected int skip;
|
||||
|
||||
/// <summary>
|
||||
/// The top pager
|
||||
/// </summary>
|
||||
protected RadzenPager topPager;
|
||||
/// <summary>
|
||||
/// The bottom pager
|
||||
/// </summary>
|
||||
protected RadzenPager bottomPager;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the page callback.
|
||||
/// </summary>
|
||||
/// <value>The page callback.</value>
|
||||
[Parameter]
|
||||
public EventCallback<PagerEventArgs> Page { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Handles the <see cref="E:PageChanged" /> event.
|
||||
/// </summary>
|
||||
/// <param name="args">The <see cref="PagerEventArgs"/> instance containing the event data.</param>
|
||||
protected async Task OnPageChanged(PagerEventArgs args)
|
||||
{
|
||||
skip = args.Skip;
|
||||
CurrentPage = args.PageIndex;
|
||||
|
||||
await Page.InvokeAsync(args);
|
||||
|
||||
await InvokeAsync(Reload);
|
||||
}
|
||||
|
||||
internal int? pageSize;
|
||||
|
||||
/// <summary>
|
||||
/// Called when [page size changed].
|
||||
/// </summary>
|
||||
/// <param name="value">The value.</param>
|
||||
protected virtual async Task OnPageSizeChanged(int value)
|
||||
{
|
||||
pageSize = value;
|
||||
await InvokeAsync(Reload);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the pager.
|
||||
/// </summary>
|
||||
protected void CalculatePager()
|
||||
{
|
||||
if (topPager != null)
|
||||
{
|
||||
topPager.GoToPage(CurrentPage).Wait();
|
||||
InvokeAsync(topPager.Reload);
|
||||
topPager.SetCount(Count);
|
||||
topPager.SetCurrentPage(CurrentPage);
|
||||
}
|
||||
|
||||
if (bottomPager != null)
|
||||
{
|
||||
bottomPager.GoToPage(CurrentPage).Wait();
|
||||
InvokeAsync(bottomPager.Reload);
|
||||
bottomPager.SetCount(Count);
|
||||
bottomPager.SetCurrentPage(CurrentPage);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task GoToPage(int page)
|
||||
/// <summary>
|
||||
/// Goes to page.
|
||||
/// </summary>
|
||||
/// <param name="page">The page.</param>
|
||||
/// <param name="forceReload">if set to <c>true</c> [force reload].</param>
|
||||
public async Task GoToPage(int page, bool forceReload = false)
|
||||
{
|
||||
if (topPager != null)
|
||||
{
|
||||
await topPager.GoToPage(page);
|
||||
await topPager.GoToPage(page, forceReload);
|
||||
}
|
||||
|
||||
if (bottomPager != null)
|
||||
{
|
||||
await bottomPager.GoToPage(page);
|
||||
await bottomPager.GoToPage(page, forceReload);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Firsts the page.
|
||||
/// </summary>
|
||||
/// <param name="forceReload">if set to <c>true</c> [force reload].</param>
|
||||
public async Task FirstPage(bool forceReload = false)
|
||||
{
|
||||
var shouldReload = forceReload && CurrentPage == 0;
|
||||
|
||||
if (topPager != null)
|
||||
{
|
||||
await topPager.FirstPage(forceReload);
|
||||
await topPager.FirstPage();
|
||||
}
|
||||
|
||||
if (bottomPager != null)
|
||||
{
|
||||
await bottomPager.FirstPage(forceReload);
|
||||
await bottomPager.FirstPage();
|
||||
}
|
||||
|
||||
if (shouldReload)
|
||||
{
|
||||
await InvokeAsync(Reload);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Previouses the page.
|
||||
/// </summary>
|
||||
public async Task PrevPage()
|
||||
{
|
||||
if (topPager != null)
|
||||
@@ -188,6 +396,9 @@ namespace Radzen
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Nexts the page.
|
||||
/// </summary>
|
||||
public async Task NextPage()
|
||||
{
|
||||
if (topPager != null)
|
||||
@@ -201,6 +412,9 @@ namespace Radzen
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Lasts the page.
|
||||
/// </summary>
|
||||
public async Task LastPage()
|
||||
{
|
||||
if (topPager != null)
|
||||
|
||||
@@ -7,9 +7,15 @@ using System.Linq.Dynamic.Core;
|
||||
|
||||
namespace Radzen
|
||||
{
|
||||
/// <summary>
|
||||
/// Class QueryableExtension.
|
||||
/// </summary>
|
||||
public static class QueryableExtension
|
||||
{
|
||||
private static readonly IDictionary<string, string> FilterOperators = new Dictionary<string, string>
|
||||
/// <summary>
|
||||
/// The filter operators
|
||||
/// </summary>
|
||||
internal static readonly IDictionary<string, string> FilterOperators = new Dictionary<string, string>
|
||||
{
|
||||
{"eq", "="},
|
||||
{"ne", "!="},
|
||||
@@ -19,9 +25,57 @@ namespace Radzen
|
||||
{"ge", ">="},
|
||||
{"startswith", "StartsWith"},
|
||||
{"endswith", "EndsWith"},
|
||||
{"contains", "Contains"}
|
||||
{"contains", "Contains"},
|
||||
{"DoesNotContain", "Contains"}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// The linq filter operators
|
||||
/// </summary>
|
||||
internal static readonly IDictionary<FilterOperator, string> LinqFilterOperators = new Dictionary<FilterOperator, string>
|
||||
{
|
||||
{FilterOperator.Equals, "="},
|
||||
{FilterOperator.NotEquals, "!="},
|
||||
{FilterOperator.LessThan, "<"},
|
||||
{FilterOperator.LessThanOrEquals, "<="},
|
||||
{FilterOperator.GreaterThan, ">"},
|
||||
{FilterOperator.GreaterThanOrEquals, ">="},
|
||||
{FilterOperator.StartsWith, "StartsWith"},
|
||||
{FilterOperator.EndsWith, "EndsWith"},
|
||||
{FilterOperator.Contains, "Contains"},
|
||||
{FilterOperator.DoesNotContain, "DoesNotContain"},
|
||||
{FilterOperator.IsNull, "=="},
|
||||
{FilterOperator.IsEmpty, "=="},
|
||||
{FilterOperator.IsNotNull, "!="},
|
||||
{FilterOperator.IsNotEmpty, "!="}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// The o data filter operators
|
||||
/// </summary>
|
||||
internal static readonly IDictionary<FilterOperator, string> ODataFilterOperators = new Dictionary<FilterOperator, string>
|
||||
{
|
||||
{FilterOperator.Equals, "eq"},
|
||||
{FilterOperator.NotEquals, "ne"},
|
||||
{FilterOperator.LessThan, "lt"},
|
||||
{FilterOperator.LessThanOrEquals, "le"},
|
||||
{FilterOperator.GreaterThan, "gt"},
|
||||
{FilterOperator.GreaterThanOrEquals, "ge"},
|
||||
{FilterOperator.StartsWith, "startswith"},
|
||||
{FilterOperator.EndsWith, "endswith"},
|
||||
{FilterOperator.Contains, "contains"},
|
||||
{FilterOperator.DoesNotContain, "DoesNotContain"},
|
||||
{FilterOperator.IsNull, "eq"},
|
||||
{FilterOperator.IsEmpty, "eq"},
|
||||
{FilterOperator.IsNotNull, "ne"},
|
||||
{FilterOperator.IsNotEmpty, "ne"}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Converts to list.
|
||||
/// </summary>
|
||||
/// <param name="query">The query.</param>
|
||||
/// <returns>IList.</returns>
|
||||
public static IList ToList(IQueryable query)
|
||||
{
|
||||
var genericToList = typeof(Enumerable).GetMethod("ToList")
|
||||
@@ -29,6 +83,12 @@ namespace Radzen
|
||||
return (IList)genericToList.Invoke(null, new[] { query });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts to filterstring.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="columns">The columns.</param>
|
||||
/// <returns>System.String.</returns>
|
||||
public static string ToFilterString<T>(this IEnumerable<RadzenGridColumn<T>> columns)
|
||||
{
|
||||
Func<RadzenGridColumn<T>, bool> canFilter = (c) => c.Filterable && !string.IsNullOrEmpty(c.Type) &&
|
||||
@@ -75,6 +135,146 @@ namespace Radzen
|
||||
return "";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts to filterstring.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="columns">The columns.</param>
|
||||
/// <returns>System.String.</returns>
|
||||
public static string ToFilterString<T>(this IEnumerable<RadzenDataGridColumn<T>> columns)
|
||||
{
|
||||
Func<RadzenDataGridColumn<T>, bool> canFilter = (c) => c.Filterable && c.FilterPropertyType != null &&
|
||||
(!(c.GetFilterValue() == null || c.GetFilterValue() as string == string.Empty) || c.GetFilterOperator() == FilterOperator.IsNotNull
|
||||
|| c.GetFilterOperator() == FilterOperator.IsNull || c.GetFilterOperator() == FilterOperator.IsEmpty
|
||||
|| c.GetFilterOperator() == FilterOperator.IsNotEmpty)
|
||||
&& c.GetFilterProperty() != null;
|
||||
|
||||
if (columns.Where(canFilter).Any())
|
||||
{
|
||||
var gridLogicalFilterOperator = columns.FirstOrDefault()?.Grid?.LogicalFilterOperator;
|
||||
var gridBooleanOperator = gridLogicalFilterOperator == LogicalFilterOperator.And ? "and" : "or";
|
||||
|
||||
var whereList = new List<string>();
|
||||
foreach (var column in columns.Where(canFilter))
|
||||
{
|
||||
string value = "";
|
||||
string secondValue = "";
|
||||
|
||||
var v = column.GetFilterValue();
|
||||
var sv = column.GetSecondFilterValue();
|
||||
|
||||
if (PropertyAccess.IsDate(column.FilterPropertyType))
|
||||
{
|
||||
if (v != null)
|
||||
{
|
||||
value = v is DateTime ? ((DateTime)v).ToString("yyyy-MM-ddTHH:mm:ss.fffZ") : v is DateTimeOffset ? ((DateTimeOffset)v).UtcDateTime.ToString("yyyy-MM-ddTHH:mm:ss.fffZ") : "";
|
||||
}
|
||||
if (sv != null)
|
||||
{
|
||||
secondValue = sv is DateTime ? ((DateTime)sv).ToString("yyyy-MM-ddTHH:mm:ss.fffZ") : sv is DateTimeOffset ? ((DateTimeOffset)sv).UtcDateTime.ToString("yyyy-MM-ddTHH:mm:ss.fffZ") : "";
|
||||
}
|
||||
}
|
||||
else if (PropertyAccess.IsEnum(column.FilterPropertyType) || PropertyAccess.IsNullableEnum(column.FilterPropertyType))
|
||||
{
|
||||
if (v != null)
|
||||
{
|
||||
value = ((int)v).ToString();
|
||||
}
|
||||
if (sv != null)
|
||||
{
|
||||
secondValue = ((int)sv).ToString();
|
||||
}
|
||||
}
|
||||
else if (IsEnumerable(column.FilterPropertyType) && column.FilterPropertyType != typeof(string))
|
||||
{
|
||||
var enumerableValue = ((IEnumerable)(v != null ? v : Enumerable.Empty<object>())).AsQueryable();
|
||||
var enumerableSecondValue = ((IEnumerable)(sv != null ? sv : Enumerable.Empty<object>())).AsQueryable();
|
||||
|
||||
var enumerableValueAsString = "new []{" + String.Join(",",
|
||||
(enumerableValue.ElementType == typeof(string) ? enumerableValue.Cast<string>().Select(i => $@"""{i}""").Cast<object>() : enumerableValue.Cast<object>())) + "}";
|
||||
|
||||
var enumerableSecondValueAsString = "new []{" + String.Join(",",
|
||||
(enumerableSecondValue.ElementType == typeof(string) ? enumerableSecondValue.Cast<string>().Select(i => $@"""{i}""").Cast<object>() : enumerableSecondValue.Cast<object>())) + "}";
|
||||
|
||||
if (enumerableValue != null)
|
||||
{
|
||||
var columnFilterOperator = column.GetFilterOperator();
|
||||
var columnSecondFilterOperator = column.GetSecondFilterOperator();
|
||||
var linqOperator = LinqFilterOperators[column.GetFilterOperator()];
|
||||
if (linqOperator == null)
|
||||
{
|
||||
linqOperator = "==";
|
||||
}
|
||||
|
||||
var booleanOperator = column.LogicalFilterOperator == LogicalFilterOperator.And ? "and" : "or";
|
||||
|
||||
var property = PropertyAccess.GetProperty(column.GetFilterProperty());
|
||||
|
||||
if (property.IndexOf(".") != -1)
|
||||
{
|
||||
property = $"({property})";
|
||||
}
|
||||
|
||||
if (sv == null)
|
||||
{
|
||||
if (columnFilterOperator == FilterOperator.Contains || columnFilterOperator == FilterOperator.DoesNotContain)
|
||||
{
|
||||
whereList.Add($@"{(columnFilterOperator == FilterOperator.DoesNotContain ? "!" : "")}({enumerableValueAsString}).Contains({property})");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((columnFilterOperator == FilterOperator.Contains || columnFilterOperator == FilterOperator.DoesNotContain) &&
|
||||
(columnSecondFilterOperator == FilterOperator.Contains || columnSecondFilterOperator == FilterOperator.DoesNotContain))
|
||||
{
|
||||
whereList.Add($@"{(columnFilterOperator == FilterOperator.DoesNotContain ? "!" : "")}({enumerableValueAsString}).Contains({property}) {booleanOperator} {(columnSecondFilterOperator == FilterOperator.DoesNotContain ? "!" : "")}({enumerableSecondValueAsString}).Contains({property})");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
value = (string)Convert.ChangeType(column.GetFilterValue(), typeof(string));
|
||||
secondValue = (string)Convert.ChangeType(column.GetSecondFilterValue(), typeof(string));
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(value) || column.GetFilterOperator() == FilterOperator.IsNotNull
|
||||
|| column.GetFilterOperator() == FilterOperator.IsNull
|
||||
|| column.GetFilterOperator() == FilterOperator.IsEmpty
|
||||
|| column.GetFilterOperator() == FilterOperator.IsNotEmpty)
|
||||
{
|
||||
var linqOperator = LinqFilterOperators[column.GetFilterOperator()];
|
||||
if (linqOperator == null)
|
||||
{
|
||||
linqOperator = "==";
|
||||
}
|
||||
|
||||
var booleanOperator = column.LogicalFilterOperator == LogicalFilterOperator.And ? "and" : "or";
|
||||
|
||||
if (string.IsNullOrEmpty(secondValue))
|
||||
{
|
||||
whereList.Add(GetColumnFilter(column, value));
|
||||
}
|
||||
else
|
||||
{
|
||||
whereList.Add($"({GetColumnFilter(column, value)} {booleanOperator} {GetColumnFilter(column, secondValue, true)})");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return string.Join($" {gridBooleanOperator} ", whereList.Where(i => !string.IsNullOrEmpty(i)));
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the column filter.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="column">The column.</param>
|
||||
/// <param name="second">if set to <c>true</c> [second].</param>
|
||||
/// <returns>System.String.</returns>
|
||||
private static string GetColumnFilter<T>(RadzenGridColumn<T> column, bool second = false)
|
||||
{
|
||||
var property = PropertyAccess.GetProperty(column.GetFilterProperty());
|
||||
@@ -127,6 +327,10 @@ namespace Radzen
|
||||
{
|
||||
return $@"({property} == null ? """" : {property}){filterCaseSensitivityOperator}.Contains(""{value}""{filterCaseSensitivityOperator})";
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(value) && columnFilterOperator == "DoesNotContain")
|
||||
{
|
||||
return $@"({property} == null ? """" : !{property}){filterCaseSensitivityOperator}.Contains(""{value}""{filterCaseSensitivityOperator})";
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(value) && columnFilterOperator == "startswith")
|
||||
{
|
||||
return $@"({property} == null ? """" : {property}){filterCaseSensitivityOperator}.StartsWith(""{value}""{filterCaseSensitivityOperator})";
|
||||
@@ -137,7 +341,11 @@ namespace Radzen
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(value) && columnFilterOperator == "eq")
|
||||
{
|
||||
return $@"{property} == null ? """" : {property}{filterCaseSensitivityOperator} == {value}{filterCaseSensitivityOperator}";
|
||||
return $@"({property} == null ? """" : {property}){filterCaseSensitivityOperator} == ""{value}""{filterCaseSensitivityOperator}";
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(value) && columnFilterOperator == "ne")
|
||||
{
|
||||
return $@"({property} == null ? """" : {property}){filterCaseSensitivityOperator} != ""{value}""{filterCaseSensitivityOperator}";
|
||||
}
|
||||
}
|
||||
else if (columnType == "number" || columnType == "integer")
|
||||
@@ -152,6 +360,144 @@ namespace Radzen
|
||||
return "";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the column filter.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="column">The column.</param>
|
||||
/// <param name="value">The value.</param>
|
||||
/// <param name="second">if set to <c>true</c> [second].</param>
|
||||
/// <returns>System.String.</returns>
|
||||
private static string GetColumnFilter<T>(RadzenDataGridColumn<T> column, string value, bool second = false)
|
||||
{
|
||||
var property = PropertyAccess.GetProperty(column.GetFilterProperty());
|
||||
|
||||
if (property.IndexOf(".") != -1)
|
||||
{
|
||||
property = $"({property})";
|
||||
}
|
||||
|
||||
var columnFilterOperator = !second ? column.GetFilterOperator() : column.GetSecondFilterOperator();
|
||||
|
||||
var linqOperator = LinqFilterOperators[columnFilterOperator];
|
||||
if (linqOperator == null)
|
||||
{
|
||||
linqOperator = "==";
|
||||
}
|
||||
|
||||
if (column.FilterPropertyType == typeof(string))
|
||||
{
|
||||
string filterCaseSensitivityOperator = column.Grid.FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ? ".ToLower()" : "";
|
||||
|
||||
if (!string.IsNullOrEmpty(value) && columnFilterOperator == FilterOperator.Contains)
|
||||
{
|
||||
return $@"({property} == null ? """" : {property}){filterCaseSensitivityOperator}.Contains(""{value}""{filterCaseSensitivityOperator})";
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(value) && columnFilterOperator == FilterOperator.DoesNotContain)
|
||||
{
|
||||
return $@"!({property} == null ? """" : {property}){filterCaseSensitivityOperator}.Contains(""{value}""{filterCaseSensitivityOperator})";
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(value) && columnFilterOperator == FilterOperator.StartsWith)
|
||||
{
|
||||
return $@"({property} == null ? """" : {property}){filterCaseSensitivityOperator}.StartsWith(""{value}""{filterCaseSensitivityOperator})";
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(value) && columnFilterOperator == FilterOperator.EndsWith)
|
||||
{
|
||||
return $@"({property} == null ? """" : {property}){filterCaseSensitivityOperator}.EndsWith(""{value}""{filterCaseSensitivityOperator})";
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(value) && columnFilterOperator == FilterOperator.Equals)
|
||||
{
|
||||
return $@"({property} == null ? """" : {property}){filterCaseSensitivityOperator} == ""{value}""{filterCaseSensitivityOperator}";
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(value) && columnFilterOperator == FilterOperator.NotEquals)
|
||||
{
|
||||
return $@"({property} == null ? """" : {property}){filterCaseSensitivityOperator} != ""{value}""{filterCaseSensitivityOperator}";
|
||||
}
|
||||
else if (columnFilterOperator == FilterOperator.IsNull)
|
||||
{
|
||||
return $@"np({property}) == null";
|
||||
}
|
||||
else if (columnFilterOperator == FilterOperator.IsEmpty)
|
||||
{
|
||||
return $@"np({property}) == """"";
|
||||
}
|
||||
else if (columnFilterOperator == FilterOperator.IsNotEmpty)
|
||||
{
|
||||
return $@"np({property}) != """"";
|
||||
}
|
||||
else if (columnFilterOperator == FilterOperator.IsNotNull)
|
||||
{
|
||||
return $@"np({property}) != null";
|
||||
}
|
||||
}
|
||||
else if (PropertyAccess.IsNumeric(column.FilterPropertyType))
|
||||
{
|
||||
if (columnFilterOperator == FilterOperator.IsNull || columnFilterOperator == FilterOperator.IsNotNull)
|
||||
{
|
||||
return $"{property} {linqOperator} null";
|
||||
}
|
||||
else if (columnFilterOperator == FilterOperator.IsEmpty || columnFilterOperator == FilterOperator.IsNotEmpty)
|
||||
{
|
||||
return $@"{property} {linqOperator} """"";
|
||||
}
|
||||
else
|
||||
{
|
||||
return $"{property} {linqOperator} {value}";
|
||||
}
|
||||
}
|
||||
else if (column.FilterPropertyType == typeof(DateTime) ||
|
||||
column.FilterPropertyType == typeof(DateTime?) ||
|
||||
column.FilterPropertyType == typeof(DateTimeOffset) ||
|
||||
column.FilterPropertyType == typeof(DateTimeOffset?))
|
||||
{
|
||||
if (columnFilterOperator == FilterOperator.IsNull || columnFilterOperator == FilterOperator.IsNotNull)
|
||||
{
|
||||
return $"{property} {linqOperator} null";
|
||||
}
|
||||
else if (columnFilterOperator == FilterOperator.IsEmpty || columnFilterOperator == FilterOperator.IsNotEmpty)
|
||||
{
|
||||
return $@"{property} {linqOperator} """"";
|
||||
}
|
||||
else
|
||||
{
|
||||
var dateTimeValue = DateTime.Parse(value, null, System.Globalization.DateTimeStyles.RoundtripKind);
|
||||
var finalDate = dateTimeValue.TimeOfDay == TimeSpan.Zero ? dateTimeValue.Date : dateTimeValue;
|
||||
var dateFormat = dateTimeValue.TimeOfDay == TimeSpan.Zero ? "yyyy-MM-dd" : "yyyy-MM-ddTHH:mm:ssZ";
|
||||
var dateFunction = column.FilterPropertyType == typeof(DateTimeOffset) || column.FilterPropertyType == typeof(DateTimeOffset?) ? "DateTimeOffset" : "DateTime";
|
||||
|
||||
return $@"{property} {linqOperator} {dateFunction}(""{finalDate.ToString(dateFormat)}"")";
|
||||
}
|
||||
}
|
||||
else if (column.FilterPropertyType == typeof(bool) || column.FilterPropertyType == typeof(bool?))
|
||||
{
|
||||
return $"{property} == {value}";
|
||||
}
|
||||
else if (column.FilterPropertyType == typeof(Guid) || column.FilterPropertyType == typeof(Guid?))
|
||||
{
|
||||
if (columnFilterOperator == FilterOperator.IsNull || columnFilterOperator == FilterOperator.IsNotNull)
|
||||
{
|
||||
return $"{property} {linqOperator} null";
|
||||
}
|
||||
else if (columnFilterOperator == FilterOperator.IsEmpty || columnFilterOperator == FilterOperator.IsNotEmpty)
|
||||
{
|
||||
return $@"{property} {linqOperator} """"";
|
||||
}
|
||||
else
|
||||
{
|
||||
return $@"{property} {linqOperator} Guid(""{value}"")";
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the column o data filter.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="column">The column.</param>
|
||||
/// <param name="second">if set to <c>true</c> [second].</param>
|
||||
/// <returns>System.String.</returns>
|
||||
private static string GetColumnODataFilter<T>(RadzenGridColumn<T> column, bool second = false)
|
||||
{
|
||||
var columnType = column.Type;
|
||||
@@ -189,6 +535,12 @@ namespace Radzen
|
||||
$"contains({property}, tolower('{value}'))" :
|
||||
$"contains({property}, '{value}')";
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(value) && columnFilterOperator == "DoesNotContain")
|
||||
{
|
||||
return column.Grid.FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ?
|
||||
$"not(contains({property}, tolower('{value}')))" :
|
||||
$"not(contains({property}, '{value}'))";
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(value) && columnFilterOperator == "startswith")
|
||||
{
|
||||
return column.Grid.FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ?
|
||||
@@ -203,7 +555,15 @@ namespace Radzen
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(value) && columnFilterOperator == "eq")
|
||||
{
|
||||
return $"{property} eq {value}";
|
||||
return column.Grid.FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ?
|
||||
$"{property} eq tolower('{value}')" :
|
||||
$"{property} eq '{value}'";
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(value) && columnFilterOperator == "ne")
|
||||
{
|
||||
return column.Grid.FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ?
|
||||
$"{property} ne tolower('{value}')" :
|
||||
$"{property} ne '{value}'";
|
||||
}
|
||||
}
|
||||
else if (columnType == "number" || columnType == "integer")
|
||||
@@ -218,6 +578,145 @@ namespace Radzen
|
||||
return "";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the column o data filter.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="column">The column.</param>
|
||||
/// <param name="second">if set to <c>true</c> [second].</param>
|
||||
/// <returns>System.String.</returns>
|
||||
private static string GetColumnODataFilter<T>(RadzenDataGridColumn<T> column, bool second = false)
|
||||
{
|
||||
var property = column.GetFilterProperty().Replace('.', '/');
|
||||
|
||||
var columnFilterOperator = !second ? column.GetFilterOperator() : column.GetSecondFilterOperator();
|
||||
var odataFilterOperator = ODataFilterOperators[columnFilterOperator];
|
||||
|
||||
var value = IsEnumerable(column.FilterPropertyType) && column.FilterPropertyType != typeof(string) ? null :
|
||||
!second ? (string)Convert.ChangeType(column.GetFilterValue(), typeof(string)) :
|
||||
(string)Convert.ChangeType(column.GetSecondFilterValue(), typeof(string));
|
||||
|
||||
if (column.Grid.FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive && column.FilterPropertyType == typeof(string))
|
||||
{
|
||||
property = $"tolower({property})";
|
||||
}
|
||||
|
||||
if (column.FilterPropertyType == typeof(string))
|
||||
{
|
||||
if (!string.IsNullOrEmpty(value) && columnFilterOperator == FilterOperator.Contains)
|
||||
{
|
||||
return column.Grid.FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ?
|
||||
$"contains({property}, tolower('{value}'))" :
|
||||
$"contains({property}, '{value}')";
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(value) && columnFilterOperator == FilterOperator.DoesNotContain)
|
||||
{
|
||||
return column.Grid.FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ?
|
||||
$"not(contains({property}, tolower('{value}')))" :
|
||||
$"not(contains({property}, '{value}'))";
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(value) && columnFilterOperator == FilterOperator.StartsWith)
|
||||
{
|
||||
return column.Grid.FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ?
|
||||
$"startswith({property}, tolower('{value}'))" :
|
||||
$"startswith({property}, '{value}')";
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(value) && columnFilterOperator == FilterOperator.EndsWith)
|
||||
{
|
||||
return column.Grid.FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ?
|
||||
$"endswith({property}, tolower('{value}'))" :
|
||||
$"endswith({property}, '{value}')";
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(value) && columnFilterOperator == FilterOperator.Equals)
|
||||
{
|
||||
return column.Grid.FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ?
|
||||
$"{property} eq tolower('{value}')" :
|
||||
$"{property} eq '{value}'";
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(value) && columnFilterOperator == FilterOperator.NotEquals)
|
||||
{
|
||||
return column.Grid.FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ?
|
||||
$"{property} ne tolower('{value}')" :
|
||||
$"{property} ne '{value}'";
|
||||
}
|
||||
else if (columnFilterOperator == FilterOperator.IsNull || columnFilterOperator == FilterOperator.IsNotNull)
|
||||
{
|
||||
return $"{property} {odataFilterOperator} null";
|
||||
}
|
||||
else if (columnFilterOperator == FilterOperator.IsEmpty || columnFilterOperator == FilterOperator.IsNotEmpty)
|
||||
{
|
||||
return $"{property} {odataFilterOperator} ''";
|
||||
}
|
||||
}
|
||||
else if (IsEnumerable(column.FilterPropertyType) && column.FilterPropertyType != typeof(string))
|
||||
{
|
||||
var v = !second ? column.GetFilterValue() : column.GetSecondFilterValue();
|
||||
|
||||
var enumerableValue = ((IEnumerable)(v != null ? v : 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() && columnFilterOperator == FilterOperator.Contains)
|
||||
{
|
||||
return $"{property} in {enumerableValueAsString}";
|
||||
}
|
||||
else if (enumerableValue.Any() && columnFilterOperator == FilterOperator.DoesNotContain)
|
||||
{
|
||||
return $"not({property} in {enumerableValueAsString})";
|
||||
}
|
||||
}
|
||||
else if (PropertyAccess.IsNumeric(column.FilterPropertyType))
|
||||
{
|
||||
return $"{property} {odataFilterOperator} {value}";
|
||||
}
|
||||
else if (column.FilterPropertyType == typeof(bool) || column.FilterPropertyType == typeof(bool?))
|
||||
{
|
||||
if (columnFilterOperator == FilterOperator.IsNull || columnFilterOperator == FilterOperator.IsNotNull)
|
||||
{
|
||||
return $"{property} {odataFilterOperator} null";
|
||||
}
|
||||
else if (columnFilterOperator == FilterOperator.IsEmpty || columnFilterOperator == FilterOperator.IsNotEmpty)
|
||||
{
|
||||
return $"{property} {odataFilterOperator} ''";
|
||||
}
|
||||
else
|
||||
{
|
||||
return $"{property} eq {value.ToLower()}";
|
||||
}
|
||||
}
|
||||
else if (column.FilterPropertyType == typeof(DateTime) ||
|
||||
column.FilterPropertyType == typeof(DateTime?) ||
|
||||
column.FilterPropertyType == typeof(DateTimeOffset) ||
|
||||
column.FilterPropertyType == typeof(DateTimeOffset?))
|
||||
{
|
||||
if (columnFilterOperator == FilterOperator.IsNull || columnFilterOperator == FilterOperator.IsNotNull)
|
||||
{
|
||||
return $"{property} {odataFilterOperator} null";
|
||||
}
|
||||
else if (columnFilterOperator == FilterOperator.IsEmpty || columnFilterOperator == FilterOperator.IsNotEmpty)
|
||||
{
|
||||
return $"{property} {odataFilterOperator} ''";
|
||||
}
|
||||
else
|
||||
{
|
||||
return $"{property} {odataFilterOperator} {DateTime.Parse(value, null, System.Globalization.DateTimeStyles.RoundtripKind).ToString("yyyy-MM-ddTHH:mm:ss.fffZ")}";
|
||||
}
|
||||
}
|
||||
else if (column.FilterPropertyType == typeof(Guid) || column.FilterPropertyType == typeof(Guid?))
|
||||
{
|
||||
return $"{property} {odataFilterOperator} {value}";
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts to odatafilterstring.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="columns">The columns.</param>
|
||||
/// <returns>System.String.</returns>
|
||||
public static string ToODataFilterString<T>(this IEnumerable<RadzenGridColumn<T>> columns)
|
||||
{
|
||||
Func<RadzenGridColumn<T>, bool> canFilter = (c) => c.Filterable && !string.IsNullOrEmpty(c.Type) &&
|
||||
@@ -266,6 +765,68 @@ namespace Radzen
|
||||
return "";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts to odatafilterstring.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="columns">The columns.</param>
|
||||
/// <returns>System.String.</returns>
|
||||
public static string ToODataFilterString<T>(this IEnumerable<RadzenDataGridColumn<T>> columns)
|
||||
{
|
||||
Func<RadzenDataGridColumn<T>, bool> canFilter = (c) => c.Filterable && c.FilterPropertyType != null &&
|
||||
(!(c.GetFilterValue() == null || c.GetFilterValue() as string == string.Empty)
|
||||
|| c.GetFilterOperator() == FilterOperator.IsNotNull || c.GetFilterOperator() == FilterOperator.IsNull
|
||||
|| c.GetFilterOperator() == FilterOperator.IsEmpty || c.GetFilterOperator() == FilterOperator.IsNotEmpty)
|
||||
&& c.GetFilterProperty() != null;
|
||||
|
||||
if (columns.Where(canFilter).Any())
|
||||
{
|
||||
var gridLogicalFilterOperator = columns.FirstOrDefault()?.Grid?.LogicalFilterOperator;
|
||||
var gridBooleanOperator = gridLogicalFilterOperator == LogicalFilterOperator.And ? "and" : "or";
|
||||
|
||||
var whereList = new List<string>();
|
||||
foreach (var column in columns.Where(canFilter))
|
||||
{
|
||||
var property = column.GetFilterProperty().Replace('.', '/');
|
||||
|
||||
var value = column.GetFilterValue();
|
||||
var secondValue = column.GetSecondFilterValue();
|
||||
|
||||
if (value != null || column.GetFilterOperator() == FilterOperator.IsNotNull || column.GetFilterOperator() == FilterOperator.IsNull
|
||||
|| column.GetFilterOperator() == FilterOperator.IsEmpty || column.GetFilterOperator() == FilterOperator.IsNotEmpty)
|
||||
{
|
||||
var linqOperator = ODataFilterOperators[column.GetFilterOperator()];
|
||||
if (linqOperator == null)
|
||||
{
|
||||
linqOperator = "==";
|
||||
}
|
||||
|
||||
var booleanOperator = column.LogicalFilterOperator == LogicalFilterOperator.And ? "and" : "or";
|
||||
|
||||
if (secondValue == null)
|
||||
{
|
||||
whereList.Add(GetColumnODataFilter(column));
|
||||
}
|
||||
else
|
||||
{
|
||||
whereList.Add($"({GetColumnODataFilter(column)} {booleanOperator} {GetColumnODataFilter(column, true)})");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return string.Join($" {gridBooleanOperator} ", whereList.Where(i => !string.IsNullOrEmpty(i)));
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wheres the specified columns.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="source">The source.</param>
|
||||
/// <param name="columns">The columns.</param>
|
||||
/// <returns>IQueryable<T>.</returns>
|
||||
public static IQueryable<T> Where<T>(this IQueryable<T> source, IEnumerable<RadzenGridColumn<T>> columns)
|
||||
{
|
||||
Func<RadzenGridColumn<T>, bool> canFilter = (c) => c.Filterable && !string.IsNullOrEmpty(c.Type) &&
|
||||
@@ -306,6 +867,11 @@ namespace Radzen
|
||||
whereList.Add($@"{property}{filterCaseSensitivityOperator}.{comparison}(@{index}{filterCaseSensitivityOperator})", new object[] { column.FilterValue });
|
||||
index++;
|
||||
}
|
||||
else if (comparison == "DoesNotContain")
|
||||
{
|
||||
whereList.Add($@"!{property}{filterCaseSensitivityOperator}.Contains(@{index}{filterCaseSensitivityOperator})", new object[] { column.FilterValue });
|
||||
index++;
|
||||
}
|
||||
else
|
||||
{
|
||||
whereList.Add($@"{property}{filterCaseSensitivityOperator} {comparison} @{index}{filterCaseSensitivityOperator}", new object[] { column.FilterValue });
|
||||
@@ -316,12 +882,14 @@ namespace Radzen
|
||||
{
|
||||
var firstFilter = comparison == "StartsWith" || comparison == "EndsWith" || comparison == "Contains" ?
|
||||
$@"{property}{filterCaseSensitivityOperator}.{comparison}(@{index}{filterCaseSensitivityOperator})" :
|
||||
comparison == "DoesNotContain" ? $@"!{property}{filterCaseSensitivityOperator}.Contains(@{index}{filterCaseSensitivityOperator})" :
|
||||
$@"{property}{filterCaseSensitivityOperator} {comparison} @{index}{filterCaseSensitivityOperator}";
|
||||
index++;
|
||||
|
||||
var secondComparison = FilterOperators[column.SecondFilterOperator];
|
||||
var secondFilter = secondComparison == "StartsWith" || secondComparison == "EndsWith" || secondComparison == "Contains" ?
|
||||
$@"{property}{filterCaseSensitivityOperator}.{secondComparison}(@{index}{filterCaseSensitivityOperator})" :
|
||||
secondComparison == "DoesNotContain" ? $@"!{property}{filterCaseSensitivityOperator}.Contains(@{index}{filterCaseSensitivityOperator})" :
|
||||
$@"{property}{filterCaseSensitivityOperator} {secondComparison} @{index}{filterCaseSensitivityOperator}";
|
||||
index++;
|
||||
|
||||
@@ -335,9 +903,294 @@ namespace Radzen
|
||||
return source;
|
||||
}
|
||||
|
||||
private static bool IsEnumerable(Type type)
|
||||
{
|
||||
return typeof(IEnumerable).IsAssignableFrom(type) || typeof(IEnumerable<>).IsAssignableFrom(type);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wheres the specified columns.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="source">The source.</param>
|
||||
/// <param name="columns">The columns.</param>
|
||||
/// <returns>IQueryable<T>.</returns>
|
||||
public static IQueryable<T> Where<T>(this IQueryable<T> source, IEnumerable<RadzenDataGridColumn<T>> columns)
|
||||
{
|
||||
Func<RadzenDataGridColumn<T>, bool> canFilter = (c) => c.Filterable && c.FilterPropertyType != null &&
|
||||
(!(c.GetFilterValue() == null || c.GetFilterValue() as string == string.Empty)
|
||||
|| c.GetFilterOperator() == FilterOperator.IsNotNull || c.GetFilterOperator() == FilterOperator.IsNull
|
||||
|| c.GetFilterOperator() == FilterOperator.IsEmpty || c.GetFilterOperator() == FilterOperator.IsNotEmpty)
|
||||
&& c.GetFilterProperty() != null;
|
||||
|
||||
if (columns.Where(canFilter).Any())
|
||||
{
|
||||
var gridLogicalFilterOperator = columns.FirstOrDefault()?.Grid?.LogicalFilterOperator;
|
||||
var gridBooleanOperator = gridLogicalFilterOperator == LogicalFilterOperator.And ? "and" : "or";
|
||||
|
||||
var index = 0;
|
||||
var whereList = new Dictionary<string, IEnumerable<object>>();
|
||||
foreach (var column in columns.Where(canFilter))
|
||||
{
|
||||
var property = PropertyAccess.GetProperty(column.GetFilterProperty());
|
||||
|
||||
if (property.IndexOf(".") != -1)
|
||||
{
|
||||
property = $"({property})";
|
||||
}
|
||||
|
||||
if (column.FilterPropertyType == typeof(string) &&
|
||||
!(column.GetFilterOperator() == FilterOperator.IsNotNull || column.GetFilterOperator() == FilterOperator.IsNull
|
||||
|| column.GetFilterOperator() == FilterOperator.IsEmpty || column.GetFilterOperator() == FilterOperator.IsNotEmpty))
|
||||
{
|
||||
property = $@"({property} == null ? """" : {property})";
|
||||
}
|
||||
|
||||
string filterCaseSensitivityOperator = column.FilterPropertyType == typeof(string)
|
||||
&& column.GetFilterOperator() != FilterOperator.IsNotNull && column.GetFilterOperator() != FilterOperator.IsNull
|
||||
&& column.GetFilterOperator() != FilterOperator.IsEmpty && column.GetFilterOperator() != FilterOperator.IsNotEmpty
|
||||
&& column.Grid.FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ? ".ToLower()" : "";
|
||||
|
||||
|
||||
var comparison = LinqFilterOperators[column.GetFilterOperator()];
|
||||
|
||||
var booleanOperator = column.LogicalFilterOperator == LogicalFilterOperator.And ? "and" : "or";
|
||||
|
||||
if (column.GetSecondFilterValue() == null)
|
||||
{
|
||||
if (comparison == "StartsWith" || comparison == "EndsWith" || comparison == "Contains")
|
||||
{
|
||||
if (IsEnumerable(column.FilterPropertyType) && column.FilterPropertyType != typeof(string) && comparison == "Contains")
|
||||
{
|
||||
whereList.Add($@"(@{index}).Contains({property})", new object[] { column.GetFilterValue() });
|
||||
}
|
||||
else
|
||||
{
|
||||
whereList.Add($@"{property}{filterCaseSensitivityOperator}.{comparison}(@{index}{filterCaseSensitivityOperator})", new object[] { column.GetFilterValue() });
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
else if (comparison == "DoesNotContain")
|
||||
{
|
||||
if (IsEnumerable(column.FilterPropertyType) && column.FilterPropertyType != typeof(string) && comparison == "DoesNotContain")
|
||||
{
|
||||
whereList.Add($@"!(@{index}).Contains({property})", new object[] { column.GetFilterValue() });
|
||||
}
|
||||
else
|
||||
{
|
||||
whereList.Add($@"!{property}{filterCaseSensitivityOperator}.Contains(@{index}{filterCaseSensitivityOperator})", new object[] { column.GetFilterValue() });
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
else if (!(IsEnumerable(column.FilterPropertyType) && column.FilterPropertyType != typeof(string)))
|
||||
{
|
||||
whereList.Add($@"{property}{filterCaseSensitivityOperator} {comparison} @{index}{filterCaseSensitivityOperator}", new object[] { column.GetFilterValue() });
|
||||
index++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var secondComparison = LinqFilterOperators[column.GetSecondFilterOperator()];
|
||||
|
||||
if (IsEnumerable(column.FilterPropertyType) && column.FilterPropertyType != typeof(string) &&
|
||||
(comparison == "Contains" || comparison == "DoesNotContain") &&
|
||||
(secondComparison == "Contains" || secondComparison == "DoesNotContain"))
|
||||
{
|
||||
var firstFilter = $@"{(comparison == "DoesNotContain" ? "!" : "")}(@{index}).Contains({property})";
|
||||
index++;
|
||||
|
||||
var secondFilter = $@"{(secondComparison == "DoesNotContain" ? "!" : "")}(@{index}).Contains({property})";
|
||||
index++;
|
||||
|
||||
whereList.Add($@"({firstFilter} {booleanOperator} {secondFilter})", new object[] { column.GetFilterValue(), column.GetSecondFilterValue() });
|
||||
}
|
||||
else
|
||||
{
|
||||
var firstFilter = comparison == "StartsWith" || comparison == "EndsWith" || comparison == "Contains" ?
|
||||
$@"{property}{filterCaseSensitivityOperator}.{comparison}(@{index}{filterCaseSensitivityOperator})" :
|
||||
comparison == "DoesNotContain" ? $@"!{property}{filterCaseSensitivityOperator}.Contains(@{index}{filterCaseSensitivityOperator})" :
|
||||
$@"{property}{filterCaseSensitivityOperator} {comparison} @{index}{filterCaseSensitivityOperator}";
|
||||
index++;
|
||||
|
||||
var secondFilter = secondComparison == "StartsWith" || secondComparison == "EndsWith" || secondComparison == "Contains" ?
|
||||
$@"{property}{filterCaseSensitivityOperator}.{secondComparison}(@{index}{filterCaseSensitivityOperator})" :
|
||||
secondComparison == "DoesNotContain" ? $@"!{property}{filterCaseSensitivityOperator}.Contains(@{index}{filterCaseSensitivityOperator})" :
|
||||
$@"{property}{filterCaseSensitivityOperator} {secondComparison} @{index}{filterCaseSensitivityOperator}";
|
||||
index++;
|
||||
|
||||
whereList.Add($@"({firstFilter} {booleanOperator} {secondFilter})", new object[] { column.GetFilterValue(), column.GetSecondFilterValue() });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return whereList.Keys.Any() ?
|
||||
source.Where(string.Join($" {gridBooleanOperator} ", whereList.Keys), whereList.Values.SelectMany(i => i.ToArray()).ToArray())
|
||||
: source;
|
||||
}
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wheres the specified filters.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="source">The source.</param>
|
||||
/// <param name="dataFilter">The DataFilter.</param>
|
||||
/// <returns>IQueryable<T>.</returns>
|
||||
public static IQueryable<T> Where<T>(this IQueryable<T> source, 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.Where(canFilter).Any())
|
||||
{
|
||||
var index = 0;
|
||||
var filterExpressions = new List<string>();
|
||||
var filterValues = new List<object[]>();
|
||||
|
||||
foreach (var filter in dataFilter.Filters)
|
||||
{
|
||||
AddWhereExpression(canFilter, filter, ref filterExpressions, ref filterValues, ref index, dataFilter);
|
||||
}
|
||||
|
||||
return filterExpressions.Any() ?
|
||||
source.Where(string.Join($" {dataFilter.LogicalFilterOperator.ToString().ToLower()} ", filterExpressions), filterValues.SelectMany(i => i.ToArray()).ToArray())
|
||||
: source;
|
||||
}
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
private static void AddWhereExpression<T>(Func<CompositeFilterDescriptor, bool> canFilter, CompositeFilterDescriptor filter, ref List<string> filterExpressions, ref List<object[]> filterValues, ref int index, RadzenDataFilter<T> dataFilter)
|
||||
{
|
||||
if (filter.Filters != null)
|
||||
{
|
||||
var innerFilterExpressions = new List<string>();
|
||||
|
||||
foreach (var f in filter.Filters)
|
||||
{
|
||||
AddWhereExpression(canFilter, f, ref innerFilterExpressions, ref filterValues, ref index, 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 = PropertyAccess.GetProperty(filter.Property);
|
||||
|
||||
if (property.IndexOf(".") != -1)
|
||||
{
|
||||
property = $"({property})";
|
||||
}
|
||||
|
||||
var column = dataFilter.properties.Where(c => c.Property == filter.Property).FirstOrDefault();
|
||||
if (column == null) return;
|
||||
|
||||
if (column.FilterPropertyType == typeof(string) &&
|
||||
!(filter.FilterOperator == FilterOperator.IsNotNull || filter.FilterOperator == FilterOperator.IsNull
|
||||
|| filter.FilterOperator == FilterOperator.IsEmpty || filter.FilterOperator == FilterOperator.IsNotEmpty))
|
||||
{
|
||||
property = $@"({property} == null ? """" : {property})";
|
||||
}
|
||||
|
||||
string filterCaseSensitivityOperator = column.FilterPropertyType == typeof(string)
|
||||
&& filter.FilterOperator != FilterOperator.IsNotNull && filter.FilterOperator != FilterOperator.IsNull
|
||||
&& filter.FilterOperator != FilterOperator.IsEmpty && filter.FilterOperator != FilterOperator.IsNotEmpty
|
||||
&& dataFilter.FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ? ".ToLower()" : "";
|
||||
|
||||
|
||||
var comparison = LinqFilterOperators[filter.FilterOperator];
|
||||
|
||||
if (comparison == "StartsWith" || comparison == "EndsWith" || comparison == "Contains")
|
||||
{
|
||||
if (column.FilterPropertyType == typeof(string) && filter.FilterValue == null)
|
||||
{
|
||||
filter.FilterValue = "";
|
||||
}
|
||||
|
||||
if (IsEnumerable(column.FilterPropertyType) && column.FilterPropertyType != typeof(string) && comparison == "Contains")
|
||||
{
|
||||
filterExpressions.Add($@"(@{index}).Contains({property})");
|
||||
filterValues.Add(new object[] { filter.FilterValue });
|
||||
}
|
||||
else
|
||||
{
|
||||
filterExpressions.Add($@"{property}{filterCaseSensitivityOperator}.{comparison}(@{index}{filterCaseSensitivityOperator})");
|
||||
filterValues.Add(new object[] { filter.FilterValue });
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
else if (comparison == "DoesNotContain")
|
||||
{
|
||||
if (column.FilterPropertyType == typeof(string) && filter.FilterValue == null)
|
||||
{
|
||||
filter.FilterValue = "";
|
||||
}
|
||||
|
||||
if (IsEnumerable(column.FilterPropertyType) && column.FilterPropertyType != typeof(string) && comparison == "DoesNotContain")
|
||||
{
|
||||
filterExpressions.Add($@"!(@{index}).Contains({property})");
|
||||
filterValues.Add(new object[] { filter.FilterValue });
|
||||
}
|
||||
else
|
||||
{
|
||||
filterExpressions.Add($@"!{property}{filterCaseSensitivityOperator}.Contains(@{index}{filterCaseSensitivityOperator})");
|
||||
filterValues.Add(new object[] { filter.FilterValue });
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
else if (!(IsEnumerable(column.FilterPropertyType) && column.FilterPropertyType != typeof(string)))
|
||||
{
|
||||
filterExpressions.Add($@"{property}{filterCaseSensitivityOperator} {comparison} @{index}{filterCaseSensitivityOperator}");
|
||||
filterValues.Add(new object[] { filter.FilterValue });
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ases the o data enumerable.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="source">The source.</param>
|
||||
/// <returns>ODataEnumerable<T>.</returns>
|
||||
public static ODataEnumerable<T> AsODataEnumerable<T>(this IEnumerable<T> source)
|
||||
{
|
||||
return new ODataEnumerable<T>(source);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Selects the many recursive.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="source">The source.</param>
|
||||
/// <param name="selector">The selector.</param>
|
||||
/// <returns>IEnumerable<T>.</returns>
|
||||
public static IEnumerable<T> SelectManyRecursive<T>(this IEnumerable<T> source, Func<T, IEnumerable<T>> selector)
|
||||
{
|
||||
var result = source.SelectMany(selector);
|
||||
if (!result.Any())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
return result.Concat(result.SelectManyRecursive(selector));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
105
Radzen.Blazor/README.md
Normal file
105
Radzen.Blazor/README.md
Normal file
@@ -0,0 +1,105 @@
|
||||
## 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.
|
||||
|
||||

|
||||
|
||||
## Why choose Radzen Blazor Components?
|
||||
|
||||
### :sparkles: Free
|
||||
|
||||
Radzen Blazor Components are open source and free for commercial use. You can install them from [nuget](https://www.nuget.org/packages/Radzen.Blazor) or build your own copy from source.
|
||||
|
||||
Paid support is available as part of the [Radzen Professional subscription](https://www.radzen.com/blazor-studio/pricing/).
|
||||
|
||||
### :computer: Native
|
||||
|
||||
The components are implemented in C# and take full advantage of the Blazor framework. They do not depend on or wrap existing JavaScript frameworks or libraries.
|
||||
|
||||
Blazor Server and Blazor WebAssembly are fully supported.
|
||||
|
||||
### :seedling: Growing
|
||||
|
||||
We add new components and features on a regular basis.
|
||||
|
||||
Short development cycle. We release as soon as new stuff is available. No more quarterly releases.
|
||||
|
||||
## Support exceeding your expectations
|
||||
|
||||
### :speech_balloon: Community Support
|
||||
Everybody is welcome to visit the [Radzen Community forum](https://forum.radzen.com/). Join the growing community and participate in the discussions!
|
||||
|
||||
### :dart: Dedicated Support
|
||||
|
||||
The Radzen team monitors the forum threads, but does not guarantee a response to every question. For guaranteed responses you may consider the dedicated support option.
|
||||
|
||||
Dedicated support for the Radzen Blazor Components is available as part of the [Radzen Professional subscription](https://www.radzen.com/blazor-studio/pricing/).
|
||||
|
||||
Our flagship product [Radzen Blazor Studio](https://www.radzen.com/blazor-studio/) provides tons of productivity features for Blazor developers:
|
||||
- An industry-leading WYSIWYG Blazor design time canvas
|
||||
- Scaffolding a complete CRUD applications from a database
|
||||
- Built-in security - authentication and authorization
|
||||
- Visual Studio Code and Professional support
|
||||
- Deployment to IIS and Azure
|
||||
- Dedicated support with 24 hour guaranteed response time
|
||||
|
||||
## Get started with Radzen Blazor Components
|
||||
|
||||
### 1. Install
|
||||
|
||||
Radzen Blazor Components are distributed as a [Radzen.Blazor nuget package](https://www.nuget.org/packages/Radzen.Blazor). You can add them to your project in one of the following ways
|
||||
- Install the package from command line by running `dotnet add package Radzen.Blazor`
|
||||
- Add the project from the Visual Nuget Package Manager
|
||||
- Manually edit the .csproj file and add a project reference
|
||||
|
||||
### 2. Import the namespace
|
||||
|
||||
Open the `_Imports.razor` file of your Blazor application and add this line `@using Radzen.Blazor`.
|
||||
|
||||
### 3. Include a theme
|
||||
Radzen Blazor components come with five free themes: Material, Standard, Default, Dark, Software and Humanistic.
|
||||
|
||||
To use a theme
|
||||
1. Pick a theme. The [online demos](https://blazor.radzen.com/colors) allow you to preview the available options via the theme dropdown located in the header. The Material theme is currently selected by default.
|
||||
1. Include the theme CSS file in your Blazor application. Open `Pages\_Layout.cshtml` (Blazor Server .NET 6), `Pages\_Host.cshtml` (Blazor Server .NET 7) or `wwwroot/index.html` (Blazor WebAssembly) and include a theme CSS file by adding this snippet
|
||||
```html
|
||||
<link rel="stylesheet" href="_content/Radzen.Blazor/css/material-base.css">
|
||||
```
|
||||
|
||||
To include a different theme (i.e. Standard) just change the name of the CSS file:
|
||||
```
|
||||
<link rel="stylesheet" href="_content/Radzen.Blazor/css/standard-base.css">
|
||||
```
|
||||
|
||||
### 4. Include Radzen.Blazor.js
|
||||
|
||||
Open `Pages\_Layout.cshtml` (Blazor Server .NET 6), `Pages\_Host.cshtml` (Blazor Server .NET 7) or `wwwroot/index.html` (Blazor WebAssembly) and include this snippet:
|
||||
|
||||
```html
|
||||
<script src="_content/Radzen.Blazor/Radzen.Blazor.js"></script>
|
||||
```
|
||||
|
||||
### 5. Use a component
|
||||
Use any Radzen Blazor component by typing its tag name in a Blazor page e.g.
|
||||
```html
|
||||
<RadzenButton Text="Hi"></RadzenButton>
|
||||
```
|
||||
|
||||
#### Data-binding a property
|
||||
```razor
|
||||
<RadzenButton Text=@text />
|
||||
<RadzenTextBox @bind-Value=@text />
|
||||
@code {
|
||||
string text = "Hi";
|
||||
}
|
||||
```
|
||||
|
||||
#### Handing events
|
||||
|
||||
```razor
|
||||
<RadzenButton Click="@ButtonClicked" Text="Hi"></RadzenButton>
|
||||
@code {
|
||||
void ButtonClicked()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -1,78 +1,75 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Razor">
|
||||
<PropertyGroup>
|
||||
<NoWarn>BL9993</NoWarn>
|
||||
<TargetFrameworks>netstandard2.1;net5.0</TargetFrameworks>
|
||||
<TargetFrameworks>netstandard2.1;net5.0;net6.0;net7.0</TargetFrameworks>
|
||||
<RazorLangVersion>3.0</RazorLangVersion>
|
||||
<LangVersion>7.3</LangVersion>
|
||||
<OutputType>Library</OutputType>
|
||||
<IsPackable>true</IsPackable>
|
||||
<PackageId>Radzen.Blazor</PackageId>
|
||||
<Product>Radzen.Blazor</Product>
|
||||
<Version>3.1.9</Version>
|
||||
<Version>4.3.9</Version>
|
||||
<Copyright>Radzen Ltd.</Copyright>
|
||||
<Authors>Radzen Ltd.</Authors>
|
||||
<Description>Native Blazor UI components by Radzen Ltd.</Description>
|
||||
<PackageTags>blazor blazor-component blazor-grid blazor-datagrid</PackageTags>
|
||||
<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>
|
||||
<PackageTags>blazor material design fluent fluentui components datagrid scheduler charts</PackageTags>
|
||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||
<PackageProjectUrl>https://www.radzen.com</PackageProjectUrl>
|
||||
<PackageIcon>icon.png</PackageIcon>
|
||||
<PackageLicenseFile>LICENSE.txt</PackageLicenseFile>
|
||||
<Title>Radzen Components for Blazor</Title>
|
||||
<RepositoryUrl>https://github.com/radzenhq/radzen-blazor</RepositoryUrl>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="LibSassBuilder" Version="2.0.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components" Condition="'$(TargetFramework)' == 'netstandard2.1'" Version="3.1.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Condition="'$(TargetFramework)' == 'netstandard2.1'" Version="3.1.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components" Condition="'$(TargetFramework)' == 'net5.0'" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Condition="'$(TargetFramework)' == 'net5.0'" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
|
||||
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.2.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components" Condition="'$(TargetFramework)' == 'net6.0'" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Condition="'$(TargetFramework)' == 'net6.0'" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components" Condition="'$(TargetFramework)' == 'net7.0'" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Condition="'$(TargetFramework)' == 'net7.0'" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
|
||||
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.2.22" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="LICENSE.txt" Pack="true" PackagePath="" />
|
||||
<None Include="icon.png" Pack="true" PackagePath="" />
|
||||
<None Include="LICENSE.txt" Pack="true" PackagePath="" />
|
||||
<None Include="icon.png" Pack="true" PackagePath="" />
|
||||
<None Include="README.md" Pack="true" PackagePath="\"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="LinkerConfig.xml">
|
||||
<LogicalName>$(MSBuildProjectName).xml</LogicalName>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="LinkerConfig.xml">
|
||||
<LogicalName>$(MSBuildProjectName).xml</LogicalName>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
|
||||
<UsingTask
|
||||
TaskName="RemoveSourceMap"
|
||||
TaskFactory="RoslynCodeTaskFactory"
|
||||
AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll" >
|
||||
<Task>
|
||||
<Using Namespace="System"/>
|
||||
<Using Namespace="System.IO"/>
|
||||
<Using Namespace="System.Text"/>
|
||||
<Code Type="Fragment" Language="cs">
|
||||
<![CDATA[
|
||||
foreach (var file in Directory.EnumerateFiles("./wwwroot/css", "*.css"))
|
||||
{
|
||||
File.WriteAllText(file, File.ReadAllText(file).Replace("/*# sourceMappingURL=themes" + Path.DirectorySeparatorChar + Path.GetFileName(file) + ".map */", ""), Encoding.UTF8);
|
||||
}
|
||||
]]>
|
||||
</Code>
|
||||
</Task>
|
||||
</UsingTask>
|
||||
|
||||
<Target Name="ToolRestore" BeforeTargets="PreBuildEvent">
|
||||
<Exec Command="dotnet tool restore" StandardOutputImportance="high" />
|
||||
|
||||
<PropertyGroup>
|
||||
<LibSassOutputStyle>expanded</LibSassOutputStyle>
|
||||
<EnableDefaultSassItems>false</EnableDefaultSassItems>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Sass Include="$(MSBuildProjectDirectory)/themes/*.scss" Exclude="$(MSBuildProjectDirectory)/themes/_*.scss" Condition="'$(TargetFramework)' == 'net6.0'" />
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="Sass" BeforeTargets="BeforeBuild" Condition="'$(TargetFramework)' == 'net6.0'">
|
||||
<PropertyGroup>
|
||||
<_SassFileList>@(Sass->'"%(FullPath)"', ' ')</_SassFileList>
|
||||
<LibSassBuilderArgs>files $(_SassFileList) --outputstyle $(LibSassOutputStyle) --level $(LibSassOutputLevel)</LibSassBuilderArgs>
|
||||
</PropertyGroup>
|
||||
<Message Text="$(LibSassBuilderArgs)" Importance="$(LibSassMessageLevel)" />
|
||||
<Message Text="Converted SassFile list to argument" Importance="$(LibSassMessageLevel)" />
|
||||
</Target>
|
||||
<Target Name="PreBuild" AfterTargets="ToolRestore">
|
||||
<Exec Command="dotnet tool run webcompiler -r themes -o wwwroot/css -z disable -m disable -p disable" StandardOutputImportance="high" />
|
||||
|
||||
<Target Name="MoveCss" AfterTargets="AfterCompile" Condition="'$(TargetFramework)' == 'net6.0'" >
|
||||
<ItemGroup>
|
||||
<CssFiles Include="$(MSBuildProjectDirectory)\themes\*.css" />
|
||||
<CssFile Include="$(MSBuildProjectDirectory)/themes/*.css" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BootstrapFiles Include="$(MSBuildProjectDirectory)\wwwroot\css\bootstrap\**\*.*" />
|
||||
</ItemGroup>
|
||||
<Delete Files="@(CssFiles)" />
|
||||
<Delete Files="@(BootstrapFiles)" />
|
||||
<RemoveDir Directories="$(MSBuildProjectDirectory)\wwwroot\css\bootstrap" />
|
||||
<RemoveSourceMap />
|
||||
<Move SourceFiles="@(CssFile)" DestinationFolder="$(MSBuildProjectDirectory)/wwwroot/css/" />
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
@@ -10,14 +10,14 @@
|
||||
}
|
||||
@if (Visible)
|
||||
{
|
||||
<div @ref="@Element" role="tablist" @attributes="Attributes" class="@GetCssClass()" id="@GetId()">
|
||||
<div @ref="@Element" role="tablist" style=@Style @attributes="Attributes" class="@GetCssClass()" id="@GetId()">
|
||||
@for (var i = 0; i < items.Count; i++)
|
||||
{
|
||||
var item = items[i];
|
||||
if (!item.Visible)
|
||||
continue;
|
||||
|
||||
<div class="rz-accordion-header rz-state-active" @attributes="item.Attributes" style="@item.Style">
|
||||
<div @ref="@item.Element" id="@item.GetItemId()" @attributes="item.Attributes" class="@item.GetItemCssClass()" style="@item.Style">
|
||||
<a @onclick="@((args) => SelectItem(item))" href="javascript:void(0)" role="tab" tabindex="0"
|
||||
id="@($"rz-accordiontab-{items.IndexOf(item)}")" aria-controls="@($"rz-accordiontab-{items.IndexOf(item)}-content")" aria-expanded="true">
|
||||
@if (IsSelected(i, item))
|
||||
@@ -49,112 +49,4 @@
|
||||
}
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
@code {
|
||||
protected override string GetComponentCssClass()
|
||||
{
|
||||
return "rz-accordion";
|
||||
}
|
||||
|
||||
[Parameter]
|
||||
public bool Multiple { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public int SelectedIndex { get; set; } = 0;
|
||||
|
||||
[Parameter]
|
||||
public EventCallback<int> Expand { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public EventCallback<int> Collapse { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public RenderFragment Items { get; set; }
|
||||
|
||||
List<RadzenAccordionItem> items = new List<RadzenAccordionItem>();
|
||||
|
||||
public void AddItem(RadzenAccordionItem item)
|
||||
{
|
||||
if (items.IndexOf(item) == -1)
|
||||
{
|
||||
if (item.Selected)
|
||||
{
|
||||
SelectedIndex = items.Count;
|
||||
if (!Multiple)
|
||||
{
|
||||
expandedIdexes.Clear();
|
||||
}
|
||||
|
||||
if (!expandedIdexes.Contains(SelectedIndex))
|
||||
{
|
||||
expandedIdexes.Add(SelectedIndex);
|
||||
}
|
||||
}
|
||||
|
||||
items.Add(item);
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveItem(RadzenAccordionItem item)
|
||||
{
|
||||
if (items.Contains(item))
|
||||
{
|
||||
items.Remove(item);
|
||||
try { InvokeAsync(StateHasChanged); } catch { }
|
||||
}
|
||||
}
|
||||
|
||||
internal void Refresh()
|
||||
{
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
protected bool IsSelected(int index, RadzenAccordionItem item)
|
||||
{
|
||||
return expandedIdexes.Contains(index);
|
||||
}
|
||||
|
||||
List<int> expandedIdexes = new List<int>();
|
||||
|
||||
internal async System.Threading.Tasks.Task SelectItem(RadzenAccordionItem item)
|
||||
{
|
||||
await CollapseAll(item);
|
||||
|
||||
var itemIndex = items.IndexOf(item);
|
||||
if (!expandedIdexes.Contains(itemIndex))
|
||||
{
|
||||
expandedIdexes.Add(itemIndex);
|
||||
await Expand.InvokeAsync(itemIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
expandedIdexes.Remove(itemIndex);
|
||||
await Collapse.InvokeAsync(itemIndex);
|
||||
}
|
||||
|
||||
if (!Multiple)
|
||||
{
|
||||
SelectedIndex = itemIndex;
|
||||
}
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
async System.Threading.Tasks.Task CollapseAll(RadzenAccordionItem item)
|
||||
{
|
||||
if (!Multiple && items.Count > 1)
|
||||
{
|
||||
foreach (var i in items.Where(i => i != item))
|
||||
{
|
||||
var itemIndex = items.IndexOf(i);
|
||||
if (expandedIdexes.Contains(itemIndex))
|
||||
{
|
||||
expandedIdexes.Remove(itemIndex);
|
||||
await Collapse.InvokeAsync(items.IndexOf(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
173
Radzen.Blazor/RadzenAccordion.razor.cs
Normal file
173
Radzen.Blazor/RadzenAccordion.razor.cs
Normal file
@@ -0,0 +1,173 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// RadzenAccordion component.
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// <RadzenAccordion>
|
||||
/// <Items>
|
||||
/// <RadzenAccordionItem Text="Orders" Icon="account_balance_wallet">
|
||||
/// Details for Orders
|
||||
/// </RadzenAccordionItem>
|
||||
/// <RadzenAccordionItem Text="Employees" Icon="account_box">
|
||||
/// Details for Employees
|
||||
/// </RadzenAccordionItem>
|
||||
/// </Items>
|
||||
/// </RadzenAccordion>
|
||||
/// </code>
|
||||
/// </example>
|
||||
public partial class RadzenAccordion : RadzenComponent
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override string GetComponentCssClass()
|
||||
{
|
||||
return "rz-accordion";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether multiple items can be expanded.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if multiple items can be expanded; otherwise, <c>false</c>.</value>
|
||||
[Parameter]
|
||||
public bool Multiple { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the index of the selected item.
|
||||
/// </summary>
|
||||
/// <value>The index of the selected item.</value>
|
||||
[Parameter]
|
||||
public int SelectedIndex { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a callback raised when the item is expanded.
|
||||
/// </summary>
|
||||
/// <value>The expand.</value>
|
||||
[Parameter]
|
||||
public EventCallback<int> Expand { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a callback raised when the item is collapsed.
|
||||
/// </summary>
|
||||
/// <value>The collapse.</value>
|
||||
[Parameter]
|
||||
public EventCallback<int> Collapse { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the items.
|
||||
/// </summary>
|
||||
/// <value>The items.</value>
|
||||
[Parameter]
|
||||
public RenderFragment Items { get; set; }
|
||||
|
||||
List<RadzenAccordionItem> items = new List<RadzenAccordionItem>();
|
||||
|
||||
/// <summary>
|
||||
/// Adds the item.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
public void AddItem(RadzenAccordionItem item)
|
||||
{
|
||||
if (items.IndexOf(item) == -1)
|
||||
{
|
||||
if (item.Selected)
|
||||
{
|
||||
SelectedIndex = items.Count;
|
||||
if (!Multiple)
|
||||
{
|
||||
expandedIdexes.Clear();
|
||||
}
|
||||
|
||||
if (!expandedIdexes.Contains(SelectedIndex))
|
||||
{
|
||||
expandedIdexes.Add(SelectedIndex);
|
||||
}
|
||||
}
|
||||
|
||||
items.Add(item);
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes the item.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
public void RemoveItem(RadzenAccordionItem item)
|
||||
{
|
||||
if (items.Contains(item))
|
||||
{
|
||||
items.Remove(item);
|
||||
if (!disposed)
|
||||
{
|
||||
try { InvokeAsync(StateHasChanged); } catch { }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Refreshes this instance.
|
||||
/// </summary>
|
||||
internal void Refresh()
|
||||
{
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the specified index is selected.
|
||||
/// </summary>
|
||||
/// <param name="index">The index.</param>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <returns><c>true</c> if the specified index is selected; otherwise, <c>false</c>.</returns>
|
||||
protected bool IsSelected(int index, RadzenAccordionItem item)
|
||||
{
|
||||
return expandedIdexes.Contains(index);
|
||||
}
|
||||
|
||||
List<int> expandedIdexes = new List<int>();
|
||||
|
||||
internal async System.Threading.Tasks.Task SelectItem(RadzenAccordionItem item)
|
||||
{
|
||||
await CollapseAll(item);
|
||||
|
||||
var itemIndex = items.IndexOf(item);
|
||||
if (!expandedIdexes.Contains(itemIndex))
|
||||
{
|
||||
expandedIdexes.Add(itemIndex);
|
||||
await Expand.InvokeAsync(itemIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
expandedIdexes.Remove(itemIndex);
|
||||
await Collapse.InvokeAsync(itemIndex);
|
||||
}
|
||||
|
||||
if (!Multiple)
|
||||
{
|
||||
SelectedIndex = itemIndex;
|
||||
}
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
async System.Threading.Tasks.Task CollapseAll(RadzenAccordionItem item)
|
||||
{
|
||||
if (!Multiple && items.Count > 1)
|
||||
{
|
||||
foreach (var i in items.Where(i => i != item))
|
||||
{
|
||||
var itemIndex = items.IndexOf(i);
|
||||
if (expandedIdexes.Contains(itemIndex))
|
||||
{
|
||||
expandedIdexes.Remove(itemIndex);
|
||||
await Collapse.InvokeAsync(items.IndexOf(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
129
Radzen.Blazor/RadzenAccordionItem.cs
Normal file
129
Radzen.Blazor/RadzenAccordionItem.cs
Normal file
@@ -0,0 +1,129 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// Class RadzenAccordionItem.
|
||||
/// </summary>
|
||||
public partial class RadzenAccordionItem : RadzenComponent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the text.
|
||||
/// </summary>
|
||||
/// <value>The text.</value>
|
||||
[Parameter]
|
||||
public string Text { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the icon.
|
||||
/// </summary>
|
||||
/// <value>The icon.</value>
|
||||
[Parameter]
|
||||
public string Icon { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this <see cref="RadzenAccordionItem"/> is selected.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if selected; otherwise, <c>false</c>.</value>
|
||||
[Parameter]
|
||||
public bool Selected { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the child content.
|
||||
/// </summary>
|
||||
/// <value>The child content.</value>
|
||||
[Parameter]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
|
||||
|
||||
bool _visible = true;
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this <see cref="RadzenAccordionItem"/> is visible.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if visible; otherwise, <c>false</c>.</value>
|
||||
[Parameter]
|
||||
public override bool Visible
|
||||
{
|
||||
get
|
||||
{
|
||||
return _visible;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (_visible != value)
|
||||
{
|
||||
_visible = value;
|
||||
if (Accordion != null)
|
||||
{
|
||||
Accordion.Refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RadzenAccordion _accordion;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the accordion.
|
||||
/// </summary>
|
||||
/// <value>The accordion.</value>
|
||||
[CascadingParameter]
|
||||
public RadzenAccordion Accordion
|
||||
{
|
||||
get
|
||||
{
|
||||
return _accordion;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (_accordion != value)
|
||||
{
|
||||
_accordion = value;
|
||||
_accordion.AddItem(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set parameters as an asynchronous operation.
|
||||
/// </summary>
|
||||
/// <param name="parameters">The parameters.</param>
|
||||
/// <returns>A Task representing the asynchronous operation.</returns>
|
||||
public override async Task SetParametersAsync(ParameterView parameters)
|
||||
{
|
||||
if (parameters.DidParameterChange(nameof(Selected), Selected))
|
||||
{
|
||||
Accordion?.SelectItem(this);
|
||||
}
|
||||
|
||||
await base.SetParametersAsync(parameters);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disposes this instance.
|
||||
/// </summary>
|
||||
public override void Dispose()
|
||||
{
|
||||
base.Dispose();
|
||||
|
||||
Accordion?.RemoveItem(this);
|
||||
}
|
||||
|
||||
internal string GetItemId()
|
||||
{
|
||||
return GetId();
|
||||
}
|
||||
|
||||
internal string GetItemCssClass()
|
||||
{
|
||||
return GetCssClass();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override string GetComponentCssClass()
|
||||
{
|
||||
return "rz-accordion-header";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
@inherits RadzenComponent
|
||||
@code {
|
||||
[Parameter]
|
||||
public string Text { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string Icon { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public bool Selected { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
|
||||
bool _visible = true;
|
||||
[Parameter]
|
||||
public override bool Visible
|
||||
{
|
||||
get
|
||||
{
|
||||
return _visible;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (_visible != value)
|
||||
{
|
||||
_visible = value;
|
||||
Accordion.Refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RadzenAccordion _accordion;
|
||||
|
||||
[CascadingParameter]
|
||||
public RadzenAccordion Accordion
|
||||
{
|
||||
get
|
||||
{
|
||||
return _accordion;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (_accordion != value)
|
||||
{
|
||||
_accordion = value;
|
||||
_accordion.AddItem(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task SetParametersAsync(ParameterView parameters)
|
||||
{
|
||||
if (parameters.DidParameterChange(nameof(Selected), Selected))
|
||||
{
|
||||
Accordion?.SelectItem(this);
|
||||
}
|
||||
|
||||
await base.SetParametersAsync(parameters);
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
base.Dispose();
|
||||
|
||||
Accordion?.RemoveItem(this);
|
||||
}
|
||||
}
|
||||
81
Radzen.Blazor/RadzenAlert.razor
Normal file
81
Radzen.Blazor/RadzenAlert.razor
Normal file
@@ -0,0 +1,81 @@
|
||||
@inherits RadzenComponentWithChildren
|
||||
@if (GetVisible())
|
||||
{
|
||||
<div @ref="@Element" style="@Style" @attributes="Attributes" class="@GetCssClass()" id="@GetId()" aria-live="polite">
|
||||
<div class="rz-alert-item">
|
||||
@if (ShowIcon)
|
||||
{
|
||||
<RadzenIcon Icon="@getIcon()" Class="rz-alert-icon" />
|
||||
}
|
||||
<div class="rz-alert-message">
|
||||
|
||||
@if (!string.IsNullOrEmpty(Title))
|
||||
{
|
||||
<div class="rz-alert-title">@Title</div>
|
||||
}
|
||||
<div class="rz-alert-content">@ChildContent</div>
|
||||
</div>
|
||||
</div>
|
||||
@if (AllowClose)
|
||||
{
|
||||
if (Shade == Shade.Lighter)
|
||||
{
|
||||
if (AlertStyle == AlertStyle.Primary)
|
||||
{
|
||||
<RadzenButton Click=@Close Icon="close" Variant="Variant.Text" ButtonStyle="ButtonStyle.Primary" Shade="Shade.Dark" Size="@getCloseButtonSize()" />
|
||||
}
|
||||
else if (AlertStyle == AlertStyle.Secondary)
|
||||
{
|
||||
<RadzenButton Click=@Close Icon="close" Variant="Variant.Text" ButtonStyle="ButtonStyle.Secondary" Shade="Shade.Dark" Size="@getCloseButtonSize()" />
|
||||
}
|
||||
else if (AlertStyle == AlertStyle.Light)
|
||||
{
|
||||
<RadzenButton Click=@Close Icon="close" Variant="Variant.Text" ButtonStyle="ButtonStyle.Dark" Shade="Shade.Dark" Size="@getCloseButtonSize()" />
|
||||
}
|
||||
else if (AlertStyle == AlertStyle.Base)
|
||||
{
|
||||
<RadzenButton Click=@Close Icon="close" Variant="Variant.Text" ButtonStyle="ButtonStyle.Dark" Shade="Shade.Dark" Size="@getCloseButtonSize()" />
|
||||
}
|
||||
else if (AlertStyle == AlertStyle.Dark)
|
||||
{
|
||||
<RadzenButton Click=@Close Icon="close" Variant="Variant.Text" ButtonStyle="ButtonStyle.Light" Shade="Shade.Dark" Size="@getCloseButtonSize()" />
|
||||
}
|
||||
else if (AlertStyle == AlertStyle.Success)
|
||||
{
|
||||
<RadzenButton Click=@Close Icon="close" Variant="Variant.Text" ButtonStyle="ButtonStyle.Success" Shade="Shade.Dark" Size="@getCloseButtonSize()" />
|
||||
}
|
||||
else if (AlertStyle == AlertStyle.Danger)
|
||||
{
|
||||
<RadzenButton Click=@Close Icon="close" Variant="Variant.Text" ButtonStyle="ButtonStyle.Danger" Shade="Shade.Dark" Size="@getCloseButtonSize()" />
|
||||
}
|
||||
else if (AlertStyle == AlertStyle.Warning)
|
||||
{
|
||||
<RadzenButton Click=@Close Icon="close" Variant="Variant.Text" ButtonStyle="ButtonStyle.Warning" Shade="Shade.Dark" Size="@getCloseButtonSize()" />
|
||||
}
|
||||
else if (AlertStyle == AlertStyle.Info)
|
||||
{
|
||||
<RadzenButton Click=@Close Icon="close" Variant="Variant.Text" ButtonStyle="ButtonStyle.Info" Shade="Shade.Dark" Size="@getCloseButtonSize()" />
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (AlertStyle == AlertStyle.Light)
|
||||
{
|
||||
<RadzenButton Click=@Close Icon="close" Variant="Variant.Text" ButtonStyle="ButtonStyle.Dark" Size="@getCloseButtonSize()" />
|
||||
}
|
||||
else if (AlertStyle == AlertStyle.Base)
|
||||
{
|
||||
<RadzenButton Click=@Close Icon="close" Variant="Variant.Text" ButtonStyle="ButtonStyle.Dark" Size="@getCloseButtonSize()" />
|
||||
}
|
||||
else if (AlertStyle == AlertStyle.Dark)
|
||||
{
|
||||
<RadzenButton Click=@Close Icon="close" Variant="Variant.Text" ButtonStyle="ButtonStyle.Light" Size="@getCloseButtonSize()" />
|
||||
}
|
||||
else
|
||||
{
|
||||
<RadzenButton Click=@Close Icon="close" Variant="Variant.Text" ButtonStyle="ButtonStyle.Light" Size="@getCloseButtonSize()" />
|
||||
}
|
||||
}
|
||||
}
|
||||
</div>
|
||||
}
|
||||
151
Radzen.Blazor/RadzenAlert.razor.cs
Normal file
151
Radzen.Blazor/RadzenAlert.razor.cs
Normal file
@@ -0,0 +1,151 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Web;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// RadzenAlert component.
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// <RadzenAlert>
|
||||
/// <ChildContent>
|
||||
/// Content
|
||||
/// </ChildContent>
|
||||
/// </RadzenAlert>
|
||||
/// </code>
|
||||
/// </example>
|
||||
public partial class RadzenAlert : RadzenComponentWithChildren
|
||||
{
|
||||
private string getAlertSize()
|
||||
{
|
||||
return Size == AlertSize.Medium ? "md" : Size == AlertSize.Large ? "lg" : Size == AlertSize.Small ? "sm" : "xs";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether close is allowed. Set to <c>true</c> by default.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if close is allowed; otherwise, <c>false</c>.</value>
|
||||
[Parameter]
|
||||
public bool AllowClose { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether icon should be shown. Set to <c>true</c> by default.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if icon is shown; otherwise, <c>false</c>.</value>
|
||||
[Parameter]
|
||||
public bool ShowIcon { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the title.
|
||||
/// </summary>
|
||||
/// <value>The title.</value>
|
||||
[Parameter]
|
||||
public string Title { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the icon.
|
||||
/// </summary>
|
||||
/// <value>The icon.</value>
|
||||
[Parameter]
|
||||
public string Icon { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the severity.
|
||||
/// </summary>
|
||||
/// <value>The severity.</value>
|
||||
[Parameter]
|
||||
public AlertStyle AlertStyle { get; set; } = AlertStyle.Base;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the design variant of the alert.
|
||||
/// </summary>
|
||||
/// <value>The variant of the alert.</value>
|
||||
[Parameter]
|
||||
public Variant Variant { get; set; } = Variant.Filled;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the color shade of the alert.
|
||||
/// </summary>
|
||||
/// <value>The color shade of the alert.</value>
|
||||
[Parameter]
|
||||
public Shade Shade { get; set; } = Shade.Default;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the size.
|
||||
/// </summary>
|
||||
/// <value>The size.</value>
|
||||
[Parameter]
|
||||
public AlertSize Size { get; set; } = AlertSize.Medium;
|
||||
|
||||
ButtonSize getCloseButtonSize()
|
||||
{
|
||||
return Size == AlertSize.ExtraSmall ? ButtonSize.ExtraSmall : ButtonSize.Small;
|
||||
}
|
||||
|
||||
bool? visible;
|
||||
bool GetVisible()
|
||||
{
|
||||
return visible ?? Visible;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override string GetComponentCssClass()
|
||||
{
|
||||
return $"rz-alert rz-alert-{getAlertSize()} rz-variant-{Enum.GetName(typeof(Variant), Variant).ToLowerInvariant()} rz-{Enum.GetName(typeof(AlertStyle), AlertStyle).ToLowerInvariant()} rz-shade-{Enum.GetName(typeof(Shade), Shade).ToLowerInvariant()}";
|
||||
}
|
||||
|
||||
string getIcon()
|
||||
{
|
||||
if (!string.IsNullOrEmpty(Icon))
|
||||
{
|
||||
return Icon;
|
||||
}
|
||||
else if (AlertStyle == AlertStyle.Primary)
|
||||
{
|
||||
return "lightbulb_outline";
|
||||
}
|
||||
else if (AlertStyle == AlertStyle.Secondary)
|
||||
{
|
||||
return "lightbulb_outline";
|
||||
}
|
||||
else if (AlertStyle == AlertStyle.Light)
|
||||
{
|
||||
return "lightbulb_outline";
|
||||
}
|
||||
else if (AlertStyle == AlertStyle.Base)
|
||||
{
|
||||
return "lightbulb_outline";
|
||||
}
|
||||
else if (AlertStyle == AlertStyle.Dark)
|
||||
{
|
||||
return "lightbulb_outline";
|
||||
}
|
||||
else if (AlertStyle == AlertStyle.Success)
|
||||
{
|
||||
return "check_circle_outline";
|
||||
}
|
||||
else if (AlertStyle == AlertStyle.Danger)
|
||||
{
|
||||
return "error_outline";
|
||||
}
|
||||
else if (AlertStyle == AlertStyle.Warning)
|
||||
{
|
||||
return "warning_amber";
|
||||
}
|
||||
else if (AlertStyle == AlertStyle.Info)
|
||||
{
|
||||
return "info_outline";
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
void Close()
|
||||
{
|
||||
visible = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
@if (Visible)
|
||||
{
|
||||
<div @ref="Element" class=@GetCssClass() @attributes=@Attributes style=@Style id="@GetId()">
|
||||
<div @ref="Element" style=@Style @attributes=@Attributes class=@GetCssClass() id="@GetId()">
|
||||
@if (Width.HasValue && Height.HasValue)
|
||||
{
|
||||
<svg style="width: 100%; height: 100%">
|
||||
|
||||
@@ -39,149 +39,3 @@
|
||||
<CascadingValue Value=@this>
|
||||
@ChildContent
|
||||
</CascadingValue>
|
||||
@code {
|
||||
[CascadingParameter]
|
||||
public RadzenArcGauge Gauge { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string Stroke { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public double StrokeWidth { get; set; } = 1;
|
||||
|
||||
[Parameter]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public double TickLength { get; set; } = 10;
|
||||
|
||||
[Parameter]
|
||||
public double MinorTickLength { get; set; } = 5;
|
||||
|
||||
[Parameter]
|
||||
public double TickLabelOffset { get; set; } = 25;
|
||||
|
||||
[Parameter]
|
||||
public string FormatString { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string Fill { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public double Height { get; set; } = 0.2;
|
||||
|
||||
[Parameter]
|
||||
public Func<double, string> Formatter { get; set; } = value => value.ToString();
|
||||
|
||||
[Parameter]
|
||||
public double StartAngle { get; set; } = -90;
|
||||
|
||||
[Parameter]
|
||||
public GaugeTickPosition TickPosition { get; set; } = GaugeTickPosition.None;
|
||||
|
||||
[Parameter]
|
||||
public double EndAngle { get; set; } = 90;
|
||||
|
||||
[Parameter]
|
||||
public double Radius { get; set; } = 1;
|
||||
|
||||
[Parameter]
|
||||
public bool ShowFirstTick { get; set; } = true;
|
||||
|
||||
[Parameter]
|
||||
public bool ShowLastTick { get; set; } = true;
|
||||
|
||||
[Parameter]
|
||||
public bool ShowTickLabels { get; set; } = true;
|
||||
|
||||
[Parameter]
|
||||
public double X { get; set; } = 0.5;
|
||||
|
||||
[Parameter]
|
||||
public double Min { get; set; } = 0;
|
||||
|
||||
[Parameter]
|
||||
public double Max { get; set; } = 100;
|
||||
|
||||
[Parameter]
|
||||
public double Step { get; set; } = 20;
|
||||
|
||||
[Parameter]
|
||||
public double MinorStep { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public double Y { get; set; } = 0.5;
|
||||
|
||||
[Parameter]
|
||||
public double Margin { get; set; } = 16;
|
||||
|
||||
public double CurrentStrokeWidth
|
||||
{
|
||||
get
|
||||
{
|
||||
if (TickPosition == GaugeTickPosition.None)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return StrokeWidth;
|
||||
}
|
||||
}
|
||||
|
||||
public double CurrentRadius
|
||||
{
|
||||
get
|
||||
{
|
||||
var radius = Math.Min(Gauge.Width.Value, Gauge.Height.Value) / 2 - Margin * 2;
|
||||
|
||||
radius *= Radius;
|
||||
|
||||
if (TickPosition == GaugeTickPosition.Outside)
|
||||
{
|
||||
radius -= TextMeasurer.TextWidth(Max.ToString(), 16);
|
||||
}
|
||||
|
||||
return radius;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
double CurrentScaleRadius
|
||||
{
|
||||
get
|
||||
{
|
||||
if (TickPosition == GaugeTickPosition.Inside)
|
||||
{
|
||||
return CurrentRadius - CurrentSize;
|
||||
}
|
||||
|
||||
return CurrentRadius;
|
||||
}
|
||||
}
|
||||
|
||||
public double CurrentSize
|
||||
{
|
||||
get
|
||||
{
|
||||
var radius = Math.Min(Gauge.Width.Value, Gauge.Height.Value) / 2 - Margin * 2;
|
||||
|
||||
if (TickPosition == GaugeTickPosition.Outside)
|
||||
{
|
||||
radius -= TextMeasurer.TextWidth(Max.ToString(), 16);
|
||||
}
|
||||
|
||||
return radius * Height;
|
||||
}
|
||||
}
|
||||
|
||||
public Point CurrentCenter
|
||||
{
|
||||
get
|
||||
{
|
||||
var x = X * Gauge.Width;
|
||||
var y = Y * Gauge.Height;
|
||||
|
||||
return new Point { X = x.Value, Y = y.Value };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
272
Radzen.Blazor/RadzenArcGaugeScale.razor.cs
Normal file
272
Radzen.Blazor/RadzenArcGaugeScale.razor.cs
Normal file
@@ -0,0 +1,272 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Radzen.Blazor.Rendering;
|
||||
using System;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// RadzenArcGaugeScale component.
|
||||
/// </summary>
|
||||
public partial class RadzenArcGaugeScale: ComponentBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the gauge.
|
||||
/// </summary>
|
||||
/// <value>The gauge.</value>
|
||||
[CascadingParameter]
|
||||
public RadzenArcGauge Gauge { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the stroke.
|
||||
/// </summary>
|
||||
/// <value>The stroke.</value>
|
||||
[Parameter]
|
||||
public string Stroke { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the width of the stroke.
|
||||
/// </summary>
|
||||
/// <value>The width of the stroke.</value>
|
||||
[Parameter]
|
||||
public double StrokeWidth { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the child content.
|
||||
/// </summary>
|
||||
/// <value>The child content.</value>
|
||||
[Parameter]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the length of the tick.
|
||||
/// </summary>
|
||||
/// <value>The length of the tick.</value>
|
||||
[Parameter]
|
||||
public double TickLength { get; set; } = 10;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the length of the minor tick.
|
||||
/// </summary>
|
||||
/// <value>The length of the minor tick.</value>
|
||||
[Parameter]
|
||||
public double MinorTickLength { get; set; } = 5;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the tick label offset.
|
||||
/// </summary>
|
||||
/// <value>The tick label offset.</value>
|
||||
[Parameter]
|
||||
public double TickLabelOffset { get; set; } = 25;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the format string.
|
||||
/// </summary>
|
||||
/// <value>The format string.</value>
|
||||
[Parameter]
|
||||
public string FormatString { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the fill.
|
||||
/// </summary>
|
||||
/// <value>The fill.</value>
|
||||
[Parameter]
|
||||
public string Fill { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the height.
|
||||
/// </summary>
|
||||
/// <value>The height.</value>
|
||||
[Parameter]
|
||||
public double Height { get; set; } = 0.2;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the formatter.
|
||||
/// </summary>
|
||||
/// <value>The formatter.</value>
|
||||
[Parameter]
|
||||
public Func<double, string> Formatter { get; set; } = value => value.ToString();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the start angle.
|
||||
/// </summary>
|
||||
/// <value>The start angle.</value>
|
||||
[Parameter]
|
||||
public double StartAngle { get; set; } = -90;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the tick position.
|
||||
/// </summary>
|
||||
/// <value>The tick position.</value>
|
||||
[Parameter]
|
||||
public GaugeTickPosition TickPosition { get; set; } = GaugeTickPosition.None;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the end angle.
|
||||
/// </summary>
|
||||
/// <value>The end angle.</value>
|
||||
[Parameter]
|
||||
public double EndAngle { get; set; } = 90;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the radius.
|
||||
/// </summary>
|
||||
/// <value>The radius.</value>
|
||||
[Parameter]
|
||||
public double Radius { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether first tick is shown.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if first tick is shown; otherwise, <c>false</c>.</value>
|
||||
[Parameter]
|
||||
public bool ShowFirstTick { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether last tick is shown.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if last tick is shown; otherwise, <c>false</c>.</value>
|
||||
[Parameter]
|
||||
public bool ShowLastTick { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to show tick labels.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if tick labels are shown; otherwise, <c>false</c>.</value>
|
||||
[Parameter]
|
||||
public bool ShowTickLabels { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the x.
|
||||
/// </summary>
|
||||
/// <value>The x.</value>
|
||||
[Parameter]
|
||||
public double X { get; set; } = 0.5;
|
||||
|
||||
/// <summary>
|
||||
/// Determines the minimum value.
|
||||
/// </summary>
|
||||
/// <value>The minimum value.</value>
|
||||
[Parameter]
|
||||
public double Min { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Determines the maximum value.
|
||||
/// </summary>
|
||||
/// <value>The maximum value.</value>
|
||||
[Parameter]
|
||||
public double Max { get; set; } = 100;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the step.
|
||||
/// </summary>
|
||||
/// <value>The step.</value>
|
||||
[Parameter]
|
||||
public double Step { get; set; } = 20;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the minor step.
|
||||
/// </summary>
|
||||
/// <value>The minor step.</value>
|
||||
[Parameter]
|
||||
public double MinorStep { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the y.
|
||||
/// </summary>
|
||||
/// <value>The y.</value>
|
||||
[Parameter]
|
||||
public double Y { get; set; } = 0.5;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the margin.
|
||||
/// </summary>
|
||||
/// <value>The margin.</value>
|
||||
[Parameter]
|
||||
public double Margin { get; set; } = 16;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the width of the current stroke.
|
||||
/// </summary>
|
||||
/// <value>The width of the current stroke.</value>
|
||||
public double CurrentStrokeWidth
|
||||
{
|
||||
get
|
||||
{
|
||||
if (TickPosition == GaugeTickPosition.None)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return StrokeWidth;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current radius.
|
||||
/// </summary>
|
||||
/// <value>The current radius.</value>
|
||||
public double CurrentRadius
|
||||
{
|
||||
get
|
||||
{
|
||||
var radius = Math.Min(Gauge.Width.Value, Gauge.Height.Value) / 2 - Margin * 2;
|
||||
|
||||
radius *= Radius;
|
||||
|
||||
if (TickPosition == GaugeTickPosition.Outside)
|
||||
{
|
||||
radius -= TextMeasurer.TextWidth(Max.ToString(), 16);
|
||||
}
|
||||
|
||||
return radius;
|
||||
}
|
||||
}
|
||||
|
||||
double CurrentScaleRadius
|
||||
{
|
||||
get
|
||||
{
|
||||
if (TickPosition == GaugeTickPosition.Inside)
|
||||
{
|
||||
return CurrentRadius - CurrentSize;
|
||||
}
|
||||
|
||||
return CurrentRadius;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current size.
|
||||
/// </summary>
|
||||
/// <value>The current size.</value>
|
||||
public double CurrentSize
|
||||
{
|
||||
get
|
||||
{
|
||||
var radius = Math.Min(Gauge.Width.Value, Gauge.Height.Value) / 2 - Margin * 2;
|
||||
|
||||
if (TickPosition == GaugeTickPosition.Outside)
|
||||
{
|
||||
radius -= TextMeasurer.TextWidth(Max.ToString(), 16);
|
||||
}
|
||||
|
||||
return radius * Height;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current center.
|
||||
/// </summary>
|
||||
/// <value>The current center.</value>
|
||||
public Point CurrentCenter
|
||||
{
|
||||
get
|
||||
{
|
||||
var x = X * Gauge.Width;
|
||||
var y = Y * Gauge.Height;
|
||||
|
||||
return new Point { X = x.Value, Y = y.Value };
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,54 +17,3 @@
|
||||
Size=@Scale.CurrentSize
|
||||
/>
|
||||
</g>
|
||||
@code {
|
||||
[Parameter]
|
||||
public double Value { get; set; }
|
||||
|
||||
[CascadingParameter]
|
||||
public RadzenArcGaugeScale Scale { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string Stroke { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public double StrokeWidth { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string Fill { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public bool ShowValue { get; set; } = true;
|
||||
|
||||
[Parameter]
|
||||
public string FormatString { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public RenderFragment<RadzenArcGaugeScaleValue> Template { get; set; }
|
||||
|
||||
[CascadingParameter]
|
||||
public RadzenArcGauge Gauge { get; set; }
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
base.OnInitialized();
|
||||
|
||||
Gauge.AddValue(this);
|
||||
}
|
||||
public override async Task SetParametersAsync(ParameterView parameters)
|
||||
{
|
||||
var shouldRefresh = false;
|
||||
|
||||
if (parameters.DidParameterChange(nameof(Value), Value) || parameters.DidParameterChange(nameof(ShowValue), ShowValue))
|
||||
{
|
||||
shouldRefresh = true;
|
||||
}
|
||||
|
||||
await base.SetParametersAsync(parameters);
|
||||
|
||||
if (shouldRefresh)
|
||||
{
|
||||
Gauge.Reload();
|
||||
}
|
||||
}
|
||||
}
|
||||
99
Radzen.Blazor/RadzenArcGaugeScaleValue.razor.cs
Normal file
99
Radzen.Blazor/RadzenArcGaugeScaleValue.razor.cs
Normal file
@@ -0,0 +1,99 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// RadzenArcGaugeScaleValue component.
|
||||
/// </summary>
|
||||
public partial class RadzenArcGaugeScaleValue : ComponentBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the value.
|
||||
/// </summary>
|
||||
/// <value>The value.</value>
|
||||
[Parameter]
|
||||
public double Value { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the scale.
|
||||
/// </summary>
|
||||
/// <value>The scale.</value>
|
||||
[CascadingParameter]
|
||||
public RadzenArcGaugeScale Scale { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the stroke.
|
||||
/// </summary>
|
||||
/// <value>The stroke.</value>
|
||||
[Parameter]
|
||||
public string Stroke { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the width of the stroke.
|
||||
/// </summary>
|
||||
/// <value>The width of the stroke.</value>
|
||||
[Parameter]
|
||||
public double StrokeWidth { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the fill.
|
||||
/// </summary>
|
||||
/// <value>The fill.</value>
|
||||
[Parameter]
|
||||
public string Fill { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to show value.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if value is shown; otherwise, <c>false</c>.</value>
|
||||
[Parameter]
|
||||
public bool ShowValue { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the format string.
|
||||
/// </summary>
|
||||
/// <value>The format string.</value>
|
||||
[Parameter]
|
||||
public string FormatString { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the template.
|
||||
/// </summary>
|
||||
/// <value>The template.</value>
|
||||
[Parameter]
|
||||
public RenderFragment<RadzenArcGaugeScaleValue> Template { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the gauge.
|
||||
/// </summary>
|
||||
/// <value>The gauge.</value>
|
||||
[CascadingParameter]
|
||||
public RadzenArcGauge Gauge { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
base.OnInitialized();
|
||||
|
||||
Gauge.AddValue(this);
|
||||
}
|
||||
/// <inheritdoc />
|
||||
public override async Task SetParametersAsync(ParameterView parameters)
|
||||
{
|
||||
var shouldRefresh = false;
|
||||
|
||||
if (parameters.DidParameterChange(nameof(Value), Value) || parameters.DidParameterChange(nameof(ShowValue), ShowValue))
|
||||
{
|
||||
shouldRefresh = true;
|
||||
}
|
||||
|
||||
await base.SetParametersAsync(parameters);
|
||||
|
||||
if (shouldRefresh)
|
||||
{
|
||||
Gauge.Reload();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,64 +6,6 @@
|
||||
@ChildContent
|
||||
</CascadingValue>
|
||||
@code {
|
||||
[Parameter]
|
||||
public string Stroke { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string Fill { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public double StrokeWidth { get; set; } = 2;
|
||||
|
||||
[Parameter]
|
||||
public LineType LineType { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public bool Smooth { get; set; }
|
||||
|
||||
public override string Color
|
||||
{
|
||||
get
|
||||
{
|
||||
return Stroke;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool Contains(double x, double y)
|
||||
{
|
||||
var tolerance = 25;
|
||||
var category = ComposeCategory(Chart.CategoryScale);
|
||||
var value = ComposeValue(Chart.ValueScale);
|
||||
|
||||
var points = Items.Select(item => new Point { X = category(item), Y = value(item) }).ToArray();
|
||||
|
||||
var valueTicks = Chart.ValueScale.Ticks(Chart.ValueAxis.TickDistance);
|
||||
var axisY = Chart.ValueScale.Scale(Math.Max(0, valueTicks.Start));
|
||||
|
||||
if (points.Any())
|
||||
{
|
||||
for (var i = 0; i < points.Length - 1; i++)
|
||||
{
|
||||
var start = points[i];
|
||||
var end = points[i + 1];
|
||||
|
||||
var polygon = new[] {
|
||||
new Point { X = start.X, Y = start.Y - tolerance },
|
||||
new Point { X = end.X, Y = end.Y - tolerance },
|
||||
new Point { X = end.X, Y = axisY },
|
||||
new Point { X = start.X, Y = axisY },
|
||||
};
|
||||
|
||||
if (InsidePolygon(new Point { X = x, Y = y }, polygon))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override RenderFragment Render(ScaleBase categoryScale, ScaleBase valueScale)
|
||||
{
|
||||
var category = ComposeCategory(categoryScale);
|
||||
|
||||
137
Radzen.Blazor/RadzenAreaSeries.razor.cs
Normal file
137
Radzen.Blazor/RadzenAreaSeries.razor.cs
Normal file
@@ -0,0 +1,137 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Radzen.Blazor.Rendering;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// Renders area series in <see cref="RadzenChart" />.
|
||||
/// </summary>
|
||||
public partial class RadzenAreaSeries<TItem> : CartesianSeries<TItem>
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies the color of the line.
|
||||
/// </summary>
|
||||
/// <value>The stroke.</value>
|
||||
[Parameter]
|
||||
public string Stroke { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the fill (background color) of the area series.
|
||||
/// </summary>
|
||||
/// <value>The fill.</value>
|
||||
[Parameter]
|
||||
public string Fill { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the pixel width of the line. Set to <c>2</c> by default.
|
||||
/// </summary>
|
||||
/// <value>The width of the stroke.</value>
|
||||
[Parameter]
|
||||
public double StrokeWidth { get; set; } = 2;
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the line type.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public LineType LineType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Specifies whether to render a smooth line. Set to <c>false</c> by default.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public bool Smooth { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Color
|
||||
{
|
||||
get
|
||||
{
|
||||
return Stroke;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override string TooltipStyle(TItem item)
|
||||
{
|
||||
var style = base.TooltipStyle(item);
|
||||
|
||||
var index = Items.IndexOf(item);
|
||||
|
||||
if (index >= 0)
|
||||
{
|
||||
var color = Fill;
|
||||
|
||||
if (color != null)
|
||||
{
|
||||
style = $"{style}; border-color: {color};";
|
||||
}
|
||||
}
|
||||
|
||||
return style;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool Contains(double x, double y, double tolerance)
|
||||
{
|
||||
var category = ComposeCategory(Chart.CategoryScale);
|
||||
var value = ComposeValue(Chart.ValueScale);
|
||||
|
||||
var points = Items.Select(item => new Point { X = category(item), Y = value(item) }).ToArray();
|
||||
|
||||
var valueTicks = Chart.ValueScale.Ticks(Chart.ValueAxis.TickDistance);
|
||||
var axisY = Chart.ValueScale.Scale(Math.Max(0, valueTicks.Start));
|
||||
|
||||
if (points.Length > 0)
|
||||
{
|
||||
if (points.Length == 1)
|
||||
{
|
||||
var point = points[0];
|
||||
|
||||
var polygon = new[] {
|
||||
new Point { X = point.X - tolerance, Y = point.Y - tolerance },
|
||||
new Point { X = point.X - tolerance, Y = point.Y + tolerance },
|
||||
new Point { X = point.X + tolerance, Y = point.Y + tolerance },
|
||||
new Point { X = point.X + tolerance, Y = point.Y - tolerance },
|
||||
};
|
||||
|
||||
if (InsidePolygon(new Point { X = x, Y = y }, polygon))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (var i = 0; i < points.Length - 1; i++)
|
||||
{
|
||||
var start = points[i];
|
||||
var end = points[i + 1];
|
||||
|
||||
var polygon = new[]
|
||||
{
|
||||
new Point { X = start.X, Y = start.Y - tolerance },
|
||||
new Point { X = end.X, Y = end.Y - tolerance },
|
||||
new Point { X = end.X, Y = axisY },
|
||||
new Point { X = start.X, Y = axisY },
|
||||
};
|
||||
|
||||
if (InsidePolygon(new Point { X = x, Y = y }, polygon))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override IEnumerable<ChartDataLabel> GetDataLabels(double offsetX, double offsetY)
|
||||
{
|
||||
return base.GetDataLabels(offsetX, offsetY - 16);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
@using Radzen
|
||||
@using Radzen.Blazor.Rendering
|
||||
@using System.Collections
|
||||
@using System.Linq.Dynamic.Core
|
||||
@using Microsoft.AspNetCore.Components.Forms
|
||||
@@ -9,20 +10,39 @@
|
||||
@if (Visible)
|
||||
{
|
||||
<div @ref="@Element" style="@($"{Style};display:inline-block;")" @attributes="Attributes" class="@GetCssClass()" id="@GetId()">
|
||||
<span class="rz-autocomplete" style="width:100%">
|
||||
@if (Multiline)
|
||||
{
|
||||
<textarea @ref="@search" @onkeydown="@OnFilterKeyPress" value="@Value" disabled="@Disabled"
|
||||
oninput="@OpenScript()" tabindex="@(Disabled ? "-1" : $"{TabIndex}")" @onchange="@OnChange"
|
||||
aria-autocomplete="list" aria-haspopup="true" autocomplete="off" role="combobox"
|
||||
class="@InputClassList"
|
||||
id="@Name" aria-expanded="true" placeholder="@Placeholder" />
|
||||
}
|
||||
else
|
||||
{
|
||||
<input @ref="@search" @onkeydown="@OnFilterKeyPress" value="@Value" disabled="@Disabled"
|
||||
onfocus="@OpenScript()" onkeypress="@OpenScript()" tabindex="@TabIndex" @onchange="@OnChange"
|
||||
aria-autocomplete="list" aria-haspopup="true" autocomplete="off" role="combobox"
|
||||
class="@getCssClasses()"
|
||||
type="text" id="@Name" aria-expanded="true" placeholder="@Placeholder" />
|
||||
</span><div id="@PopupID" class="rz-autocomplete-panel" style="display:none; transform: none; box-sizing: border-box; max-height: 200px;">
|
||||
oninput="@OpenScript()" tabindex="@(Disabled ? "-1" : $"{TabIndex}")" @onchange="@OnChange"
|
||||
aria-autocomplete="list" aria-haspopup="true" autocomplete="off" role="combobox"
|
||||
class="@InputClassList"
|
||||
type="text" id="@Name" aria-expanded="true" placeholder="@Placeholder" />
|
||||
}
|
||||
<div id="@PopupID" class="rz-autocomplete-panel" style="@PopupStyle">
|
||||
<ul @ref="@list" class="rz-autocomplete-items rz-autocomplete-list" role="listbox">
|
||||
@if (!string.IsNullOrEmpty(searchText) || !string.IsNullOrEmpty(customSearchText))
|
||||
{
|
||||
@foreach (var item in LoadData.HasDelegate ? Data != null ? Data : Enumerable.Empty<object>() : (View != null ? View : Enumerable.Empty<object>()))
|
||||
{
|
||||
<li role="option" class="rz-autocomplete-list-item" @onclick="@(() => OnSelectItem(item))">
|
||||
<span>@PropertyAccess.GetItemOrValueFromProperty(item, TextProperty)</span>
|
||||
<li role="option" class="rz-autocomplete-list-item" @onclick="@(() => OnSelectItem(item))" onmousedown="Radzen.activeElement = null">
|
||||
<span>
|
||||
@if (Template != null)
|
||||
{
|
||||
@Template(item)
|
||||
}
|
||||
else
|
||||
{
|
||||
@PropertyAccess.GetItemOrValueFromProperty(item, TextProperty)
|
||||
}
|
||||
</span>
|
||||
</li>
|
||||
}
|
||||
}
|
||||
@@ -30,194 +50,3 @@
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@code {
|
||||
[Parameter]
|
||||
public int MinLength { get; set; } = 1;
|
||||
|
||||
[Parameter]
|
||||
public int FilterDelay { get; set; } = 500;
|
||||
|
||||
protected ElementReference search;
|
||||
protected ElementReference list;
|
||||
string customSearchText;
|
||||
|
||||
int selectedIndex = -1;
|
||||
|
||||
protected async Task OnFilterKeyPress(KeyboardEventArgs args)
|
||||
{
|
||||
var items = (LoadData.HasDelegate ? Data != null ? Data : Enumerable.Empty<object>() : (View != null ? View : Enumerable.Empty<object>())).OfType<object>();
|
||||
|
||||
var key = args.Code != null ? args.Code : args.Key;
|
||||
|
||||
if (key == "ArrowDown" || key == "ArrowUp")
|
||||
{
|
||||
try
|
||||
{
|
||||
selectedIndex = await JSRuntime.InvokeAsync<int>("Radzen.focusListItem", search, list, key == "ArrowDown", selectedIndex);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
else if (key == "Enter")
|
||||
{
|
||||
if (selectedIndex >= 0 && selectedIndex <= items.Count() - 1)
|
||||
{
|
||||
await OnSelectItem(items.ElementAt(selectedIndex));
|
||||
selectedIndex = -1;
|
||||
}
|
||||
}
|
||||
else if (key == "Escape")
|
||||
{
|
||||
await JSRuntime.InvokeVoidAsync("Radzen.closePopup", PopupID);
|
||||
}
|
||||
else if(key != "Tab")
|
||||
{
|
||||
selectedIndex = -1;
|
||||
|
||||
Debounce(DebounceFilter, FilterDelay);
|
||||
}
|
||||
}
|
||||
|
||||
async Task DebounceFilter()
|
||||
{
|
||||
var value = await JSRuntime.InvokeAsync<string>("Radzen.getInputValue", search);
|
||||
|
||||
if (value.Length < MinLength)
|
||||
return;
|
||||
|
||||
if (!LoadData.HasDelegate)
|
||||
{
|
||||
searchText = value;
|
||||
await InvokeAsync(() => { StateHasChanged(); });
|
||||
}
|
||||
else
|
||||
{
|
||||
customSearchText = value;
|
||||
await InvokeAsync(() => { LoadData.InvokeAsync(new Radzen.LoadDataArgs() { Filter = customSearchText }); });
|
||||
}
|
||||
}
|
||||
|
||||
private string PopupID
|
||||
{
|
||||
get
|
||||
{
|
||||
return $"popup{UniqueID}";
|
||||
}
|
||||
}
|
||||
|
||||
private async Task OnSelectItem(object item)
|
||||
{
|
||||
await JSRuntime.InvokeVoidAsync("Radzen.closePopup", PopupID);
|
||||
|
||||
await SelectItem(item);
|
||||
}
|
||||
|
||||
protected override IQueryable Query
|
||||
{
|
||||
get
|
||||
{
|
||||
return Data != null && !string.IsNullOrEmpty(searchText) ? Data.AsQueryable() : null;
|
||||
}
|
||||
}
|
||||
|
||||
protected override IEnumerable View
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Query != null)
|
||||
{
|
||||
string filterCaseSensitivityOperator = FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ? ".ToLower()" : "";
|
||||
|
||||
return Query.Where($"{TextProperty}{filterCaseSensitivityOperator}.{Enum.GetName(typeof(StringFilterOperator), FilterOperator)}(@0)",
|
||||
FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ? searchText.ToLower() : searchText);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
protected async System.Threading.Tasks.Task OnChange(ChangeEventArgs args)
|
||||
{
|
||||
Value = args.Value;
|
||||
|
||||
await ValueChanged.InvokeAsync($"{Value}");
|
||||
if (FieldIdentifier.FieldName != null) { EditContext?.NotifyFieldChanged(FieldIdentifier); }
|
||||
await Change.InvokeAsync(Value);
|
||||
}
|
||||
|
||||
async System.Threading.Tasks.Task SelectItem(object item)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(TextProperty))
|
||||
{
|
||||
Value = PropertyAccess.GetItemOrValueFromProperty(item, TextProperty);
|
||||
}
|
||||
else
|
||||
{
|
||||
Value = item;
|
||||
}
|
||||
|
||||
await ValueChanged.InvokeAsync($"{Value}");
|
||||
if (FieldIdentifier.FieldName != null) { EditContext?.NotifyFieldChanged(FieldIdentifier); }
|
||||
await Change.InvokeAsync(Value);
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private string getCssClasses()
|
||||
{
|
||||
return $"rz-inputtext rz-autocomplete-input{(Disabled ? " rz-state-disabled" : "")}";
|
||||
}
|
||||
|
||||
private string OpenScript()
|
||||
{
|
||||
if (Disabled)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
return $"Radzen.openPopup(this.parentNode, '{PopupID}', true)";
|
||||
}
|
||||
|
||||
protected override string GetComponentCssClass()
|
||||
{
|
||||
var fieldCssClass = FieldIdentifier.FieldName != null ? EditContext?.FieldCssClass(FieldIdentifier) : "";
|
||||
|
||||
return $"{base.GetComponentCssClass()} {fieldCssClass}";
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
base.Dispose();
|
||||
|
||||
JSRuntime.InvokeVoidAsync("Radzen.destroyPopup", PopupID);
|
||||
}
|
||||
|
||||
private bool firstRender = true;
|
||||
|
||||
protected override Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
this.firstRender = firstRender;
|
||||
|
||||
return base.OnAfterRenderAsync(firstRender);
|
||||
}
|
||||
|
||||
public override async Task SetParametersAsync(ParameterView parameters)
|
||||
{
|
||||
var shouldClose = false;
|
||||
|
||||
if (parameters.DidParameterChange(nameof(Visible), Visible))
|
||||
{
|
||||
var visible = parameters.GetValueOrDefault<bool>(nameof(Visible));
|
||||
shouldClose = !visible;
|
||||
}
|
||||
|
||||
await base.SetParametersAsync(parameters);
|
||||
|
||||
if (shouldClose && !firstRender)
|
||||
{
|
||||
await JSRuntime.InvokeVoidAsync("Radzen.destroyPopup", PopupID);
|
||||
}
|
||||
}
|
||||
}
|
||||
276
Radzen.Blazor/RadzenAutoComplete.razor.cs
Normal file
276
Radzen.Blazor/RadzenAutoComplete.razor.cs
Normal file
@@ -0,0 +1,276 @@
|
||||
using Radzen;
|
||||
using Radzen.Blazor.Rendering;
|
||||
using System.Collections;
|
||||
using System.Linq.Dynamic.Core;
|
||||
using Microsoft.AspNetCore.Components.Forms;
|
||||
using Microsoft.JSInterop;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Web;
|
||||
using System.Linq;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// RadzenAutoComplete component.
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// <RadzenAutoComplete Data=@customers TextProperty="CompanyName" Change=@(args => Console.WriteLine($"Selected text: {args}")) />
|
||||
/// </code>
|
||||
/// </example>
|
||||
public partial class RadzenAutoComplete : DataBoundFormComponent<string>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this <see cref="RadzenAutoComplete"/> is multiline.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if multiline; otherwise, <c>false</c>.</value>
|
||||
[Parameter]
|
||||
public bool Multiline { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Popup height.
|
||||
/// </summary>
|
||||
/// <value>The number Popup height.</value>
|
||||
[Parameter]
|
||||
public string PopupStyle { get; set; } = "display:none; transform: none; box-sizing: border-box; max-height: 200px;";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the template.
|
||||
/// </summary>
|
||||
/// <value>The template.</value>
|
||||
[Parameter]
|
||||
public RenderFragment<dynamic> Template { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the minimum length.
|
||||
/// </summary>
|
||||
/// <value>The minimum length.</value>
|
||||
[Parameter]
|
||||
public int MinLength { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the filter delay.
|
||||
/// </summary>
|
||||
/// <value>The filter delay.</value>
|
||||
[Parameter]
|
||||
public int FilterDelay { get; set; } = 500;
|
||||
|
||||
/// <summary>
|
||||
/// Gets search input reference.
|
||||
/// </summary>
|
||||
protected ElementReference search;
|
||||
|
||||
/// <summary>
|
||||
/// Gets list element reference.
|
||||
/// </summary>
|
||||
protected ElementReference list;
|
||||
|
||||
string customSearchText;
|
||||
int selectedIndex = -1;
|
||||
|
||||
/// <summary>
|
||||
/// Handles the <see cref="E:FilterKeyPress" /> event.
|
||||
/// </summary>
|
||||
/// <param name="args">The <see cref="KeyboardEventArgs"/> instance containing the event data.</param>
|
||||
protected async Task OnFilterKeyPress(KeyboardEventArgs args)
|
||||
{
|
||||
var items = (LoadData.HasDelegate ? Data != null ? Data : Enumerable.Empty<object>() : (View != null ? View : Enumerable.Empty<object>())).OfType<object>();
|
||||
|
||||
var key = args.Code != null ? args.Code : args.Key;
|
||||
|
||||
if (key == "ArrowDown" || key == "ArrowUp")
|
||||
{
|
||||
try
|
||||
{
|
||||
selectedIndex = await JSRuntime.InvokeAsync<int>("Radzen.focusListItem", search, list, key == "ArrowDown", selectedIndex);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
else if (key == "Enter")
|
||||
{
|
||||
if (selectedIndex >= 0 && selectedIndex <= items.Count() - 1)
|
||||
{
|
||||
await OnSelectItem(items.ElementAt(selectedIndex));
|
||||
selectedIndex = -1;
|
||||
}
|
||||
}
|
||||
else if (key == "Escape" || key == "Tab")
|
||||
{
|
||||
await JSRuntime.InvokeVoidAsync("Radzen.closePopup", PopupID);
|
||||
}
|
||||
else
|
||||
{
|
||||
selectedIndex = -1;
|
||||
|
||||
Debounce(DebounceFilter, FilterDelay);
|
||||
}
|
||||
}
|
||||
|
||||
async Task DebounceFilter()
|
||||
{
|
||||
var value = await JSRuntime.InvokeAsync<string>("Radzen.getInputValue", search);
|
||||
|
||||
if (value.Length < MinLength)
|
||||
return;
|
||||
|
||||
if (!LoadData.HasDelegate)
|
||||
{
|
||||
searchText = value;
|
||||
await InvokeAsync(() => { StateHasChanged(); });
|
||||
}
|
||||
else
|
||||
{
|
||||
customSearchText = value;
|
||||
await InvokeAsync(() => { LoadData.InvokeAsync(new Radzen.LoadDataArgs() { Filter = customSearchText }); });
|
||||
}
|
||||
}
|
||||
|
||||
private string PopupID
|
||||
{
|
||||
get
|
||||
{
|
||||
return $"popup{UniqueID}";
|
||||
}
|
||||
}
|
||||
|
||||
private async Task OnSelectItem(object item)
|
||||
{
|
||||
await JSRuntime.InvokeVoidAsync("Radzen.closePopup", PopupID);
|
||||
|
||||
await SelectItem(item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the IQueryable.
|
||||
/// </summary>
|
||||
/// <value>The IQueryable.</value>
|
||||
protected override IQueryable Query
|
||||
{
|
||||
get
|
||||
{
|
||||
return Data != null && !string.IsNullOrEmpty(searchText) ? Data.AsQueryable() : null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the view - the Query with filtering applied.
|
||||
/// </summary>
|
||||
/// <value>The view.</value>
|
||||
protected override IEnumerable View
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Query != null)
|
||||
{
|
||||
string filterCaseSensitivityOperator = FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ? ".ToLower()" : "";
|
||||
|
||||
string textProperty = string.IsNullOrEmpty(TextProperty) ? string.Empty : $".{TextProperty}";
|
||||
|
||||
return Query.Where($"o=>o{textProperty}{filterCaseSensitivityOperator}.{Enum.GetName(typeof(StringFilterOperator), FilterOperator)}(@0)",
|
||||
FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ? searchText.ToLower() : searchText);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the <see cref="E:Change" /> event.
|
||||
/// </summary>
|
||||
/// <param name="args">The <see cref="ChangeEventArgs"/> instance containing the event data.</param>
|
||||
protected async System.Threading.Tasks.Task OnChange(ChangeEventArgs args)
|
||||
{
|
||||
Value = args.Value;
|
||||
|
||||
await ValueChanged.InvokeAsync($"{Value}");
|
||||
if (FieldIdentifier.FieldName != null) { EditContext?.NotifyFieldChanged(FieldIdentifier); }
|
||||
await Change.InvokeAsync(Value);
|
||||
}
|
||||
|
||||
async System.Threading.Tasks.Task SelectItem(object item)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(TextProperty))
|
||||
{
|
||||
Value = PropertyAccess.GetItemOrValueFromProperty(item, TextProperty);
|
||||
}
|
||||
else
|
||||
{
|
||||
Value = item;
|
||||
}
|
||||
|
||||
await ValueChanged.InvokeAsync($"{Value}");
|
||||
if (FieldIdentifier.FieldName != null) { EditContext?.NotifyFieldChanged(FieldIdentifier); }
|
||||
await Change.InvokeAsync(Value);
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
ClassList InputClassList => ClassList.Create("rz-inputtext rz-autocomplete-input")
|
||||
.AddDisabled(Disabled);
|
||||
|
||||
private string OpenScript()
|
||||
{
|
||||
if (Disabled)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
return $"Radzen.openPopup(this.parentNode, '{PopupID}', true)";
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override string GetComponentCssClass()
|
||||
{
|
||||
return GetClassList("rz-autocomplete").ToString();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Dispose()
|
||||
{
|
||||
base.Dispose();
|
||||
|
||||
if (IsJSRuntimeAvailable)
|
||||
{
|
||||
JSRuntime.InvokeVoidAsync("Radzen.destroyPopup", PopupID);
|
||||
}
|
||||
}
|
||||
|
||||
private bool firstRender = true;
|
||||
|
||||
/// <summary>
|
||||
/// Called on after render asynchronous.
|
||||
/// </summary>
|
||||
/// <param name="firstRender">if set to <c>true</c> is first render.</param>
|
||||
/// <returns>Task.</returns>
|
||||
protected override Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
this.firstRender = firstRender;
|
||||
|
||||
return base.OnAfterRenderAsync(firstRender);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override async Task SetParametersAsync(ParameterView parameters)
|
||||
{
|
||||
var shouldClose = false;
|
||||
|
||||
if (parameters.DidParameterChange(nameof(Visible), Visible))
|
||||
{
|
||||
var visible = parameters.GetValueOrDefault<bool>(nameof(Visible));
|
||||
shouldClose = !visible;
|
||||
}
|
||||
|
||||
await base.SetParametersAsync(parameters);
|
||||
|
||||
if (shouldClose && !firstRender)
|
||||
{
|
||||
await JSRuntime.InvokeVoidAsync("Radzen.destroyPopup", PopupID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
44
Radzen.Blazor/RadzenAxisTitle.cs
Normal file
44
Radzen.Blazor/RadzenAxisTitle.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the title configuration of a <see cref="AxisBase" />.
|
||||
/// </summary>
|
||||
public class RadzenAxisTitle : RadzenChartComponentBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the text displayed by the title.
|
||||
/// </summary>
|
||||
/// <value>The text.</value>
|
||||
[Parameter]
|
||||
public string Text { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Sets the axis with this configuration applies to.
|
||||
/// </summary>
|
||||
/// <value>The axis.</value>
|
||||
[CascadingParameter]
|
||||
public AxisBase Axis
|
||||
{
|
||||
set
|
||||
{
|
||||
value.Title = this;
|
||||
}
|
||||
}
|
||||
|
||||
internal double Size
|
||||
{
|
||||
get
|
||||
{
|
||||
return 16 * 0.875;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override bool ShouldRefreshChart(ParameterView parameters)
|
||||
{
|
||||
return DidParameterChange(parameters, nameof(Text), Text);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
@inherits RadzenChartComponentBase
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public string Text { get; set; }
|
||||
|
||||
[CascadingParameter]
|
||||
public AxisBase Axis
|
||||
{
|
||||
set
|
||||
{
|
||||
value.Title = this;
|
||||
}
|
||||
}
|
||||
|
||||
internal double Size
|
||||
{
|
||||
get
|
||||
{
|
||||
return 16 * 0.875;
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool ShouldRefreshChart(ParameterView parameters)
|
||||
{
|
||||
return DidParameterChange(parameters, nameof(Text), Text);
|
||||
}
|
||||
}
|
||||
14
Radzen.Blazor/RadzenBadge.razor
Normal file
14
Radzen.Blazor/RadzenBadge.razor
Normal file
@@ -0,0 +1,14 @@
|
||||
@inherits RadzenComponent
|
||||
@if (Visible)
|
||||
{
|
||||
<span @ref="@Element" style="@Style" @attributes="Attributes" class="@GetCssClass()" id="@GetId()">
|
||||
@if (ChildContent != null)
|
||||
{
|
||||
@ChildContent
|
||||
}
|
||||
else
|
||||
{
|
||||
@Text
|
||||
}
|
||||
</span>
|
||||
}
|
||||
76
Radzen.Blazor/RadzenBadge.razor.cs
Normal file
76
Radzen.Blazor/RadzenBadge.razor.cs
Normal file
@@ -0,0 +1,76 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// RadzenBadge component.
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// <RadzenBadge BadgeStyle="BadgeStyle.Primary" Text="Primary" />
|
||||
/// </code>
|
||||
/// </example>
|
||||
public partial class RadzenBadge : RadzenComponent
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override string GetComponentCssClass()
|
||||
{
|
||||
var classList = new List<string>();
|
||||
|
||||
classList.Add("rz-badge");
|
||||
classList.Add($"rz-badge-{BadgeStyle.ToString().ToLowerInvariant()}");
|
||||
classList.Add($"rz-variant-{Variant.ToString().ToLowerInvariant()}");
|
||||
classList.Add($"rz-shade-{Shade.ToString().ToLowerInvariant()}");
|
||||
|
||||
if (IsPill)
|
||||
{
|
||||
classList.Add("rz-badge-pill");
|
||||
}
|
||||
|
||||
return string.Join(" ", classList);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the child content.
|
||||
/// </summary>
|
||||
/// <value>The child content.</value>
|
||||
[Parameter]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the text.
|
||||
/// </summary>
|
||||
/// <value>The text.</value>
|
||||
[Parameter]
|
||||
public string Text { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the badge style.
|
||||
/// </summary>
|
||||
/// <value>The badge style.</value>
|
||||
[Parameter]
|
||||
public BadgeStyle BadgeStyle { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the badge variant.
|
||||
/// </summary>
|
||||
/// <value>The badge variant.</value>
|
||||
[Parameter]
|
||||
public Variant Variant { get; set; } = Variant.Filled;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the badge shade color.
|
||||
/// </summary>
|
||||
/// <value>The badge shade color.</value>
|
||||
[Parameter]
|
||||
public Shade Shade { get; set; } = Shade.Default;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance is pill.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance is pill; otherwise, <c>false</c>.</value>
|
||||
[Parameter]
|
||||
public bool IsPill { get; set; }
|
||||
}
|
||||
}
|
||||
45
Radzen.Blazor/RadzenBarOptions.cs
Normal file
45
Radzen.Blazor/RadzenBarOptions.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// Common configuration of <see cref="RadzenBarSeries{TItem}" />.
|
||||
/// </summary>
|
||||
public partial class RadzenBarOptions : RadzenChartComponentBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the border radius of the bars.
|
||||
/// </summary>
|
||||
/// <value>The radius. Values greater than <c>0</c> make rounded corners.</value>
|
||||
[Parameter]
|
||||
public double Radius { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the margin between bars.
|
||||
/// </summary>
|
||||
/// <value>The margin. By default set to <c>10</c></value>
|
||||
[Parameter]
|
||||
public double Margin { get; set; } = 10;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the height of all bars in pixels. By default it is automatically calculated depending on the chart height.
|
||||
/// </summary>
|
||||
/// <value>The pixel height of the bar. By default set to <c>null</c></value>
|
||||
[Parameter]
|
||||
public double? Height { get; set;}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Initialize()
|
||||
{
|
||||
Chart.BarOptions = this;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override bool ShouldRefreshChart(ParameterView parameters)
|
||||
{
|
||||
return DidParameterChange(parameters, nameof(Radius), Radius) ||
|
||||
DidParameterChange(parameters, nameof(Height), Height) ||
|
||||
DidParameterChange(parameters, nameof(Margin), Margin);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
@inherits RadzenChartComponentBase
|
||||
@code {
|
||||
[Parameter]
|
||||
public double Radius { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public double Margin { get; set; } = 10;
|
||||
|
||||
protected override void Initialize()
|
||||
{
|
||||
Chart.BarOptions = this;
|
||||
}
|
||||
|
||||
protected override bool ShouldRefreshChart(ParameterView parameters)
|
||||
{
|
||||
return DidParameterChange(parameters, nameof(Radius), Radius) || DidParameterChange(parameters, nameof(Margin), Margin);
|
||||
}
|
||||
}
|
||||
@@ -10,136 +10,6 @@
|
||||
</CascadingValue>
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public string Fill { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string Stroke { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public double StrokeWidth { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public LineType LineType { get; set; }
|
||||
|
||||
public override string Color
|
||||
{
|
||||
get
|
||||
{
|
||||
return Fill;
|
||||
}
|
||||
}
|
||||
|
||||
public override ScaleBase TransformCategoryScale(ScaleBase scale)
|
||||
{
|
||||
return base.TransformValueScale(scale);
|
||||
}
|
||||
|
||||
public override ScaleBase TransformValueScale(ScaleBase scale)
|
||||
{
|
||||
return base.TransformCategoryScale(scale);
|
||||
}
|
||||
|
||||
private IList<IChartSeries> BarSeries
|
||||
{
|
||||
get
|
||||
{
|
||||
return Chart.Series.Where(series => series is IChartBarSeries).Cast<IChartSeries>().ToList();
|
||||
}
|
||||
}
|
||||
|
||||
private IList<IChartSeries> VisibleBarSeries
|
||||
{
|
||||
get
|
||||
{
|
||||
return BarSeries.Where(series => series.Visible).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
private double BandHeight
|
||||
{
|
||||
get
|
||||
{
|
||||
var availableHeight = Chart.ValueScale.OutputSize; // - (Chart.ValueAxis.Padding * 2);
|
||||
var bands = VisibleBarSeries.Cast<IChartBarSeries>().Max(series => series.Count) + 2;
|
||||
return availableHeight / bands;
|
||||
}
|
||||
}
|
||||
|
||||
int IChartBarSeries.Count
|
||||
{
|
||||
get
|
||||
{
|
||||
return Items.Count;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool Contains(double x, double y)
|
||||
{
|
||||
return DataAt(x, y) != null;
|
||||
}
|
||||
|
||||
protected override double TooltipX(TItem item)
|
||||
{
|
||||
var value = Chart.CategoryScale.Compose(Value);
|
||||
var x = value(item);
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
protected override string TooltipValue(TItem item)
|
||||
{
|
||||
return Chart.ValueAxis.Format(Chart.CategoryScale, Chart.CategoryScale.Value(Value(item)));
|
||||
}
|
||||
protected override string TooltipTitle(TItem item)
|
||||
{
|
||||
var category = Category(Chart.ValueScale);
|
||||
return Chart.CategoryAxis.Format(Chart.ValueScale, Chart.ValueScale.Value(category(item)));
|
||||
}
|
||||
|
||||
public override object DataAt(double x, double y)
|
||||
{
|
||||
var value = ComposeValue(Chart.CategoryScale);
|
||||
var category = ComposeCategory(Chart.ValueScale);
|
||||
var ticks = Chart.CategoryScale.Ticks(Chart.ValueAxis.TickDistance);
|
||||
var x0 = Chart.CategoryScale.Scale(Math.Max(0, ticks.Start));
|
||||
|
||||
var barSeries = VisibleBarSeries;
|
||||
var index = barSeries.IndexOf(this);
|
||||
var padding = Chart.BarOptions.Margin;
|
||||
var bandHeight = BandHeight;
|
||||
var height = bandHeight / barSeries.Count() - padding + padding / barSeries.Count();
|
||||
|
||||
foreach(var data in Items)
|
||||
{
|
||||
var startY = category(data) - bandHeight / 2 + index * height + index * padding;
|
||||
var endY = startY + height;
|
||||
var dataX = value(data);
|
||||
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;
|
||||
}
|
||||
|
||||
protected override double TooltipY(TItem item)
|
||||
{
|
||||
var category = ComposeCategory(Chart.ValueScale);
|
||||
var barSeries = VisibleBarSeries;
|
||||
var index = barSeries.IndexOf(this);
|
||||
var padding = Chart.BarOptions.Margin;
|
||||
var bandHeight = BandHeight;
|
||||
var height = bandHeight / barSeries.Count() - padding + padding / barSeries.Count();
|
||||
var y = category(item) - bandHeight / 2 + index * height + index * padding;
|
||||
|
||||
return y + height / 2;
|
||||
}
|
||||
|
||||
public override RenderFragment Render(ScaleBase categoryScale, ScaleBase valueScale)
|
||||
{
|
||||
var value = ComposeValue(categoryScale);
|
||||
@@ -177,8 +47,10 @@
|
||||
{
|
||||
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" />
|
||||
<Path @key="@path" D="@path" Stroke="@stroke" StrokeWidth="@StrokeWidth" Fill="@fill" LineType="@LineType" Style="@style" />
|
||||
}
|
||||
</g>;
|
||||
}
|
||||
|
||||
238
Radzen.Blazor/RadzenBarSeries.razor.cs
Normal file
238
Radzen.Blazor/RadzenBarSeries.razor.cs
Normal file
@@ -0,0 +1,238 @@
|
||||
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 RadzenBarSeries<TItem> : CartesianSeries<TItem>, IChartBarSeries
|
||||
{
|
||||
/// <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)
|
||||
{
|
||||
return base.TransformValueScale(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
|
||||
{
|
||||
get
|
||||
{
|
||||
return Chart.Series.Where(series => series is IChartBarSeries).Cast<IChartSeries>().ToList();
|
||||
}
|
||||
}
|
||||
|
||||
private IList<IChartSeries> VisibleBarSeries
|
||||
{
|
||||
get
|
||||
{
|
||||
return BarSeries.Where(series => series.Visible).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<IChartBarSeries>().Max(series => series.Count) + 2;
|
||||
return availableHeight / bands;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int IChartBarSeries.Count
|
||||
{
|
||||
get
|
||||
{
|
||||
return Items.Count;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool Contains(double x, double y, double tolerance)
|
||||
{
|
||||
return DataAt(x, y) != null;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
internal override double TooltipX(TItem item)
|
||||
{
|
||||
var value = Chart.CategoryScale.Compose(Value);
|
||||
var x = value(item);
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
/// <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 value = ComposeValue(Chart.CategoryScale);
|
||||
var category = ComposeCategory(Chart.ValueScale);
|
||||
var ticks = Chart.CategoryScale.Ticks(Chart.ValueAxis.TickDistance);
|
||||
var x0 = Chart.CategoryScale.Scale(Math.Max(0, ticks.Start));
|
||||
|
||||
var barSeries = VisibleBarSeries;
|
||||
var index = barSeries.IndexOf(this);
|
||||
var padding = Chart.BarOptions.Margin;
|
||||
var bandHeight = BandHeight;
|
||||
var height = bandHeight / barSeries.Count() - padding + padding / barSeries.Count();
|
||||
|
||||
foreach (var data in Items)
|
||||
{
|
||||
var startY = category(data) - bandHeight / 2 + index * height + index * padding;
|
||||
var endY = startY + height;
|
||||
var dataX = value(data);
|
||||
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)
|
||||
{
|
||||
var category = ComposeCategory(Chart.ValueScale);
|
||||
var barSeries = VisibleBarSeries;
|
||||
var index = barSeries.IndexOf(this);
|
||||
var padding = Chart.BarOptions.Margin;
|
||||
var bandHeight = BandHeight;
|
||||
var height = bandHeight / barSeries.Count() - padding + padding / barSeries.Count();
|
||||
var y = category(item) - bandHeight / 2 + index * height + index * padding;
|
||||
|
||||
return y + height / 2;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override IEnumerable<ChartDataLabel> GetDataLabels(double offsetX, double offsetY)
|
||||
{
|
||||
var list = new List<ChartDataLabel>();
|
||||
|
||||
foreach (var d in Data)
|
||||
{
|
||||
list.Add(new ChartDataLabel
|
||||
{
|
||||
Position = new Point() { X = TooltipX(d) + offsetX + 8, Y = TooltipY(d) + offsetY },
|
||||
TextAnchor = "start",
|
||||
Text = Chart.ValueAxis.Format(Chart.CategoryScale, Value(d))
|
||||
});
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,41 +6,3 @@
|
||||
@ChildContent
|
||||
</div>
|
||||
}
|
||||
@code {
|
||||
[Parameter]
|
||||
public override string Style { get; set; } = "margin-top: 51px; margin-bottom: 57px; margin-left:250px;";
|
||||
|
||||
protected override string GetComponentCssClass()
|
||||
{
|
||||
return "body";
|
||||
}
|
||||
|
||||
public void Toggle()
|
||||
{
|
||||
Expanded = !Expanded;
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
protected string GetStyle()
|
||||
{
|
||||
var marginLeft = 250;
|
||||
|
||||
if (!string.IsNullOrEmpty(Style))
|
||||
{
|
||||
var marginLeftStyle = Style.Split(';').Where(i => i.Split(':')[0].Contains("margin-left")).FirstOrDefault();
|
||||
if (!string.IsNullOrEmpty(marginLeftStyle) && marginLeftStyle.Contains("px"))
|
||||
{
|
||||
marginLeft = int.Parse(marginLeftStyle.Split(':')[1].Trim().Replace("px", "").Split('.')[0].Trim());
|
||||
}
|
||||
}
|
||||
|
||||
return $"{Style}; margin-left: {(Expanded ? 0 : marginLeft)}px";
|
||||
}
|
||||
|
||||
[Parameter]
|
||||
public bool Expanded { get; set; } = false;
|
||||
|
||||
[Parameter]
|
||||
public EventCallback<bool> ExpandedChanged { get; set; }
|
||||
}
|
||||
126
Radzen.Blazor/RadzenBody.razor.cs
Normal file
126
Radzen.Blazor/RadzenBody.razor.cs
Normal file
@@ -0,0 +1,126 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using System.Linq;
|
||||
using Radzen.Blazor.Rendering;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Components.Routing;
|
||||
using Microsoft.JSInterop;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// RadzenBody component.
|
||||
/// </summary>
|
||||
public partial class RadzenBody : RadzenComponentWithChildren
|
||||
{
|
||||
private const string DefaultStyle = "margin-top: 51px; margin-bottom: 57px; margin-left:250px;";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the style.
|
||||
/// </summary>
|
||||
/// <value>The style.</value>
|
||||
[Parameter]
|
||||
public override string Style { get; set; } = DefaultStyle;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override string GetComponentCssClass()
|
||||
{
|
||||
var classList = ClassList.Create("rz-body")
|
||||
.Add("body")
|
||||
.Add("body-expanded", Expanded);
|
||||
|
||||
return classList.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Toggles this instance width and left margin.
|
||||
/// </summary>
|
||||
public void Toggle()
|
||||
{
|
||||
Expanded = !Expanded;
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="RadzenLayout" /> this component is nested in.
|
||||
/// </summary>
|
||||
[CascadingParameter]
|
||||
public RadzenLayout Layout { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the style.
|
||||
/// </summary>
|
||||
/// <returns>System.String.</returns>
|
||||
protected string GetStyle()
|
||||
{
|
||||
if (Layout == null)
|
||||
{
|
||||
var marginLeft = 250;
|
||||
var style = Style;
|
||||
|
||||
if (!string.IsNullOrEmpty(Style))
|
||||
{
|
||||
var marginLeftStyle = Style.Split(';').Where(i => i.Split(':')[0].Contains("margin-left")).FirstOrDefault();
|
||||
if (!string.IsNullOrEmpty(marginLeftStyle) && marginLeftStyle.Contains("px"))
|
||||
{
|
||||
marginLeft = int.Parse(marginLeftStyle.Split(':')[1].Trim().Replace("px", "").Split('.')[0].Trim());
|
||||
}
|
||||
}
|
||||
|
||||
return $"{Style}; margin-left: {(Expanded ? 0 : marginLeft)}px";
|
||||
}
|
||||
else
|
||||
{
|
||||
var style = Style;
|
||||
|
||||
if (!string.IsNullOrEmpty(style))
|
||||
{
|
||||
style = style.Replace(DefaultStyle, "");
|
||||
}
|
||||
|
||||
return $"{style}";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this <see cref="RadzenBody"/> is expanded.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if expanded; otherwise, <c>false</c>.</value>
|
||||
[Parameter]
|
||||
public bool Expanded { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a callback raised when the component is expanded or collapsed.
|
||||
/// </summary>
|
||||
/// <value>The expanded changed callback.</value>
|
||||
[Parameter]
|
||||
public EventCallback<bool> ExpandedChanged { get; set; }
|
||||
|
||||
[Inject]
|
||||
NavigationManager NavigationManager { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Task OnInitializedAsync()
|
||||
{
|
||||
NavigationManager.LocationChanged += OnLocationChanged;
|
||||
|
||||
return base.OnInitializedAsync();
|
||||
}
|
||||
|
||||
private void OnLocationChanged(object sender, LocationChangedEventArgs e)
|
||||
{
|
||||
if (IsJSRuntimeAvailable && Layout != null)
|
||||
{
|
||||
JSRuntime.InvokeVoidAsync("eval", $"document.getElementById('{GetId()}').scrollTop = 0");
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Dispose()
|
||||
{
|
||||
NavigationManager.LocationChanged -= OnLocationChanged;
|
||||
|
||||
base.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
13
Radzen.Blazor/RadzenBreadCrumb.razor
Normal file
13
Radzen.Blazor/RadzenBreadCrumb.razor
Normal file
@@ -0,0 +1,13 @@
|
||||
@inherits RadzenComponentWithChildren
|
||||
|
||||
<CascadingValue Value="@Template">
|
||||
@if (Visible)
|
||||
{
|
||||
<div class="@GetCssClass()" style="@Style" @attributes="@Attributes" id="@GetId()">
|
||||
@if (ChildContent != null)
|
||||
{
|
||||
@ChildContent
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</CascadingValue>
|
||||
23
Radzen.Blazor/RadzenBreadCrumb.razor.cs
Normal file
23
Radzen.Blazor/RadzenBreadCrumb.razor.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// A component to display a Bread Crumb style menu
|
||||
/// </summary>
|
||||
public partial class RadzenBreadCrumb : RadzenComponentWithChildren
|
||||
{
|
||||
/// <summary>
|
||||
/// An optional RenderFragment that is rendered per Item
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public RenderFragment<RadzenBreadCrumbItem> Template { get; set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override string GetComponentCssClass()
|
||||
{
|
||||
return "rz-breadcrumb";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
30
Radzen.Blazor/RadzenBreadCrumbItem.razor
Normal file
30
Radzen.Blazor/RadzenBreadCrumbItem.razor
Normal file
@@ -0,0 +1,30 @@
|
||||
@inherits RadzenComponent
|
||||
|
||||
@if (Visible)
|
||||
{
|
||||
<div class="@GetCssClass()" id="@GetId()" style="@Style" @attributes="@Attributes">
|
||||
@if (ChildContent != null)
|
||||
{
|
||||
@ChildContent
|
||||
}
|
||||
else if (Template != null)
|
||||
{
|
||||
@Template(this)
|
||||
}
|
||||
else
|
||||
{
|
||||
@if (!string.IsNullOrWhiteSpace(Path))
|
||||
{
|
||||
<RadzenLink Icon="@Icon" Path="@Path" Text="@Text" />
|
||||
}
|
||||
else
|
||||
{
|
||||
@if (!string.IsNullOrWhiteSpace(Icon))
|
||||
{
|
||||
<RadzenIcon Icon="@Icon" />
|
||||
}
|
||||
<RadzenLabel Text="@Text" />
|
||||
}
|
||||
}
|
||||
</div>
|
||||
}
|
||||
47
Radzen.Blazor/RadzenBreadCrumbItem.razor.cs
Normal file
47
Radzen.Blazor/RadzenBreadCrumbItem.razor.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// Bread Crumb Item Component
|
||||
/// </summary>
|
||||
public partial class RadzenBreadCrumbItem : RadzenComponent
|
||||
{
|
||||
/// <summary>
|
||||
/// Cascaded Template Parameter from <see cref="RadzenBreadCrumb"/> Component
|
||||
/// </summary>
|
||||
[CascadingParameter]
|
||||
public RenderFragment<RadzenBreadCrumbItem> Template { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The Displayed Text
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string Text { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// An optional Link to be rendendered
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string Path { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// An optional Icon to be rendered
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string Icon { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Template Parameter used only for this Item
|
||||
/// Note: this overrides the <see cref="Template"/> Cascading Parameter
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override string GetComponentCssClass()
|
||||
{
|
||||
return "rz-breadcrumb-item";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,71 +2,41 @@
|
||||
|
||||
@if (Visible)
|
||||
{
|
||||
<button @ref="@Element" style="@Style" disabled="@Disabled"
|
||||
<button @ref="@Element" style="@Style" disabled="@IsDisabled"
|
||||
type="@Enum.GetName(typeof(ButtonType), ButtonType).ToLower()"
|
||||
@attributes="Attributes" class="@GetCssClass()" id="@GetId()"
|
||||
@onclick="@((args) => OnClick(args))">
|
||||
@if (ChildContent != null)
|
||||
{
|
||||
@ChildContent
|
||||
}
|
||||
else
|
||||
{
|
||||
@if (!string.IsNullOrEmpty(@Icon))
|
||||
@onclick="@OnClick">
|
||||
<span class="rz-button-box">
|
||||
@if (ChildContent != null)
|
||||
{
|
||||
<i class="rz-button-icon-left rzi">@((MarkupString)Icon)</i>
|
||||
@ChildContent
|
||||
}
|
||||
@if (!string.IsNullOrEmpty(Image))
|
||||
else
|
||||
{
|
||||
<img class="rz-button-icon-left rzi" src="@Image" />
|
||||
@if (IsBusy)
|
||||
{
|
||||
<RadzenIcon Icon="refresh" Style="animation: rotation 700ms linear infinite" />
|
||||
@if (!string.IsNullOrEmpty(BusyText))
|
||||
{
|
||||
<span class="rz-button-text">@BusyText</span>
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@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>
|
||||
}
|
||||
}
|
||||
}
|
||||
@if (!string.IsNullOrEmpty(Text))
|
||||
{
|
||||
<span class="rz-button-text">@Text</span>
|
||||
}
|
||||
}
|
||||
</span>
|
||||
</button>
|
||||
}
|
||||
@code {
|
||||
private string getButtonSize()
|
||||
{
|
||||
return Size == ButtonSize.Medium ? "md" : "sm";
|
||||
}
|
||||
|
||||
[Parameter]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string Text { get; set; } = "";
|
||||
|
||||
[Parameter]
|
||||
public string Icon { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string Image { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public ButtonStyle ButtonStyle { get; set; } = ButtonStyle.Primary;
|
||||
|
||||
[Parameter]
|
||||
public ButtonType ButtonType { get; set; } = ButtonType.Button;
|
||||
|
||||
[Parameter]
|
||||
public ButtonSize Size { get; set; } = ButtonSize.Medium;
|
||||
|
||||
[Parameter]
|
||||
public bool Disabled { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public EventCallback<MouseEventArgs> Click { get; set; }
|
||||
|
||||
public async System.Threading.Tasks.Task OnClick(MouseEventArgs args)
|
||||
{
|
||||
await Click.InvokeAsync(args);
|
||||
}
|
||||
|
||||
protected override string GetComponentCssClass()
|
||||
{
|
||||
return $"rz-button rz-button-{getButtonSize()} btn-{Enum.GetName(typeof(ButtonStyle), ButtonStyle).ToLower()}{(Disabled ? " rz-state-disabled" : "")}{(string.IsNullOrEmpty(Text) && !string.IsNullOrEmpty(Icon) ? " rz-button-icon-only" : "")}";
|
||||
}
|
||||
}
|
||||
|
||||
151
Radzen.Blazor/RadzenButton.razor.cs
Normal file
151
Radzen.Blazor/RadzenButton.razor.cs
Normal file
@@ -0,0 +1,151 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Web;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// RadzenButton component.
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// <RadzenButton Click=@(args => Console.WriteLine("Button clicked")) Text="Button" />
|
||||
/// </code>
|
||||
/// </example>
|
||||
public partial class RadzenButton : RadzenComponent
|
||||
{
|
||||
private string getButtonSize()
|
||||
{
|
||||
return Size == ButtonSize.Medium ? "md" : Size == ButtonSize.Large ? "lg" : Size == ButtonSize.Small ? "sm" : "xs";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the child content.
|
||||
/// </summary>
|
||||
/// <value>The child content.</value>
|
||||
[Parameter]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the text.
|
||||
/// </summary>
|
||||
/// <value>The text.</value>
|
||||
[Parameter]
|
||||
public string Text { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the icon.
|
||||
/// </summary>
|
||||
/// <value>The icon.</value>
|
||||
[Parameter]
|
||||
public string Icon { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the image.
|
||||
/// </summary>
|
||||
/// <value>The image.</value>
|
||||
[Parameter]
|
||||
public string Image { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the button style.
|
||||
/// </summary>
|
||||
/// <value>The button style.</value>
|
||||
[Parameter]
|
||||
public ButtonStyle ButtonStyle { get; set; } = ButtonStyle.Primary;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the type of the button.
|
||||
/// </summary>
|
||||
/// <value>The type of the button.</value>
|
||||
[Parameter]
|
||||
public ButtonType ButtonType { get; set; } = ButtonType.Button;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the design variant of the button.
|
||||
/// </summary>
|
||||
/// <value>The variant of the button.</value>
|
||||
[Parameter]
|
||||
public Variant Variant { get; set; } = Variant.Filled;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the color shade of the button.
|
||||
/// </summary>
|
||||
/// <value>The color shade of the button.</value>
|
||||
[Parameter]
|
||||
public Shade Shade { get; set; } = Shade.Default;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the size.
|
||||
/// </summary>
|
||||
/// <value>The size.</value>
|
||||
[Parameter]
|
||||
public ButtonSize Size { get; set; } = ButtonSize.Medium;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this <see cref="RadzenButton"/> is disabled.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if disabled; otherwise, <c>false</c>.</value>
|
||||
[Parameter]
|
||||
public bool Disabled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the click callback.
|
||||
/// </summary>
|
||||
/// <value>The click callback.</value>
|
||||
[Parameter]
|
||||
public EventCallback<MouseEventArgs> Click { get; set; }
|
||||
|
||||
/// <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; }
|
||||
|
||||
|
||||
bool clicking;
|
||||
/// <summary>
|
||||
/// Handles the <see cref="E:Click" /> event.
|
||||
/// </summary>
|
||||
/// <param name="args">The <see cref="MouseEventArgs"/> instance containing the event data.</param>
|
||||
public async Task OnClick(MouseEventArgs args)
|
||||
{
|
||||
if (clicking)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
clicking = true;
|
||||
|
||||
await Click.InvokeAsync(args);
|
||||
}
|
||||
finally
|
||||
{
|
||||
clicking = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override string GetComponentCssClass()
|
||||
{
|
||||
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" : "")}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,10 +4,3 @@
|
||||
{
|
||||
<div @ref="@Element" @attributes="Attributes" class="@GetCssClass()" style="@Style" id="@GetId()">@ChildContent</div>
|
||||
}
|
||||
|
||||
@code {
|
||||
protected override string GetComponentCssClass()
|
||||
{
|
||||
return "rz-card card";
|
||||
}
|
||||
}
|
||||
|
||||
19
Radzen.Blazor/RadzenCard.razor.cs
Normal file
19
Radzen.Blazor/RadzenCard.razor.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Web;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// RadzenCard component.
|
||||
/// </summary>
|
||||
public partial class RadzenCard : RadzenComponentWithChildren
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override string GetComponentCssClass()
|
||||
{
|
||||
return "rz-card";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@
|
||||
<CascadingValue Value="@this">
|
||||
@ChildContent
|
||||
</CascadingValue>
|
||||
<div @ref="Element" class="@GetCssClass()" @attributes="@Attributes" style="@Style" id="@GetId()">
|
||||
<div @ref="Element" @attributes="@Attributes" class="@GetCssClass()" style="@Style" id="@GetId()">
|
||||
@if (Width.HasValue && Height.HasValue)
|
||||
{
|
||||
<CascadingValue Value="@this">
|
||||
@@ -26,6 +26,7 @@
|
||||
@if (series.Visible)
|
||||
{
|
||||
@series.Render(CategoryScale, ValueScale);
|
||||
@series.RenderOverlays(CategoryScale, ValueScale);
|
||||
}
|
||||
}
|
||||
</g>
|
||||
@@ -45,386 +46,3 @@
|
||||
}
|
||||
</div>
|
||||
}
|
||||
@code {
|
||||
[Parameter]
|
||||
public ColorScheme ColorScheme { get; set; }
|
||||
|
||||
double? Width { get; set; }
|
||||
|
||||
double? Height { get; set; }
|
||||
|
||||
double MarginTop { get; set; }
|
||||
|
||||
double MarginLeft { get; set; }
|
||||
|
||||
double MarginRight { get; set; }
|
||||
|
||||
double MarginBottom { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
|
||||
internal ScaleBase CategoryScale { get; set; } = new LinearScale();
|
||||
internal ScaleBase ValueScale { get; set; } = new LinearScale();
|
||||
internal IList<IChartSeries> Series { get; set; } = new List<IChartSeries>();
|
||||
internal RadzenColumnOptions ColumnOptions { get; set; } = new RadzenColumnOptions();
|
||||
internal RadzenBarOptions BarOptions { get; set; } = new RadzenBarOptions();
|
||||
|
||||
internal RadzenLegend Legend { get; set; } = new RadzenLegend();
|
||||
internal RadzenCategoryAxis CategoryAxis { get; set; } = new RadzenCategoryAxis();
|
||||
internal RadzenValueAxis ValueAxis { get; set; } = new RadzenValueAxis();
|
||||
internal RadzenChartTooltipOptions Tooltip { get; set; } = new RadzenChartTooltipOptions();
|
||||
|
||||
internal void AddSeries(IChartSeries series)
|
||||
{
|
||||
if (!Series.Contains(series))
|
||||
{
|
||||
Series.Add(series);
|
||||
}
|
||||
}
|
||||
|
||||
internal void RemoveSeries(IChartSeries series)
|
||||
{
|
||||
Series.Remove(series);
|
||||
}
|
||||
|
||||
private bool ShouldRenderAxes()
|
||||
{
|
||||
var pieType = typeof(RadzenPieSeries<>);
|
||||
var donutType = typeof(RadzenDonutSeries<>);
|
||||
|
||||
return !Series.All(series =>
|
||||
{
|
||||
var type = series.GetType().GetGenericTypeDefinition();
|
||||
|
||||
return type == pieType || type == donutType;
|
||||
});
|
||||
}
|
||||
|
||||
internal bool ShouldInvertAxes()
|
||||
{
|
||||
return Series.Count > 0 && Series.All(series => series is IChartBarSeries);
|
||||
}
|
||||
|
||||
private bool UpdateScales()
|
||||
{
|
||||
var valueScale = ValueScale;
|
||||
var categoryScale = CategoryScale;
|
||||
|
||||
CategoryScale = new LinearScale { Output = CategoryScale.Output };
|
||||
ValueScale = new LinearScale { Output = ValueScale.Output };
|
||||
|
||||
var visibleSeries = Series.Where(series => series.Visible).ToList();
|
||||
|
||||
if (!visibleSeries.Any() && invisibleSeries.Any())
|
||||
{
|
||||
visibleSeries.Add(invisibleSeries.Last());
|
||||
}
|
||||
|
||||
foreach (var series in visibleSeries)
|
||||
{
|
||||
CategoryScale = series.TransformCategoryScale(CategoryScale);
|
||||
ValueScale = series.TransformValueScale(ValueScale);
|
||||
}
|
||||
|
||||
AxisBase xAxis = CategoryAxis;
|
||||
AxisBase yAxis = ValueAxis;
|
||||
|
||||
if (ShouldInvertAxes())
|
||||
{
|
||||
xAxis = ValueAxis;
|
||||
yAxis = CategoryAxis;
|
||||
}
|
||||
else
|
||||
{
|
||||
CategoryScale.Padding = CategoryAxis.Padding;
|
||||
}
|
||||
|
||||
CategoryScale.Resize(xAxis.Min, xAxis.Max);
|
||||
|
||||
if (xAxis.Step != null)
|
||||
{
|
||||
CategoryScale.Step = xAxis.Step;
|
||||
CategoryScale.Round = false;
|
||||
}
|
||||
|
||||
ValueScale.Resize(yAxis.Min, yAxis.Max);
|
||||
|
||||
if (yAxis.Step != null)
|
||||
{
|
||||
ValueScale.Step = yAxis.Step;
|
||||
ValueScale.Round = false;
|
||||
}
|
||||
|
||||
var legendSize = Legend.Measure(this);
|
||||
var valueAxisSize = ValueAxis.Measure(this);
|
||||
var categoryAxisSize = CategoryAxis.Measure(this);
|
||||
|
||||
if (!ShouldRenderAxes())
|
||||
{
|
||||
valueAxisSize = categoryAxisSize = 0;
|
||||
}
|
||||
|
||||
MarginTop = MarginRight = 32;
|
||||
MarginLeft = valueAxisSize;
|
||||
MarginBottom = Math.Max(32, categoryAxisSize);
|
||||
|
||||
if (Legend.Visible)
|
||||
{
|
||||
if (Legend.Position == LegendPosition.Right || Legend.Position == LegendPosition.Left)
|
||||
{
|
||||
if (Legend.Position == LegendPosition.Right)
|
||||
{
|
||||
MarginRight = legendSize + 16;
|
||||
}
|
||||
else
|
||||
{
|
||||
MarginLeft = legendSize + 16 + valueAxisSize;
|
||||
}
|
||||
}
|
||||
else if (Legend.Position == LegendPosition.Top || Legend.Position == LegendPosition.Bottom)
|
||||
{
|
||||
if (Legend.Position == LegendPosition.Top)
|
||||
{
|
||||
MarginTop = legendSize + 16;
|
||||
}
|
||||
else
|
||||
{
|
||||
MarginBottom = legendSize + 16 + categoryAxisSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CategoryScale.Output = new ScaleRange { Start = MarginLeft, End = Width.Value - MarginRight };
|
||||
ValueScale.Output = new ScaleRange { Start = Height.Value - MarginBottom, End = MarginTop };
|
||||
|
||||
ValueScale.Fit(ValueAxis.TickDistance);
|
||||
CategoryScale.Fit(CategoryAxis.TickDistance);
|
||||
|
||||
var stateHasChanged = false;
|
||||
|
||||
if (!ValueScale.IsEqualTo(valueScale))
|
||||
{
|
||||
stateHasChanged = true;
|
||||
}
|
||||
|
||||
if (!CategoryScale.IsEqualTo(categoryScale))
|
||||
{
|
||||
stateHasChanged = true;
|
||||
}
|
||||
|
||||
return stateHasChanged;
|
||||
}
|
||||
|
||||
[JSInvokable]
|
||||
public void Resize(double width, double height)
|
||||
{
|
||||
var stateHasChanged = false;
|
||||
|
||||
if (width != Width)
|
||||
{
|
||||
Width = width;
|
||||
stateHasChanged = true;
|
||||
|
||||
CategoryScale.Output = new ScaleRange { Start = MarginLeft, End = Width.Value - MarginRight };
|
||||
}
|
||||
|
||||
if (height != Height)
|
||||
{
|
||||
Height = height;
|
||||
stateHasChanged = true;
|
||||
|
||||
ValueScale.Output = new ScaleRange { Start = Height.Value - MarginBottom, End = MarginTop };
|
||||
}
|
||||
|
||||
if (stateHasChanged)
|
||||
{
|
||||
Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
RenderFragment tooltip;
|
||||
object tooltipData;
|
||||
|
||||
[JSInvokable]
|
||||
public void MouseMove(double x, double y)
|
||||
{
|
||||
if (Tooltip.Visible)
|
||||
{
|
||||
foreach (var series in Series)
|
||||
{
|
||||
if (series.Visible && series.Contains(x - MarginLeft, y - MarginTop))
|
||||
{
|
||||
var data = series.DataAt(x - MarginLeft, y - MarginTop);
|
||||
|
||||
if (data != tooltipData)
|
||||
{
|
||||
tooltipData = data;
|
||||
tooltip = series.RenderTooltip(data, MarginLeft, MarginTop);
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (tooltip != null)
|
||||
{
|
||||
tooltipData = null;
|
||||
tooltip = null;
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private IList<IChartSeries> invisibleSeries = new List<IChartSeries>();
|
||||
|
||||
internal void ToggleSeries(IChartSeries series)
|
||||
{
|
||||
series.Visible = !series.Visible;
|
||||
|
||||
if (series.Visible)
|
||||
{
|
||||
invisibleSeries.Remove(series);
|
||||
}
|
||||
else
|
||||
{
|
||||
invisibleSeries.Add(series);
|
||||
}
|
||||
|
||||
Refresh();
|
||||
}
|
||||
|
||||
private bool widthAndHeightAreSet = false;
|
||||
private bool firstRender = true;
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
this.firstRender = firstRender;
|
||||
|
||||
if (firstRender || visibleChanged)
|
||||
{
|
||||
visibleChanged = false;
|
||||
|
||||
if (Visible)
|
||||
{
|
||||
var rect = await JSRuntime.InvokeAsync<Rect>("Radzen.createChart", Element, Reference);
|
||||
|
||||
if (!widthAndHeightAreSet)
|
||||
{
|
||||
widthAndHeightAreSet = true;
|
||||
|
||||
Resize(rect.Width, rect.Height);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal string ClipPath { get; set; }
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
base.OnInitialized();
|
||||
|
||||
ClipPath = $"clipPath{UniqueID}";
|
||||
CategoryAxis.Chart = this;
|
||||
ValueAxis.Chart = this;
|
||||
|
||||
Initialize();
|
||||
}
|
||||
|
||||
private void Initialize()
|
||||
{
|
||||
double width = 0;
|
||||
double height = 0;
|
||||
|
||||
if (CurrentStyle.ContainsKey("height"))
|
||||
{
|
||||
var pixelHeight = CurrentStyle["height"];
|
||||
|
||||
if (pixelHeight.EndsWith("px"))
|
||||
{
|
||||
height = Convert.ToDouble(pixelHeight.TrimEnd("px".ToCharArray()));
|
||||
}
|
||||
}
|
||||
|
||||
if (CurrentStyle.ContainsKey("width"))
|
||||
{
|
||||
var pixelWidth = CurrentStyle["width"];
|
||||
|
||||
if (pixelWidth.EndsWith("px"))
|
||||
{
|
||||
width = Convert.ToDouble(pixelWidth.TrimEnd("px".ToCharArray()));
|
||||
}
|
||||
}
|
||||
|
||||
if (width > 0 && height > 0)
|
||||
{
|
||||
widthAndHeightAreSet = true;
|
||||
|
||||
Width = width;
|
||||
Height = height;
|
||||
|
||||
CategoryScale.Output = new ScaleRange { Start = MarginLeft, End = Width.Value - MarginRight };
|
||||
ValueScale.Output = new ScaleRange { Start = Height.Value - MarginBottom, End = MarginTop };
|
||||
}
|
||||
}
|
||||
|
||||
private bool visibleChanged = false;
|
||||
|
||||
public override async Task SetParametersAsync(ParameterView parameters)
|
||||
{
|
||||
bool shouldRefresh = parameters.DidParameterChange(nameof(Style), Style);
|
||||
|
||||
visibleChanged = parameters.DidParameterChange(nameof(Visible), Visible);
|
||||
|
||||
await base.SetParametersAsync(parameters);
|
||||
|
||||
if (shouldRefresh)
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
|
||||
if (visibleChanged && !firstRender)
|
||||
{
|
||||
if (Visible == false)
|
||||
{
|
||||
await JSRuntime.InvokeVoidAsync("Radzen.destroyChart", Element);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void Refresh(bool force = true)
|
||||
{
|
||||
if (widthAndHeightAreSet)
|
||||
{
|
||||
var stateHasChanged = UpdateScales();
|
||||
|
||||
if (stateHasChanged || force)
|
||||
{
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Reload()
|
||||
{
|
||||
Refresh(true);
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
base.Dispose();
|
||||
|
||||
if (Visible)
|
||||
{
|
||||
JSRuntime.InvokeVoidAsync("Radzen.destroyChart", Element);
|
||||
}
|
||||
}
|
||||
|
||||
protected override string GetComponentCssClass()
|
||||
{
|
||||
return $"rz-chart rz-scheme-{ColorScheme.ToString().ToLower()}";
|
||||
}
|
||||
}
|
||||
|
||||
495
Radzen.Blazor/RadzenChart.razor.cs
Normal file
495
Radzen.Blazor/RadzenChart.razor.cs
Normal file
@@ -0,0 +1,495 @@
|
||||
using Microsoft.JSInterop;
|
||||
using Radzen.Blazor.Rendering;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using System.Linq;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// Displays line, area, donut, pie, bar or column series.
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// <RadzenChart>
|
||||
/// <RadzenColumnSeries Data=@revenue CategoryProperty="Quarter" ValueProperty="Revenue" />
|
||||
/// </RadzenChart>
|
||||
/// @code {
|
||||
/// class DataItem
|
||||
/// {
|
||||
/// public string Quarter { get; set; }
|
||||
/// public double Revenue { get; set; }
|
||||
/// }
|
||||
/// DataItem[] revenue = new DataItem[]
|
||||
/// {
|
||||
/// new DataItem { Quarter = "Q1", Revenue = 234000 },
|
||||
/// new DataItem { Quarter = "Q2", Revenue = 284000 },
|
||||
/// new DataItem { Quarter = "Q3", Revenue = 274000 },
|
||||
/// new DataItem { Quarter = "Q4", Revenue = 294000 }
|
||||
/// };
|
||||
/// }
|
||||
/// </code>
|
||||
/// </example>
|
||||
public partial class RadzenChart : RadzenComponent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the color scheme used to render the series.
|
||||
/// </summary>
|
||||
/// <value>The color scheme.</value>
|
||||
[Parameter]
|
||||
public ColorScheme ColorScheme { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public EventCallback<LegendClickEventArgs> LegendClick { get; set; }
|
||||
double? Width { get; set; }
|
||||
|
||||
double? Height { get; set; }
|
||||
|
||||
double MarginTop { get; set; }
|
||||
|
||||
double MarginLeft { get; set; }
|
||||
|
||||
double MarginRight { get; set; }
|
||||
|
||||
double MarginBottom { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the child content. Used to specify series and other configuration.
|
||||
/// </summary>
|
||||
/// <value>The child content.</value>
|
||||
[Parameter]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
|
||||
internal ScaleBase CategoryScale { get; set; } = new LinearScale();
|
||||
internal ScaleBase ValueScale { get; set; } = new LinearScale();
|
||||
internal IList<IChartSeries> Series { get; set; } = new List<IChartSeries>();
|
||||
internal RadzenColumnOptions ColumnOptions { get; set; } = new RadzenColumnOptions();
|
||||
internal RadzenBarOptions BarOptions { get; set; } = new RadzenBarOptions();
|
||||
internal RadzenLegend Legend { get; set; } = new RadzenLegend();
|
||||
internal RadzenCategoryAxis CategoryAxis { get; set; } = new RadzenCategoryAxis();
|
||||
internal RadzenValueAxis ValueAxis { get; set; } = new RadzenValueAxis();
|
||||
internal RadzenChartTooltipOptions Tooltip { get; set; } = new RadzenChartTooltipOptions();
|
||||
internal void AddSeries(IChartSeries series)
|
||||
{
|
||||
if (!Series.Contains(series))
|
||||
{
|
||||
Series.Add(series);
|
||||
}
|
||||
}
|
||||
|
||||
internal void RemoveSeries(IChartSeries series)
|
||||
{
|
||||
Series.Remove(series);
|
||||
}
|
||||
|
||||
private bool ShouldRenderAxes()
|
||||
{
|
||||
var pieType = typeof(RadzenPieSeries<>);
|
||||
var donutType = typeof(RadzenDonutSeries<>);
|
||||
|
||||
return !Series.All(series =>
|
||||
{
|
||||
var type = series.GetType().GetGenericTypeDefinition();
|
||||
|
||||
return type == pieType || type == donutType;
|
||||
});
|
||||
}
|
||||
|
||||
internal bool ShouldInvertAxes()
|
||||
{
|
||||
return Series.Count > 0 && Series.All(series => series is IChartBarSeries);
|
||||
}
|
||||
|
||||
private bool UpdateScales()
|
||||
{
|
||||
var valueScale = ValueScale;
|
||||
var categoryScale = CategoryScale;
|
||||
|
||||
CategoryScale = new LinearScale { Output = CategoryScale.Output };
|
||||
ValueScale = new LinearScale { Output = ValueScale.Output };
|
||||
|
||||
var visibleSeries = Series.Where(series => series.Visible).ToList();
|
||||
var invisibleSeries = Series.Where(series => series.Visible == false).ToList();
|
||||
|
||||
if (!visibleSeries.Any() && invisibleSeries.Any())
|
||||
{
|
||||
visibleSeries.Add(invisibleSeries.Last());
|
||||
}
|
||||
|
||||
foreach (var series in visibleSeries)
|
||||
{
|
||||
CategoryScale = series.TransformCategoryScale(CategoryScale);
|
||||
ValueScale = series.TransformValueScale(ValueScale);
|
||||
}
|
||||
|
||||
AxisBase xAxis = CategoryAxis;
|
||||
AxisBase yAxis = ValueAxis;
|
||||
|
||||
if (ShouldInvertAxes())
|
||||
{
|
||||
xAxis = ValueAxis;
|
||||
yAxis = CategoryAxis;
|
||||
}
|
||||
else
|
||||
{
|
||||
CategoryScale.Padding = CategoryAxis.Padding;
|
||||
}
|
||||
|
||||
CategoryScale.Resize(xAxis.Min, xAxis.Max);
|
||||
|
||||
if (xAxis.Step != null)
|
||||
{
|
||||
CategoryScale.Step = xAxis.Step;
|
||||
CategoryScale.Round = false;
|
||||
}
|
||||
|
||||
ValueScale.Resize(yAxis.Min, yAxis.Max);
|
||||
|
||||
if (yAxis.Step != null)
|
||||
{
|
||||
ValueScale.Step = yAxis.Step;
|
||||
ValueScale.Round = false;
|
||||
}
|
||||
|
||||
var legendSize = Legend.Measure(this);
|
||||
var valueAxisSize = ValueAxis.Measure(this);
|
||||
var categoryAxisSize = CategoryAxis.Measure(this);
|
||||
|
||||
if (!ShouldRenderAxes())
|
||||
{
|
||||
valueAxisSize = categoryAxisSize = 0;
|
||||
}
|
||||
|
||||
MarginTop = MarginRight = 32;
|
||||
MarginLeft = valueAxisSize;
|
||||
MarginBottom = Math.Max(32, categoryAxisSize);
|
||||
|
||||
if (Legend.Visible)
|
||||
{
|
||||
if (Legend.Position == LegendPosition.Right || Legend.Position == LegendPosition.Left)
|
||||
{
|
||||
if (Legend.Position == LegendPosition.Right)
|
||||
{
|
||||
MarginRight = legendSize + 16;
|
||||
}
|
||||
else
|
||||
{
|
||||
MarginLeft = legendSize + 16 + valueAxisSize;
|
||||
}
|
||||
}
|
||||
else if (Legend.Position == LegendPosition.Top || Legend.Position == LegendPosition.Bottom)
|
||||
{
|
||||
if (Legend.Position == LegendPosition.Top)
|
||||
{
|
||||
MarginTop = legendSize + 16;
|
||||
}
|
||||
else
|
||||
{
|
||||
MarginBottom = legendSize + 16 + categoryAxisSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CategoryScale.Output = new ScaleRange { Start = MarginLeft, End = Width.Value - MarginRight };
|
||||
ValueScale.Output = new ScaleRange { Start = Height.Value - MarginBottom, End = MarginTop };
|
||||
|
||||
ValueScale.Fit(ValueAxis.TickDistance);
|
||||
CategoryScale.Fit(CategoryAxis.TickDistance);
|
||||
|
||||
var stateHasChanged = false;
|
||||
|
||||
if (!ValueScale.IsEqualTo(valueScale))
|
||||
{
|
||||
stateHasChanged = true;
|
||||
}
|
||||
|
||||
if (!CategoryScale.IsEqualTo(categoryScale))
|
||||
{
|
||||
stateHasChanged = true;
|
||||
}
|
||||
|
||||
return stateHasChanged;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invoked via interop when the RadzenChart resizes. Display the series with the new dimensions.
|
||||
/// </summary>
|
||||
/// <param name="width">The width.</param>
|
||||
/// <param name="height">The height.</param>
|
||||
[JSInvokable]
|
||||
public async Task Resize(double width, double height)
|
||||
{
|
||||
var stateHasChanged = false;
|
||||
|
||||
if (width != Width)
|
||||
{
|
||||
Width = width;
|
||||
stateHasChanged = true;
|
||||
|
||||
CategoryScale.Output = new ScaleRange { Start = MarginLeft, End = Width.Value - MarginRight };
|
||||
}
|
||||
|
||||
if (height != Height)
|
||||
{
|
||||
Height = height;
|
||||
stateHasChanged = true;
|
||||
|
||||
ValueScale.Output = new ScaleRange { Start = Height.Value - MarginBottom, End = MarginTop };
|
||||
}
|
||||
|
||||
if (stateHasChanged)
|
||||
{
|
||||
await Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
RenderFragment tooltip;
|
||||
object tooltipData;
|
||||
double mouseX;
|
||||
double mouseY;
|
||||
|
||||
/// <summary>
|
||||
/// Invoked via interop when the user moves the mouse over the RadzenChart. Displays the tooltip.
|
||||
/// </summary>
|
||||
/// <param name="x">The x.</param>
|
||||
/// <param name="y">The y.</param>
|
||||
[JSInvokable]
|
||||
public async Task MouseMove(double x, double y)
|
||||
{
|
||||
mouseX = x;
|
||||
mouseY = y;
|
||||
|
||||
await DisplayTooltip();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invoked via interop when the user clicks the RadzenChart. Raises the <see cref="SeriesClick" /> handler.
|
||||
/// </summary>
|
||||
/// <param name="x">The x.</param>
|
||||
/// <param name="y">The y.</param>
|
||||
[JSInvokable]
|
||||
public async Task Click(double x, double y)
|
||||
{
|
||||
foreach (var series in Series)
|
||||
{
|
||||
if (series.Visible && series.Contains(mouseX - MarginLeft, mouseY - MarginTop, 5))
|
||||
{
|
||||
var data = series.DataAt(mouseX - MarginLeft, mouseY - MarginTop);
|
||||
|
||||
if (data != null)
|
||||
{
|
||||
await series.InvokeClick(SeriesClick, data);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal async Task DisplayTooltip()
|
||||
{
|
||||
if (Tooltip.Visible)
|
||||
{
|
||||
var orderedSeries = Series.OrderBy(s => s.RenderingOrder).Reverse();
|
||||
|
||||
foreach (var series in orderedSeries)
|
||||
{
|
||||
if (series.Visible)
|
||||
{
|
||||
foreach (var overlay in series.Overlays.Reverse())
|
||||
{
|
||||
if (overlay.Visible && overlay.Contains(mouseX - MarginLeft, mouseY - MarginTop, 25))
|
||||
{
|
||||
tooltipData = null;
|
||||
tooltip = overlay.RenderTooltip(mouseX, mouseY, MarginLeft, MarginTop);
|
||||
StateHasChanged();
|
||||
await Task.Yield();
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (series.Contains(mouseX - MarginLeft, mouseY - MarginTop, 25))
|
||||
{
|
||||
var data = series.DataAt(mouseX - MarginLeft, mouseY - MarginTop);
|
||||
|
||||
if (data != tooltipData)
|
||||
{
|
||||
tooltipData = data;
|
||||
tooltip = series.RenderTooltip(data, MarginLeft, MarginTop);
|
||||
StateHasChanged();
|
||||
await Task.Yield();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tooltip != null)
|
||||
{
|
||||
tooltipData = null;
|
||||
tooltip = null;
|
||||
|
||||
StateHasChanged();
|
||||
await Task.Yield();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool widthAndHeightAreSet = false;
|
||||
private bool firstRender = true;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
await base.OnAfterRenderAsync(firstRender);
|
||||
|
||||
this.firstRender = firstRender;
|
||||
|
||||
if (firstRender || visibleChanged)
|
||||
{
|
||||
visibleChanged = false;
|
||||
|
||||
if (Visible)
|
||||
{
|
||||
var rect = await JSRuntime.InvokeAsync<Rect>("Radzen.createChart", Element, Reference);
|
||||
|
||||
if (!widthAndHeightAreSet)
|
||||
{
|
||||
widthAndHeightAreSet = true;
|
||||
|
||||
await Resize(rect.Width, rect.Height);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal string ClipPath { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
base.OnInitialized();
|
||||
|
||||
ClipPath = $"clipPath{UniqueID}";
|
||||
CategoryAxis.Chart = this;
|
||||
ValueAxis.Chart = this;
|
||||
|
||||
Initialize();
|
||||
}
|
||||
|
||||
private void Initialize()
|
||||
{
|
||||
double width = 0;
|
||||
double height = 0;
|
||||
|
||||
if (CurrentStyle.ContainsKey("height"))
|
||||
{
|
||||
var pixelHeight = CurrentStyle["height"];
|
||||
|
||||
if (pixelHeight.EndsWith("px"))
|
||||
{
|
||||
height = Convert.ToDouble(pixelHeight.TrimEnd("px".ToCharArray()));
|
||||
}
|
||||
}
|
||||
|
||||
if (CurrentStyle.ContainsKey("width"))
|
||||
{
|
||||
var pixelWidth = CurrentStyle["width"];
|
||||
|
||||
if (pixelWidth.EndsWith("px"))
|
||||
{
|
||||
width = Convert.ToDouble(pixelWidth.TrimEnd("px".ToCharArray()));
|
||||
}
|
||||
}
|
||||
|
||||
if (width > 0 && height > 0)
|
||||
{
|
||||
widthAndHeightAreSet = true;
|
||||
|
||||
Width = width;
|
||||
Height = height;
|
||||
|
||||
CategoryScale.Output = new ScaleRange { Start = MarginLeft, End = Width.Value - MarginRight };
|
||||
ValueScale.Output = new ScaleRange { Start = Height.Value - MarginBottom, End = MarginTop };
|
||||
}
|
||||
}
|
||||
|
||||
private bool visibleChanged = false;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override async Task SetParametersAsync(ParameterView parameters)
|
||||
{
|
||||
bool shouldRefresh = parameters.DidParameterChange(nameof(Style), Style);
|
||||
|
||||
visibleChanged = parameters.DidParameterChange(nameof(Visible), Visible);
|
||||
|
||||
await base.SetParametersAsync(parameters);
|
||||
|
||||
if (shouldRefresh)
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
|
||||
if (visibleChanged && !firstRender)
|
||||
{
|
||||
if (Visible == false)
|
||||
{
|
||||
await JSRuntime.InvokeVoidAsync("Radzen.destroyChart", Element);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal async Task Refresh(bool force = true)
|
||||
{
|
||||
if (widthAndHeightAreSet)
|
||||
{
|
||||
|
||||
var stateHasChanged = UpdateScales();
|
||||
|
||||
if (stateHasChanged || force)
|
||||
{
|
||||
StateHasChanged();
|
||||
await DisplayTooltip();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Causes all series to refresh. Use it when <see cref="CartesianSeries{TItem}.Data" /> has changed.
|
||||
/// </summary>
|
||||
public async Task Reload()
|
||||
{
|
||||
await Refresh(true);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Dispose()
|
||||
{
|
||||
base.Dispose();
|
||||
|
||||
if (Visible && IsJSRuntimeAvailable)
|
||||
{
|
||||
JSRuntime.InvokeVoidAsync("Radzen.destroyChart", Element);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override string GetComponentCssClass()
|
||||
{
|
||||
return $"rz-chart rz-scheme-{ColorScheme.ToString().ToLowerInvariant()}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,19 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class of components that are rendered inside a <see cref="RadzenChart" />.
|
||||
/// </summary>
|
||||
public abstract class RadzenChartComponentBase : ComponentBase
|
||||
{
|
||||
private RadzenChart chart;
|
||||
|
||||
/// <summary>
|
||||
/// Used to inject the RadzenChart instance. Invokes <see cref="Initialize" />.
|
||||
/// </summary>
|
||||
/// <value>The chart.</value>
|
||||
[CascadingParameter]
|
||||
public RadzenChart Chart
|
||||
{
|
||||
@@ -22,16 +28,24 @@ namespace Radzen.Blazor
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform initialization when <see cref="Chart" /> is set.
|
||||
/// </summary>
|
||||
protected virtual void Initialize()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if RadzenChart should render.
|
||||
/// </summary>
|
||||
/// <param name="parameters">The parameters.</param>
|
||||
protected virtual bool ShouldRefreshChart(ParameterView parameters)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override async Task SetParametersAsync(ParameterView parameters)
|
||||
{
|
||||
bool shouldRefresh = ShouldRefreshChart(parameters);
|
||||
@@ -42,14 +56,25 @@ namespace Radzen.Blazor
|
||||
|
||||
if (shouldRefresh)
|
||||
{
|
||||
Chart.Refresh();
|
||||
await Chart.Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates the parameters.
|
||||
/// </summary>
|
||||
protected virtual void ValidateParameters()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the specified parameter changed.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="parameters">The parameters.</param>
|
||||
/// <param name="parameterName">Name of the parameter.</param>
|
||||
/// <param name="parameterValue">The parameter value.</param>
|
||||
/// <returns><c>true</c> if the parameter changed, <c>false</c> otherwise.</returns>
|
||||
protected bool DidParameterChange<T>(ParameterView parameters, string parameterName, T parameterValue)
|
||||
{
|
||||
return parameters.DidParameterChange(parameterName, parameterValue);
|
||||
|
||||
36
Radzen.Blazor/RadzenChartTooltipOptions.cs
Normal file
36
Radzen.Blazor/RadzenChartTooltipOptions.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace Radzen.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains <see cref="RadzenChart" /> tooltip configuration.
|
||||
/// </summary>
|
||||
public partial class RadzenChartTooltipOptions : RadzenChartComponentBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to show tooltips. By defaults RadzenChart displays tooltips.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> to display tooltips; otherwise, <c>false</c>.</value>
|
||||
[Parameter]
|
||||
public bool Visible { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the CSS style of the tooltip.
|
||||
/// </summary>
|
||||
/// <value>The style.</value>
|
||||
[Parameter]
|
||||
public string Style { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Initialize()
|
||||
{
|
||||
Chart.Tooltip = this;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override bool ShouldRefreshChart(ParameterView parameters)
|
||||
{
|
||||
return parameters.DidParameterChange(nameof(Style), Style);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
@inherits RadzenChartComponentBase
|
||||
@code {
|
||||
[Parameter]
|
||||
public bool Visible { get; set; } = true;
|
||||
|
||||
[Parameter]
|
||||
public string Style { get; set; }
|
||||
|
||||
protected override void Initialize()
|
||||
{
|
||||
Chart.Tooltip = this;
|
||||
}
|
||||
|
||||
protected override bool ShouldRefreshChart(ParameterView parameters)
|
||||
{
|
||||
return parameters.DidParameterChange(nameof(Style), Style);
|
||||
}
|
||||
}
|
||||
@@ -1,88 +1,17 @@
|
||||
@using Radzen
|
||||
@using Radzen.Blazor.Rendering
|
||||
@using Microsoft.AspNetCore.Components.Forms
|
||||
@typeparam TValue
|
||||
@inherits FormComponent<TValue>
|
||||
@if (Visible)
|
||||
{
|
||||
<div @ref="@Element" @attributes="Attributes" class="@GetCssClass()"
|
||||
@onmouseup="@OnMouseUp" @onkeypress="@(async (args) => { if (args.Code == "Space") { await Toggle(); } })" style="@Style" tabindex="@TabIndex" id="@GetId()">
|
||||
<div class="rz-helper-hidden-accessible">
|
||||
<input type="text" name="@Name" value="@Value" tabindex="-1">
|
||||
</div>
|
||||
<div class="@getInnerCssClass()">
|
||||
<span class="@getCheckBoxCssClass()"></span>
|
||||
</div>
|
||||
<div @ref="@Element" @attributes="Attributes" class="@GetCssClass()" @onkeypress=@OnKeyPress @onkeypress:preventDefault style="@Style" tabindex="@(Disabled ? "-1" : $"{TabIndex}")" id="@GetId()">
|
||||
<div class="rz-helper-hidden-accessible">
|
||||
<input type="checkbox" @onchange=@Toggle value=@CheckBoxValue name=@Name id=@Name checked=@CheckBoxChecked
|
||||
tabindex="-1">
|
||||
</div>
|
||||
}
|
||||
@code {
|
||||
[Parameter]
|
||||
public bool TriState { get; set; } = false;
|
||||
|
||||
string getInnerCssClass()
|
||||
{
|
||||
string activeState = !object.Equals(Value, false) ? " rz-state-active" : "";
|
||||
string disabledState = Disabled ? " rz-state-disabled" : "";
|
||||
return $"rz-chkbox-box {activeState}{disabledState}";
|
||||
}
|
||||
|
||||
string getCheckBoxCssClass()
|
||||
{
|
||||
if (object.Equals(Value, true))
|
||||
{
|
||||
return "rz-chkbox-icon rzi rzi-check";
|
||||
}
|
||||
else if (object.Equals(Value, false))
|
||||
{
|
||||
return "rz-chkbox-icon";
|
||||
}
|
||||
else if (object.Equals(Value, null))
|
||||
{
|
||||
return "rz-chkbox-icon rzi rzi-times";
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
protected override string GetComponentCssClass()
|
||||
{
|
||||
var fieldCssClass = FieldIdentifier.FieldName != null ? EditContext?.FieldCssClass(FieldIdentifier) : "";
|
||||
return $"rz-chkbox {(Disabled ? " rz-state-disabled" : "")} {fieldCssClass}";
|
||||
}
|
||||
|
||||
public async Task OnMouseUp(MouseEventArgs args)
|
||||
{
|
||||
await Toggle();
|
||||
}
|
||||
|
||||
async System.Threading.Tasks.Task Toggle()
|
||||
{
|
||||
if (Disabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (object.Equals(Value, false))
|
||||
{
|
||||
if (TriState)
|
||||
{
|
||||
Value = default(TValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
Value = (TValue)(object)true;
|
||||
}
|
||||
}
|
||||
else if (Value == null)
|
||||
{
|
||||
Value = (TValue)(object)true;
|
||||
}
|
||||
else if (object.Equals(Value, true))
|
||||
{
|
||||
Value = (TValue)(object)false;
|
||||
}
|
||||
|
||||
await ValueChanged.InvokeAsync(Value);
|
||||
if (FieldIdentifier.FieldName != null) { EditContext?.NotifyFieldChanged(FieldIdentifier); }
|
||||
await Change.InvokeAsync(Value);
|
||||
}
|
||||
<div class=@BoxClassList @onclick=@Toggle @onclick:preventDefault>
|
||||
<span class=@IconClassList></span>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user