kopia lustrzana https://github.com/wagtail/wagtail
Porównaj commity
654 Commity
Autor | SHA1 | Data |
---|---|---|
![]() |
917e74661b | |
![]() |
714e5c0f62 | |
![]() |
d18ea820bf | |
![]() |
e28cb2930e | |
![]() |
32e1366534 | |
![]() |
e86fdb1899 | |
![]() |
01a47c3e37 | |
![]() |
24179dc418 | |
![]() |
5e0b0b56b6 | |
![]() |
0b683aa320 | |
![]() |
26e65b5c01 | |
![]() |
1dc0fd0441 | |
![]() |
7a68f466f3 | |
![]() |
b87372a5ba | |
![]() |
49dafb1e76 | |
![]() |
2d4c2b0ed5 | |
![]() |
2a0a864eb9 | |
![]() |
b94683d5b1 | |
![]() |
1bc88e77a2 | |
![]() |
d555bd6186 | |
![]() |
51291a77de | |
![]() |
faca901a89 | |
![]() |
28be91e258 | |
![]() |
3b1bed811f | |
![]() |
ca7e9bd65a | |
![]() |
136e0a8461 | |
![]() |
b27deeaaa9 | |
![]() |
d9a09a7442 | |
![]() |
4b990df86a | |
![]() |
cfda3a6ad2 | |
![]() |
f3e2084b3a | |
![]() |
a3352a8676 | |
![]() |
32f4a78c96 | |
![]() |
5b429e24d6 | |
![]() |
8a9d05eef5 | |
![]() |
c6c996b54c | |
![]() |
c4922ccd39 | |
![]() |
273d231992 | |
![]() |
32ec338538 | |
![]() |
9fe5987549 | |
![]() |
5c30b4211a | |
![]() |
c663911b9c | |
![]() |
730ce4c092 | |
![]() |
8054801f3e | |
![]() |
934aa79789 | |
![]() |
014f6b2b35 | |
![]() |
46c7c60b49 | |
![]() |
9f04de83d5 | |
![]() |
97975b5293 | |
![]() |
cc345cff54 | |
![]() |
edf7c66fac | |
![]() |
db3a695695 | |
![]() |
125a749a9a | |
![]() |
d0f28a1a69 | |
![]() |
39e4db4e39 | |
![]() |
5c97298e15 | |
![]() |
45f89a335d | |
![]() |
2fbf6b5f06 | |
![]() |
7b5d772b21 | |
![]() |
6a7917697c | |
![]() |
d3341e8fa7 | |
![]() |
9eac93a565 | |
![]() |
6b40a38346 | |
![]() |
8faa15175c | |
![]() |
103ea61702 | |
![]() |
68a3bd4725 | |
![]() |
6938786444 | |
![]() |
6d01356ec6 | |
![]() |
c38db51559 | |
![]() |
04a174f0f2 | |
![]() |
6a0bd93e5b | |
![]() |
397edf2ec5 | |
![]() |
5015eddef3 | |
![]() |
2ab55ac3c8 | |
![]() |
3f70a0a52f | |
![]() |
f649856cf4 | |
![]() |
0745ae53da | |
![]() |
2b882743ec | |
![]() |
96f9ebe3f6 | |
![]() |
abb7a687e4 | |
![]() |
a20c55a9bc | |
![]() |
51629e8488 | |
![]() |
a56888a7ab | |
![]() |
d0e106b403 | |
![]() |
1f210831dd | |
![]() |
13dbf61323 | |
![]() |
a80f40999e | |
![]() |
8cdbbcfe29 | |
![]() |
8f640a8cdb | |
![]() |
a983dc220b | |
![]() |
de99b8b90f | |
![]() |
57fcb353d8 | |
![]() |
322d7e1620 | |
![]() |
6bbd109072 | |
![]() |
8654aadb63 | |
![]() |
f0c7e88d0e | |
![]() |
8e4a721525 | |
![]() |
8e8770d334 | |
![]() |
52ac35acea | |
![]() |
ee83938fa5 | |
![]() |
3c628b8ad2 | |
![]() |
1772909551 | |
![]() |
3c09da2fb8 | |
![]() |
472c1e95c2 | |
![]() |
5ccea76e3d | |
![]() |
9edb8be32d | |
![]() |
7b7dd98c19 | |
![]() |
85665af504 | |
![]() |
83ec67d6c1 | |
![]() |
c793d302b4 | |
![]() |
bfcd0c7496 | |
![]() |
3d9a868a97 | |
![]() |
cbfaecdfae | |
![]() |
b82f0fb150 | |
![]() |
9dcdaeecfc | |
![]() |
dbf920e00c | |
![]() |
d9de2d781f | |
![]() |
a81b119821 | |
![]() |
8998549807 | |
![]() |
871f12934f | |
![]() |
da57f04b80 | |
![]() |
aae7d85153 | |
![]() |
21b5e3114f | |
![]() |
2d2953a28a | |
![]() |
e8a3d753e3 | |
![]() |
e67836da34 | |
![]() |
b59539c7d6 | |
![]() |
df6a3d8256 | |
![]() |
4016cbeafb | |
![]() |
a6f2a68aae | |
![]() |
8559ae9d68 | |
![]() |
1f1956246e | |
![]() |
6505a02d61 | |
![]() |
855dcd4bb6 | |
![]() |
eb36ff3570 | |
![]() |
41a36333ff | |
![]() |
de30668dad | |
![]() |
4a1497437c | |
![]() |
399df657a9 | |
![]() |
35b71a0b7b | |
![]() |
0c168e302a | |
![]() |
f2ebae3343 | |
![]() |
204df71f40 | |
![]() |
b3202ebf20 | |
![]() |
33ef3d5317 | |
![]() |
732ac35b3f | |
![]() |
fcbd114936 | |
![]() |
add5b57b18 | |
![]() |
6a22961ff2 | |
![]() |
7e299fb267 | |
![]() |
43220b9dde | |
![]() |
78a239175d | |
![]() |
dad755eee8 | |
![]() |
3a2792ea88 | |
![]() |
5b2791f18e | |
![]() |
c09bd91db9 | |
![]() |
3f381892cd | |
![]() |
7c284d9e31 | |
![]() |
cbbc571867 | |
![]() |
311d49b04a | |
![]() |
e8b3cd885d | |
![]() |
a668dea376 | |
![]() |
b1fad0cb61 | |
![]() |
411088da71 | |
![]() |
5ee7e62074 | |
![]() |
f714f8d219 | |
![]() |
2fb27ed018 | |
![]() |
fd7ec28e3d | |
![]() |
786d9eb854 | |
![]() |
8393c5ad2a | |
![]() |
0bcdc4359f | |
![]() |
c986bacd77 | |
![]() |
1c973a7605 | |
![]() |
297a810d10 | |
![]() |
bcf9f55b96 | |
![]() |
aa7b1d58ef | |
![]() |
6847656406 | |
![]() |
f7695bc4e7 | |
![]() |
d1b7c38fa8 | |
![]() |
451195a3de | |
![]() |
952ee04f08 | |
![]() |
3e24fee094 | |
![]() |
81171b1eae | |
![]() |
8dd59b149a | |
![]() |
cbca63c1a3 | |
![]() |
995203f42e | |
![]() |
c865c8a1f3 | |
![]() |
fcf3e257ec | |
![]() |
88abe5872c | |
![]() |
e01aaed00c | |
![]() |
3c81589250 | |
![]() |
33d30d8105 | |
![]() |
182ae8488c | |
![]() |
e23096f354 | |
![]() |
8f6b72b19a | |
![]() |
31f547e103 | |
![]() |
6c7e45b894 | |
![]() |
225d3f384c | |
![]() |
801b1bb067 | |
![]() |
a812b61f60 | |
![]() |
ad70e5fdb6 | |
![]() |
530cc5c355 | |
![]() |
1aecddf34a | |
![]() |
ea30d636d4 | |
![]() |
9294907f31 | |
![]() |
2acd50c2db | |
![]() |
a61cfa678d | |
![]() |
09c7f66e03 | |
![]() |
794fe25e97 | |
![]() |
58584896df | |
![]() |
78ba5f3625 | |
![]() |
9de2f4ddd6 | |
![]() |
9c4136635b | |
![]() |
4f37b011f5 | |
![]() |
251d1d188c | |
![]() |
f309a44075 | |
![]() |
88bb61d32e | |
![]() |
f04af6cc16 | |
![]() |
c6923f43c4 | |
![]() |
af7254a808 | |
![]() |
cb0a358022 | |
![]() |
c70719bfa6 | |
![]() |
14d3341ffd | |
![]() |
58ff3e1067 | |
![]() |
2970a1531e | |
![]() |
7722ffed1e | |
![]() |
88cbfb2875 | |
![]() |
e4748e45de | |
![]() |
b365206d05 | |
![]() |
0193cad5ea | |
![]() |
6cad9c4397 | |
![]() |
6a8298879d | |
![]() |
d9e2714c56 | |
![]() |
bdde31c9ed | |
![]() |
f2f94c4d12 | |
![]() |
db87deb0c8 | |
![]() |
f71be48bb3 | |
![]() |
259770f56d | |
![]() |
a7f00156ad | |
![]() |
335817e289 | |
![]() |
eb4b240791 | |
![]() |
4d6c8b87a1 | |
![]() |
2a42ae4edd | |
![]() |
b66a9bfb64 | |
![]() |
a2eb6ea8ca | |
![]() |
695ff86c87 | |
![]() |
cf19e6ea8e | |
![]() |
4301d4ded2 | |
![]() |
11f7997227 | |
![]() |
30deac59d0 | |
![]() |
6489eae6cf | |
![]() |
77a55e3f60 | |
![]() |
9d496be14c | |
![]() |
29e41ea6fc | |
![]() |
484c71c539 | |
![]() |
4b99a17554 | |
![]() |
2ce58fed95 | |
![]() |
1dd3dbea87 | |
![]() |
0bf909414a | |
![]() |
1422a9d6c4 | |
![]() |
22061091cf | |
![]() |
80c2f928fd | |
![]() |
834afaea54 | |
![]() |
8fbd74a2f0 | |
![]() |
3949026270 | |
![]() |
f25a95deee | |
![]() |
01d7858ba4 | |
![]() |
7f39750de9 | |
![]() |
4244943300 | |
![]() |
9a024bcb42 | |
![]() |
c17c1c859b | |
![]() |
1309f5e7cc | |
![]() |
ac4bd79e40 | |
![]() |
476e7aa35c | |
![]() |
00fd54acda | |
![]() |
63d5ce9d11 | |
![]() |
28d8ba6af7 | |
![]() |
77bcbf702d | |
![]() |
d25a67a4b8 | |
![]() |
efc73a649d | |
![]() |
e236919a79 | |
![]() |
3cbca376a9 | |
![]() |
1636059bef | |
![]() |
fe9409f99c | |
![]() |
1c3f84f9c2 | |
![]() |
03f5352fe0 | |
![]() |
ab7547c6cb | |
![]() |
6a7792e910 | |
![]() |
5cfc4aac6e | |
![]() |
b4781e2a90 | |
![]() |
a2038727a7 | |
![]() |
72808487cd | |
![]() |
1e0b0f3508 | |
![]() |
ca66dcc6af | |
![]() |
e6f27c95e8 | |
![]() |
3f551f212c | |
![]() |
fc4a892aad | |
![]() |
4c8ea0e54c | |
![]() |
3b8e15561d | |
![]() |
7055155183 | |
![]() |
839f95f50b | |
![]() |
c13caa952f | |
![]() |
adf52d85c7 | |
![]() |
3bad585b74 | |
![]() |
7c0712cc38 | |
![]() |
3ea241370d | |
![]() |
841b36ed18 | |
![]() |
06ce7d2868 | |
![]() |
0ccd99c867 | |
![]() |
26f4d07ee1 | |
![]() |
1db66a7ded | |
![]() |
a6b64dc42e | |
![]() |
bc9d5da38f | |
![]() |
0da3c731a5 | |
![]() |
5a0ecb9b30 | |
![]() |
78cd283b9e | |
![]() |
79d129f8c2 | |
![]() |
65d3b34698 | |
![]() |
7af2ca013e | |
![]() |
3e09c75814 | |
![]() |
dcf523416c | |
![]() |
14d16ae823 | |
![]() |
be9b462947 | |
![]() |
8d5fc606a8 | |
![]() |
fc6aee2318 | |
![]() |
7ec01f813e | |
![]() |
3329e6dadf | |
![]() |
4298665bfd | |
![]() |
7e1832a4eb | |
![]() |
b2958e2b4c | |
![]() |
c561977e8d | |
![]() |
9511d7f3ac | |
![]() |
581bb5ccd7 | |
![]() |
54797e3826 | |
![]() |
f3d1765353 | |
![]() |
8b3eb44340 | |
![]() |
88a3a397ca | |
![]() |
782aa0e16b | |
![]() |
cb11ec3e01 | |
![]() |
75e07498f4 | |
![]() |
d20c1b66bf | |
![]() |
da12f4a284 | |
![]() |
944fd02dc3 | |
![]() |
983a86b0b8 | |
![]() |
f0b04200a4 | |
![]() |
c63ac0af4a | |
![]() |
0bba5da337 | |
![]() |
99a9317eea | |
![]() |
4fc2c2abac | |
![]() |
7a59c9cc20 | |
![]() |
9b3acffaac | |
![]() |
d8d75bddf0 | |
![]() |
216b80111b | |
![]() |
3f91fcb3a3 | |
![]() |
09e26c3c2b | |
![]() |
a2407c0027 | |
![]() |
f9debd9084 | |
![]() |
82c42d1ecc | |
![]() |
961aa07547 | |
![]() |
da818b562f | |
![]() |
7cfae8c3b5 | |
![]() |
b97ac14cba | |
![]() |
50fb7b21bb | |
![]() |
996484099b | |
![]() |
f90fae1aee | |
![]() |
784f4bbbb9 | |
![]() |
1cbb1e8fb2 | |
![]() |
df8a6f219c | |
![]() |
2e08d84332 | |
![]() |
5a17312e42 | |
![]() |
3cfbd028e9 | |
![]() |
ac08838115 | |
![]() |
7745aa628d | |
![]() |
23b9f4aca9 | |
![]() |
57d141c701 | |
![]() |
6b33690cd3 | |
![]() |
8bb2a18cd7 | |
![]() |
130a9ebd93 | |
![]() |
58d9f9bc72 | |
![]() |
faa37c0068 | |
![]() |
e63b42b547 | |
![]() |
286d7cbd6b | |
![]() |
01e7291486 | |
![]() |
268174b781 | |
![]() |
aa08e86cba | |
![]() |
076af8bec8 | |
![]() |
5402010d16 | |
![]() |
9889bddcb8 | |
![]() |
ae89829661 | |
![]() |
6bc9b0ea40 | |
![]() |
585d3e3385 | |
![]() |
3d6f1c366f | |
![]() |
8d35cc57e6 | |
![]() |
4020efc4d0 | |
![]() |
d42af56220 | |
![]() |
4760509d65 | |
![]() |
c7700feae2 | |
![]() |
3e75c018be | |
![]() |
32417f9adc | |
![]() |
94d3557cea | |
![]() |
5f3235fa4f | |
![]() |
4bbd26d5a4 | |
![]() |
0d7ea86b2d | |
![]() |
5e88817d2e | |
![]() |
d811066a5b | |
![]() |
4e60e0a82b | |
![]() |
0c23ebed87 | |
![]() |
6db13fb704 | |
![]() |
c498be3234 | |
![]() |
e9ffe38943 | |
![]() |
93382d3f21 | |
![]() |
4ad08ddf6a | |
![]() |
a506b7f0e2 | |
![]() |
e547f5e040 | |
![]() |
3d915733e6 | |
![]() |
e79aed3616 | |
![]() |
63da8b2733 | |
![]() |
f177c02da8 | |
![]() |
547e4d3731 | |
![]() |
23275a4cef | |
![]() |
8cdeb23a43 | |
![]() |
28cde800d9 | |
![]() |
8da1796d53 | |
![]() |
c2676af857 | |
![]() |
cd7977ada8 | |
![]() |
5837d346d9 | |
![]() |
13951cf7a5 | |
![]() |
fceda14872 | |
![]() |
bc34020e0d | |
![]() |
d48cf61701 | |
![]() |
eac7dd92b6 | |
![]() |
047ecff2bb | |
![]() |
233ff2b419 | |
![]() |
8ec4ed0127 | |
![]() |
6047a66663 | |
![]() |
6054245548 | |
![]() |
585b9b4b04 | |
![]() |
acdeb4f8d9 | |
![]() |
4ea2c661c8 | |
![]() |
3a50b2467a | |
![]() |
3a19f450f6 | |
![]() |
26442631c7 | |
![]() |
97d2332ba4 | |
![]() |
4438f13d5c | |
![]() |
918ceebc17 | |
![]() |
f8f99833f2 | |
![]() |
b81b899c0c | |
![]() |
217751e747 | |
![]() |
76925488ad | |
![]() |
789a0c2572 | |
![]() |
9a1c7126e2 | |
![]() |
bda83b061c | |
![]() |
a142363a80 | |
![]() |
a1de5bdbd7 | |
![]() |
839193ff3c | |
![]() |
b7a4271930 | |
![]() |
e74703d9ab | |
![]() |
5815a7e1ef | |
![]() |
b3ba89b2ec | |
![]() |
79c9ce266c | |
![]() |
c416cfb7d6 | |
![]() |
f5a08646c9 | |
![]() |
94de52e912 | |
![]() |
6ec4dafc6a | |
![]() |
836b8138d3 | |
![]() |
ffe294bc7b | |
![]() |
8026108fa4 | |
![]() |
dddac974d2 | |
![]() |
712374072d | |
![]() |
62109ba75e | |
![]() |
dd4b40d467 | |
![]() |
7566fb84e0 | |
![]() |
8df6cae90c | |
![]() |
6b84e93259 | |
![]() |
cc335cad5f | |
![]() |
9cacfe0dc2 | |
![]() |
ba54c5cce6 | |
![]() |
975e07bbdd | |
![]() |
6be7ed2e49 | |
![]() |
3f6b919c7b | |
![]() |
f9e4e10fce | |
![]() |
98f0cd5d79 | |
![]() |
62d2d78f17 | |
![]() |
6b44838841 | |
![]() |
2b05b6a295 | |
![]() |
4bd95942e7 | |
![]() |
7aeadde451 | |
![]() |
09a9261f7d | |
![]() |
5b57bd3d85 | |
![]() |
94bdc200f2 | |
![]() |
252ca973d3 | |
![]() |
87dcaf6338 | |
![]() |
f65282f482 | |
![]() |
9b8015bb5f | |
![]() |
9e843af55a | |
![]() |
57f7abda43 | |
![]() |
87f22bebf0 | |
![]() |
cc342bbd1c | |
![]() |
31ccda4501 | |
![]() |
b9575f3498 | |
![]() |
66f1e817eb | |
![]() |
3697ee1f2a | |
![]() |
acd2c535f6 | |
![]() |
5be9bd12d3 | |
![]() |
3697501426 | |
![]() |
73445ef175 | |
![]() |
2d2fb11bf8 | |
![]() |
ae1dab03ab | |
![]() |
f833a2f520 | |
![]() |
f0d3edfad6 | |
![]() |
f741f9f333 | |
![]() |
b1251d8279 | |
![]() |
a5761bc2a9 | |
![]() |
d2b9bd224d | |
![]() |
58f849a294 | |
![]() |
0dd9b7dcb1 | |
![]() |
17378e06c8 | |
![]() |
f4d3c80e2f | |
![]() |
ed084ae3bd | |
![]() |
791f031e16 | |
![]() |
cd8c19d762 | |
![]() |
1af469cbd6 | |
![]() |
9509d6409f | |
![]() |
e7dd00e427 | |
![]() |
220a621a88 | |
![]() |
5eca192bd2 | |
![]() |
d36cb87299 | |
![]() |
ce0601b77c | |
![]() |
5212061485 | |
![]() |
210f35f7ec | |
![]() |
7a923de427 | |
![]() |
253c401ae2 | |
![]() |
aa31d329ab | |
![]() |
6315d3c1cc | |
![]() |
92714d87e7 | |
![]() |
533481b0f4 | |
![]() |
991d9bcab5 | |
![]() |
f43cf941d5 | |
![]() |
246f3c7eb5 | |
![]() |
122b9683fa | |
![]() |
e7e57cd29e | |
![]() |
98a141cbc3 | |
![]() |
f68dd505d0 | |
![]() |
aa1a848bf2 | |
![]() |
9efdadb68a | |
![]() |
24726b3797 | |
![]() |
59ac877063 | |
![]() |
37567dfe18 | |
![]() |
b0c90d4be2 | |
![]() |
825a77d6c2 | |
![]() |
cae3229716 | |
![]() |
3013673c55 | |
![]() |
281efdbc88 | |
![]() |
9d31fd3fa5 | |
![]() |
f600a356e6 | |
![]() |
f21f6dd884 | |
![]() |
794fa3bcaf | |
![]() |
a81cc7345d | |
![]() |
17ce66ad45 | |
![]() |
f54b03d595 | |
![]() |
da3e0ade37 | |
![]() |
ddf8423f3c | |
![]() |
b7cf847d69 | |
![]() |
503d1a743a | |
![]() |
5615deb5b1 | |
![]() |
9a5be8f180 | |
![]() |
857b26e5a0 | |
![]() |
9d69863f3c | |
![]() |
795ca50dc8 | |
![]() |
0dc1698857 | |
![]() |
443ccb23a8 | |
![]() |
81e6d79c5e | |
![]() |
dddf9bfd81 | |
![]() |
121624d5b1 | |
![]() |
71c93cb39c | |
![]() |
5e4c3f12c3 | |
![]() |
0cab6641cc | |
![]() |
f1597b61ed | |
![]() |
2e87f4ddec | |
![]() |
21206dc3e7 | |
![]() |
6f34d3c299 | |
![]() |
71a735476c | |
![]() |
7f6e7d4062 | |
![]() |
b0479592ff | |
![]() |
e28beb5b45 | |
![]() |
b2cd95bf3b | |
![]() |
114998fa21 | |
![]() |
940ac10a9c | |
![]() |
54e1dc875a | |
![]() |
793539d208 | |
![]() |
f110ddd934 | |
![]() |
e8ca33b023 | |
![]() |
a8e243d36b | |
![]() |
e931a40451 | |
![]() |
9ef8c834d2 | |
![]() |
0313522d38 | |
![]() |
cc1805dc86 | |
![]() |
0913118da4 | |
![]() |
bfd7e46496 | |
![]() |
b1fc61a5a2 | |
![]() |
593b95cad9 | |
![]() |
cda72797c5 | |
![]() |
d7ccda33f6 | |
![]() |
93384a062e | |
![]() |
b903b572d9 | |
![]() |
9b4999ed9d | |
![]() |
49a1e56d10 | |
![]() |
b6abec16d0 | |
![]() |
3802f8bf46 | |
![]() |
78120671da | |
![]() |
7955b815ce | |
![]() |
a2c8e2b26f | |
![]() |
7b2b44b541 | |
![]() |
f08a947f8e | |
![]() |
3a5ae9c695 | |
![]() |
b6b9c003ff | |
![]() |
fd9b1ca22b | |
![]() |
d404d37ba5 | |
![]() |
a562d4db6a | |
![]() |
652de3fcb3 | |
![]() |
37d9d7eb06 | |
![]() |
e451bbd96a | |
![]() |
fde2e6f26a | |
![]() |
e7b4daaf32 | |
![]() |
5477a872c7 | |
![]() |
4a933df9fb | |
![]() |
c611dd4056 | |
![]() |
d2f476c050 | |
![]() |
b970f635e3 | |
![]() |
987bd2a054 | |
![]() |
61fe21af16 | |
![]() |
97a1f5aabd | |
![]() |
fa81e2dbbe | |
![]() |
bd2a035439 | |
![]() |
b9e13077bb | |
![]() |
d5b56e00f6 | |
![]() |
2d644dd8e2 | |
![]() |
f588fcf249 | |
![]() |
25de8011d5 | |
![]() |
e4e94a5640 | |
![]() |
c0b2977647 | |
![]() |
d459bdb5dc | |
![]() |
46d2e44cd1 | |
![]() |
b680536286 | |
![]() |
3895136fd0 | |
![]() |
3f6cd8c18f | |
![]() |
e9af16b48d | |
![]() |
34cbec36b2 | |
![]() |
bff75a2d08 | |
![]() |
bbb50459c9 | |
![]() |
4d31bd0a29 | |
![]() |
c1ce58fb42 | |
![]() |
d35eb68b78 | |
![]() |
f265896267 |
|
@ -1,16 +1,7 @@
|
|||
{
|
||||
"sourceType": "unambiguous",
|
||||
"presets": [
|
||||
[
|
||||
"@babel/preset-env",
|
||||
{
|
||||
"targets": {
|
||||
"chrome": 100,
|
||||
"safari": 15,
|
||||
"firefox": 91
|
||||
}
|
||||
}
|
||||
],
|
||||
"@babel/preset-env",
|
||||
"@babel/preset-typescript",
|
||||
"@babel/preset-react"
|
||||
],
|
||||
|
|
|
@ -4,36 +4,38 @@ jobs:
|
|||
backend:
|
||||
docker:
|
||||
- image: cimg/python:3.12
|
||||
environment:
|
||||
PIPENV_VENV_IN_PROJECT: true
|
||||
steps:
|
||||
- checkout
|
||||
- run: python --version > .python_version
|
||||
- restore_cache:
|
||||
key: pipenv-v3-{{ checksum "setup.py" }}
|
||||
key: &venv-cache venv-v1-{{ checksum "pyproject.toml" }}-{{ checksum ".python_version" }}
|
||||
# Only install if .venv wasn’t cached.
|
||||
- run: |
|
||||
if [[ ! -e ".venv" ]]; then
|
||||
pipenv install -e .[testing,docs]
|
||||
python -m venv .venv
|
||||
source .venv/bin/activate
|
||||
python -m pip install -e .[testing,docs]
|
||||
fi
|
||||
echo "source $(pwd)/.venv/bin/activate" >> $BASH_ENV
|
||||
- save_cache:
|
||||
key: pipenv-v3-{{ checksum "setup.py" }}
|
||||
key: *venv-cache
|
||||
paths:
|
||||
- .venv
|
||||
- run: pipenv run ruff check .
|
||||
- run: pipenv run ruff format --check .
|
||||
- run: pipenv run semgrep --config .semgrep.yml --error .
|
||||
- run: git ls-files '*.html' | xargs pipenv run djhtml --check
|
||||
- run: pipenv run curlylint --parse-only wagtail
|
||||
- run: pipenv run doc8 docs
|
||||
- run: ruff check .
|
||||
- run: ruff format --check .
|
||||
- run: semgrep --config .semgrep.yml --error .
|
||||
- run: git ls-files '*.html' | xargs djhtml --check
|
||||
- run: curlylint --parse-only wagtail
|
||||
- run: doc8 docs
|
||||
- run:
|
||||
name: Run tests
|
||||
command: |
|
||||
export PYTHONUNBUFFERED=1
|
||||
WAGTAIL_CHECK_TEMPLATE_NUMBER_FORMAT=1 pipenv run python -u runtests.py --parallel=2
|
||||
WAGTAIL_CHECK_TEMPLATE_NUMBER_FORMAT=1 python -u runtests.py --parallel=2
|
||||
|
||||
frontend:
|
||||
docker:
|
||||
- image: cimg/node:20.9
|
||||
- image: cimg/node:22.11
|
||||
steps:
|
||||
- checkout
|
||||
- restore_cache:
|
||||
|
@ -64,45 +66,48 @@ jobs:
|
|||
docker:
|
||||
- image: cimg/python:3.12-browsers
|
||||
environment:
|
||||
PIPENV_VENV_IN_PROJECT: true
|
||||
DJANGO_SETTINGS_MODULE: wagtail.test.settings_ui
|
||||
DJANGO_DEBUG: true
|
||||
DJANGO_DEBUG: 'true'
|
||||
steps:
|
||||
- checkout
|
||||
- attach_workspace:
|
||||
at: ~/project
|
||||
- run: python --version > .python_version
|
||||
- restore_cache:
|
||||
key: ui_tests-pipenv-v3-{{ checksum "setup.py" }}
|
||||
key: &ui_tests-venv-cache ui_tests-venv-v1-{{ checksum "pyproject.toml" }}-{{ checksum ".python_version" }}
|
||||
# Only install if .venv wasn’t cached.
|
||||
- run: |
|
||||
if [[ ! -e ".venv" ]]; then
|
||||
pipenv install -e .[testing]
|
||||
python -m venv .venv
|
||||
source .venv/bin/activate
|
||||
python -m pip install -e .[testing]
|
||||
fi
|
||||
echo "source $(pwd)/.venv/bin/activate" >> $BASH_ENV
|
||||
- save_cache:
|
||||
key: ui_tests-pipenv-v3-{{ checksum "setup.py" }}
|
||||
key: *ui_tests-venv-cache
|
||||
paths:
|
||||
- .venv
|
||||
- restore_cache:
|
||||
key: ui_tests-npm_integration-v3-{{ checksum "client/tests/integration/package-lock.json" }}
|
||||
key: &ui_tests-npm-cache ui_tests-npm_integration-v3-{{ checksum "client/tests/integration/package-lock.json" }}
|
||||
# Only install if node_modules wasn’t cached.
|
||||
- run: |
|
||||
if [[ ! -e "client/tests/integration/node_modules" ]]; then
|
||||
npm --prefix ./client/tests/integration ci
|
||||
fi
|
||||
- save_cache:
|
||||
key: ui_tests-npm_integration-v3-{{ checksum "client/tests/integration/package-lock.json" }}
|
||||
key: *ui_tests-npm-cache
|
||||
paths:
|
||||
- client/tests/integration/node_modules
|
||||
# Also cache the global location where Puppeteer stores browsers.
|
||||
# https://pptr.dev/guides/configuration/#changing-the-default-cache-directory
|
||||
- ~/.cache/puppeteer
|
||||
- run: pipenv run ./wagtail/test/manage.py migrate
|
||||
- run: ./wagtail/test/manage.py migrate
|
||||
- run:
|
||||
command: pipenv run ./wagtail/test/manage.py runserver 0:8000
|
||||
command: ./wagtail/test/manage.py runserver 0:8000
|
||||
background: true
|
||||
- run: pipenv run ./wagtail/test/manage.py createcachetable
|
||||
- run: ./wagtail/test/manage.py createcachetable
|
||||
- run:
|
||||
command: pipenv run ./wagtail/test/manage.py createsuperuser --noinput
|
||||
command: ./wagtail/test/manage.py createsuperuser --noinput
|
||||
environment:
|
||||
DJANGO_SUPERUSER_EMAIL: admin@example.com
|
||||
DJANGO_SUPERUSER_USERNAME: admin
|
||||
|
@ -112,9 +117,9 @@ jobs:
|
|||
environment:
|
||||
JEST_JUNIT_OUTPUT_DIR: reports/jest
|
||||
- run:
|
||||
command: pipenv run ./wagtail/test/manage.py collectstatic --noinput
|
||||
command: ./wagtail/test/manage.py collectstatic --noinput
|
||||
environment:
|
||||
DJANGO_DEBUG: false
|
||||
DJANGO_DEBUG: 'false'
|
||||
STATICFILES_STORAGE: manifest
|
||||
- store_test_results:
|
||||
path: ./reports/jest
|
||||
|
@ -124,12 +129,11 @@ jobs:
|
|||
- image: cimg/python:3.12-node
|
||||
steps:
|
||||
- checkout
|
||||
- run: pip install --user wheel boto3
|
||||
- run: pip install --user build boto3
|
||||
- run: npm install
|
||||
- run: npm run build
|
||||
- run: PYTHONPATH=. python scripts/nightly/get_version.py > __init__.py
|
||||
- run: mv __init__.py wagtail/__init__.py
|
||||
- run: python setup.py bdist_wheel
|
||||
- run: python -m build
|
||||
- run: python scripts/nightly/upload.py
|
||||
|
||||
workflows:
|
||||
|
|
|
@ -11,7 +11,6 @@ wagtail/images/static
|
|||
wagtail/embeds/static
|
||||
wagtail/search/static
|
||||
wagtail/snippets/static
|
||||
wagtail/users/static
|
||||
wagtail/contrib/*/static
|
||||
.mypy_cache
|
||||
/storybook-static
|
||||
|
|
12
.eslintrc.js
12
.eslintrc.js
|
@ -132,14 +132,14 @@ module.exports = {
|
|||
files: [
|
||||
'client/extract-translatable-strings.js',
|
||||
'client/tests/**',
|
||||
'webpack.config.js',
|
||||
'tailwind.config.js',
|
||||
'storybook/**/*',
|
||||
'*.test.ts',
|
||||
'*.test.tsx',
|
||||
'*.test.js',
|
||||
'webpack.config.js',
|
||||
'*.stories.js',
|
||||
'*.stories.tsx',
|
||||
'*.test.js',
|
||||
'*.test.ts',
|
||||
'*.test.tsx',
|
||||
'**/storybook/**',
|
||||
],
|
||||
rules: {
|
||||
'@typescript-eslint/no-empty-function': 'off',
|
||||
|
@ -167,7 +167,6 @@ module.exports = {
|
|||
'wagtail/images/static_src/wagtailimages/js/add-multiple.js',
|
||||
'wagtail/images/static_src/wagtailimages/js/focal-point-chooser.js',
|
||||
'wagtail/images/static_src/wagtailimages/js/image-url-generator.js',
|
||||
'wagtail/users/static_src/wagtailusers/js/group-form.js',
|
||||
],
|
||||
globals: { $: 'readonly', jQuery: 'readonly' },
|
||||
},
|
||||
|
@ -175,7 +174,6 @@ module.exports = {
|
|||
{
|
||||
files: ['wagtail/**/**'],
|
||||
globals: {
|
||||
buildExpandingFormset: 'readonly',
|
||||
escapeHtml: 'readonly',
|
||||
ModalWorkflow: 'readonly',
|
||||
DOCUMENT_CHOOSER_MODAL_ONLOAD_HANDLERS: 'writable',
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
# Make GitHub highlight html files as Django templates
|
||||
*.html linguist-language=django
|
|
@ -24,7 +24,9 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v1
|
||||
|
|
|
@ -23,15 +23,14 @@ concurrency:
|
|||
# - django 4.2, python 3.9, postgres:12, psycopg 2, parallel
|
||||
# - django 4.2, python 3.10, mysql:8.0
|
||||
# - django 4.2, python 3.11, mariadb:10.5
|
||||
# - django 5.0, python 3.11, sqlite, WAGTAIL_CHECK_TEMPLATE_NUMBER_FORMAT=1
|
||||
# - django 5.1, python 3.12, mysql:8.4, parallel, USE_EMAIL_USER_MODEL=yes
|
||||
# - django 5.1, python 3.12, mysql:8.4, USE_EMAIL_USER_MODEL=yes
|
||||
# - django 5.1, python 3.12, mariadb:11.4, USE_EMAIL_USER_MODEL=yes
|
||||
# - django 5.1, python 3.13, sqlite, parallel, USE_EMAIL_USER_MODEL=yes
|
||||
# - django 5.1, python 3.13, postgres:15, psycopg 3, parallel, DISABLE_TIMEZONE=yes
|
||||
# - django stable/5.1.x, python 3.11, postgres:15, psycopg 3 (allow failures)
|
||||
# - django 5.2, python 3.13, sqlite, parallel, WAGTAIL_CHECK_TEMPLATE_NUMBER_FORMAT=1
|
||||
# - django 5.2, python 3.13, postgres:15, psycopg 3, parallel, DISABLE_TIMEZONE=yes
|
||||
# - django stable/5.2.x, python 3.12, postgres:15, psycopg 3 (allow failures)
|
||||
# - django main, python 3.13, postgres:latest, psycopg 3, parallel (allow failures)
|
||||
# - elasticsearch 7, django 4.2, python 3.9, postgres:latest, psycopg 2
|
||||
# - opensearch 2, django 5.0, python 3.10, sqlite
|
||||
# - opensearch 2, django 5.2, python 3.10, sqlite
|
||||
# - elasticsearch 8, django 5.1, python 3.13, sqlite, USE_EMAIL_USER_MODEL=yes
|
||||
|
||||
# Some tests are run in parallel by passing --parallel to runtests.py.
|
||||
|
@ -49,16 +48,15 @@ jobs:
|
|||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- python: '3.11'
|
||||
django: 'Django>=5.0,<5.1'
|
||||
check_template_number_format: '1'
|
||||
- python: '3.13'
|
||||
django: 'Django>=5.1,<5.2'
|
||||
emailuser: emailuser
|
||||
django: 'Django>=5.2,<5.3'
|
||||
check_template_number_format: '1'
|
||||
parallel: '--parallel'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Set up Python ${{ matrix.python }}
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
|
@ -96,14 +94,14 @@ jobs:
|
|||
experimental: false
|
||||
parallel: '--parallel'
|
||||
- python: '3.13'
|
||||
django: 'Django>=5.0,<5.1'
|
||||
django: 'Django>=5.2,<5.3'
|
||||
psycopg: 'psycopg>=3.1.8'
|
||||
postgres: 'postgres:15'
|
||||
notz: notz
|
||||
experimental: false
|
||||
parallel: '--parallel'
|
||||
- python: '3.11'
|
||||
django: 'git+https://github.com/django/django.git@stable/5.1.x#egg=Django'
|
||||
- python: '3.12'
|
||||
django: 'git+https://github.com/django/django.git@stable/5.2.x#egg=Django'
|
||||
psycopg: 'psycopg>=3.1.8'
|
||||
postgres: 'postgres:15'
|
||||
experimental: true
|
||||
|
@ -113,6 +111,9 @@ jobs:
|
|||
experimental: true
|
||||
postgres: 'postgres:latest'
|
||||
parallel: '--parallel'
|
||||
install_extras: |
|
||||
pip uninstall -y django-modelcluster
|
||||
pip install "git+https://github.com/wagtail/django-modelcluster.git@main#egg=django-modelcluster"
|
||||
services:
|
||||
postgres:
|
||||
image: ${{ matrix.postgres || 'postgres:12' }}
|
||||
|
@ -124,6 +125,8 @@ jobs:
|
|||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Set up Python ${{ matrix.python }}
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
|
@ -153,6 +156,24 @@ jobs:
|
|||
name: coverage-data-${{ github.job }}-${{ strategy.job-index }}
|
||||
path: .coverage.*
|
||||
include-hidden-files: true
|
||||
- name: Test project template
|
||||
if: ${{ matrix.experimental }}
|
||||
env:
|
||||
PYTHONWARNINGS: error
|
||||
run: |
|
||||
wagtail start testproject
|
||||
cd testproject
|
||||
tee -a testproject/settings/local.py << EOF
|
||||
from warnings import filterwarnings
|
||||
SILENCED_SYSTEM_CHECKS = ["wagtailadmin.W001"]
|
||||
# Remove when https://github.com/wagtail/Willow/issues/166 is resolved
|
||||
filterwarnings(
|
||||
"ignore", "The AVIF support in this library is marked as deprecated"
|
||||
)
|
||||
EOF
|
||||
python manage.py makemigrations --check --dry-run
|
||||
python manage.py migrate
|
||||
python manage.py check --fail-level WARNING
|
||||
|
||||
test-mysql:
|
||||
runs-on: ubuntu-latest
|
||||
|
@ -175,7 +196,6 @@ jobs:
|
|||
- python: '3.12'
|
||||
django: 'Django>=5.1,<5.2'
|
||||
experimental: false
|
||||
parallel: '--parallel'
|
||||
mysql: 'mysql:8.4'
|
||||
emailuser: emailuser
|
||||
services:
|
||||
|
@ -193,6 +213,8 @@ jobs:
|
|||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Set up Python ${{ matrix.python }}
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
|
@ -228,7 +250,7 @@ jobs:
|
|||
matrix:
|
||||
include:
|
||||
- python: '3.13'
|
||||
django: 'Django>=5.1,<5.2'
|
||||
django: 'Django>=5.2,<5.3'
|
||||
emailuser: emailuser
|
||||
steps:
|
||||
- name: Configure sysctl limits
|
||||
|
@ -246,6 +268,8 @@ jobs:
|
|||
node port: 9300
|
||||
discovery type: 'single-node'
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Set up Python ${{ matrix.python }}
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
|
@ -301,6 +325,9 @@ jobs:
|
|||
with:
|
||||
stack-version: 7.6.1
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Set up Python ${{ matrix.python }}
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
|
@ -337,7 +364,7 @@ jobs:
|
|||
matrix:
|
||||
include:
|
||||
- python: '3.10'
|
||||
django: 'Django>=5.0,<5.1'
|
||||
django: 'Django>=5.1,<5.2'
|
||||
experimental: false
|
||||
|
||||
steps:
|
||||
|
@ -351,6 +378,8 @@ jobs:
|
|||
with:
|
||||
opensearch-version: 2
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Set up Python ${{ matrix.python }}
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
|
@ -388,6 +417,8 @@ jobs:
|
|||
steps:
|
||||
- name: Check out the repo
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
|
|
2
.nvmrc
2
.nvmrc
|
@ -1 +1 @@
|
|||
20
|
||||
22
|
||||
|
|
|
@ -3,7 +3,7 @@ default_language_version:
|
|||
python: python3
|
||||
repos:
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: 'v0.1.5'
|
||||
rev: 'v0.9.6'
|
||||
hooks:
|
||||
- id: ruff
|
||||
args: [--fix, --exit-non-zero-on-fix]
|
||||
|
|
|
@ -9,5 +9,11 @@ python:
|
|||
path: .
|
||||
extra_requirements:
|
||||
- docs
|
||||
formats: all
|
||||
sphinx:
|
||||
configuration: docs/conf.py
|
||||
fail_on_warning: True
|
||||
search:
|
||||
ranking:
|
||||
releases/*: -1
|
||||
releases/upgrading.html: 0
|
||||
|
|
|
@ -3,7 +3,7 @@ deployments:
|
|||
dockerimage: python:3.11.4-slim-bullseye
|
||||
build_steps:
|
||||
- apt-get update && apt-get install -y libssl-dev libpq-dev git build-essential libfontconfig1 libfontconfig1-dev curl
|
||||
- RUN bash -c "curl -sL https://deb.nodesource.com/setup_20.x | bash -"
|
||||
- RUN bash -c "curl -sL https://deb.nodesource.com/setup_22.x | bash -"
|
||||
- apt install -y nodejs
|
||||
- pip install setuptools pip --upgrade --force-reinstall
|
||||
- cd /code
|
||||
|
|
|
@ -23,12 +23,7 @@ module.exports = {
|
|||
// Would be valuable for strict BEM components but is too hard to enforce with legacy code.
|
||||
'no-descending-specificity': null,
|
||||
// Refined ordering to align with media mixin usage - see https://github.com/wagtail/stylelint-config-wagtail/issues/37
|
||||
'order/order': [
|
||||
'dollar-variables',
|
||||
'custom-properties',
|
||||
{ type: 'at-rule', hasBlock: false }, // @-rules that have no nesting.
|
||||
'declarations',
|
||||
],
|
||||
'order/order': ['dollar-variables', 'custom-properties', 'declarations'],
|
||||
// Some parts of declaration-strict-value commented out until we are in a position to enforce them.
|
||||
'scale-unlimited/declaration-strict-value': [
|
||||
[
|
||||
|
@ -56,6 +51,7 @@ module.exports = {
|
|||
'none',
|
||||
'unset',
|
||||
'transparent',
|
||||
'normal',
|
||||
// System colors for forced-colors styling.
|
||||
// See https://drafts.csswg.org/css-color-4/#css-system-colors.
|
||||
'Canvas',
|
||||
|
|
299
CHANGELOG.txt
299
CHANGELOG.txt
|
@ -1,7 +1,266 @@
|
|||
Changelog
|
||||
=========
|
||||
|
||||
6.3 LTS (xx.xx.xxxx) - IN DEVELOPMENT
|
||||
7.0 LTS (xx.xx.xxxx) - IN DEVELOPMENT
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* Add formal support for Django 5.2 (Matt Westcott)
|
||||
* Add `WAGTAIL_` prefix to Wagtail-specific tag settings (Aayushman Singh)
|
||||
* Implement `normalize` on `TypedTableBlock` to assist with setting `default` and `preview_value` (Sage Abdullah)
|
||||
* Apply normalization when modifying a `StreamBlock`'s value to assist with programmatic changes to `StreamField` (Matt Westcott)
|
||||
* Allow a custom image rendition model to define its unique constraint with `models.UniqueConstraint` instead of `unique_together` (Oliver Parker, Cynthia Kiser, Sage Abdullah)
|
||||
* Default to the `standard` tokenizer on Elasticsearch, to correctly handle numbers as tokens (Matt Westcott)
|
||||
* Add color-scheme meta tag to Wagtail admin (Ashish Nagmoti)
|
||||
* Add the ability to set the default privacy restriction for new pages using `get_default_privacy_setting` (Shlomo Markowitz)
|
||||
* Improve performance of batch purging page urls in the frontend cache, avoiding n+1 query issues (Andy Babic)
|
||||
* Add better support and documentation for overriding or extending icons used in the in the userbar (Sébastien Corbin)
|
||||
* List the comments action, if comments are enabled, within the admin keyboard shortcuts dialog (Dhruvi Patel)
|
||||
* Add better support and documentation for overriding the default field widgets used within form pages (Baptiste Mispelon)
|
||||
* Allow workflow tasks to specify a template for the action modal via `get_template_for_action` (Sage Abdullah)
|
||||
* Change 'Publish' button label to 'Schedule to publish' if go-live schedule is set (Sage Abdullah)
|
||||
* Fix: Take preferred language into account for translatable strings in client-side code (Bernhard Bliem, Sage Abdullah)
|
||||
* Fix: Do not show the content type column as sortable when searching pages (Srishti Jaiswal, Sage Abdullah)
|
||||
* Fix: Support simple subqueries for `in` and `exact` lookup on Elasticsearch (Sage Abdullah)
|
||||
* Fix: Force preview panel scroll behavior to instant to avoid flickering (Sage Abdullah)
|
||||
* Fix: Support translating with the preferred language for rich text formatting labels (Bernhard Bliem, Sage Abdullah)
|
||||
* Fix: Make "Actions" label translatable within the rich text toolbar (Bernhard Bliem, Sage Abdullah)
|
||||
* Fix: Fix incorrect "Views (past week)" heading on promoted search results listing (Baptiste Mispelon)
|
||||
* Fix: Ensure `InlinePanel` will be correctly ordered after the first save when `min_num` is used (Elhussein Almasri, Joel William)
|
||||
* Fix: Avoid deprecation warnings about URLField `assume_scheme` on Django 5.x (Sage Abdullah)
|
||||
* Fix: Fix setup.cfg syntax for setuptools v78 (Sage Abdullah)
|
||||
* Fix: Ensure `ImproperlyConfigured` is thrown from `db_field` on unbound `FieldPanel`s as intended (Matt Westcott)
|
||||
* Fix: Refine the positioning of the add comment button next to select, radio, checkbox fields and between field row columns (Srishti Jaiswal)
|
||||
* Fix: Show the correct privacy status for child collections of private collections (Shlomo Markowitz)
|
||||
* Fix: Ensure reference index correctly handles models with primary keys not named `id` (Sage Abdullah)
|
||||
* Fix: On "move page" bulk action, do not prefill the destination with the root page (Stefan Hammer)
|
||||
* Docs: Add missing `django.contrib.admin` to list of apps in "add to Django project" guide (Mohamed Rabiaa)
|
||||
* Docs: Add tutorial on deploying on Ubuntu to third-party tutorials (Mohammad Fathi Rahman)
|
||||
* Docs: Document that request_or_site is optional on BaseGenericSetting.load (Matt Westcott)
|
||||
* Docs: Mention third-party StreamField based form builder packages in the form builder documentation (Matt Westcott)
|
||||
* Docs: Clarify that `insert_editor_js` hook applies to all core editing/creation views (LB (Ben) Johnston)
|
||||
* Docs: Clarify requirement for non-page models using model mixins to be registered as snippets (Sage Abdullah)
|
||||
* Maintenance: Migrate away from deprecated Sass import rules to module system (Srishti Jaiswal)
|
||||
* Maintenance: Apply Sass mixed declarations migration in preparation for CSS nesting (Prabhpreet Kaur)
|
||||
* Maintenance: Refactor styles for Draftail, minimap, and comments to fix remaining Sass migration warnings (Thibaud Colas)
|
||||
* Maintenance: npm package updates; `downshift`, `focus-trap-react`, `immer`, `redux`, `uuid` (LB (Ben) Johnston)
|
||||
* Maintenance: Validate against invalid characters in Lexeme values (Matt Westcott)
|
||||
* Maintenance: Split up `wagtail.models` module into submodules (Matt Westcott)
|
||||
* Maintenance: Update `ruff` to 0.9.6 (Sage Abdullah)
|
||||
* Maintenance: Fix up `stubs` & `adapter` contents to better support Jest testing (LB (Ben) Johnston)
|
||||
* Maintenance: Cleanup Stimulus controller imports, JSDoc & linting (LB (Ben) Johnston)
|
||||
* Maintenance: Rename `SkipLinkController` to `FocusController` with improved reusability, updated unit tests, and added story (LB (Ben) Johnston)
|
||||
* Maintenance: Fix CI testing issues with the Stimulus `LocaleController` time zones & non-deterministic page ordering tests (Sage Abdullah)
|
||||
* Maintenance: Make GitHub highlight `.html` files as Django templates (Jake Howard)
|
||||
* Maintenance: Remove admin JavaScript imports from shared template includes, moving the imports to the appropriate core admin inclusion locations (Sai Srikar Dumpeti)
|
||||
* Maintenance: Remove non-editing view inclusions of the `insert_editor_js` hook output, deprecate the wrapper template tag `_editor_js.html` (Sai Srikar Dumpeti, LB (Ben) Johnston)
|
||||
* Maintenance: Remove upper bound on Django dependency (Matt Westcott)
|
||||
* Maintenance: Add `default_auto_field` setting to home app in project template (Sylvain Boissel)
|
||||
* Maintenance: Migrate setuptools configuration from `setup.py` and `setup.cfg` to `pyproject.toml` (Sage Abdullah)
|
||||
* Maintenance: Refactor `move_choose_destination` to a class-based view (Chiemezuo Akujobi)
|
||||
|
||||
|
||||
6.4.1 (21.02.2025)
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* Fix: Prevent error when filtering by locale and searching with Elasticsearch (Sage Abdullah)
|
||||
* Fix: Support searching `none()` querysets (Matt Westcott)
|
||||
* Fix: Correctly handle UUID primary keys when invoking background tasks (Matt Westcott)
|
||||
* Fix: Fix regression where nested sub-menu items would not be visible (Sage Abdullah)
|
||||
* Fix: Ensure the top of the minimap correctly adjusts when resizing the browser viewport (Thibaud Colas)
|
||||
* Fix: Remove obsolete SubqueryConstraint check in search backends, for provisional Django 5.2 compatibility (Sage Abdullah)
|
||||
* Fix: Add missing “Close” label to the upgrade notification dismiss button (Sage Abdullah)
|
||||
* Fix: Fix white text on white background in previews for sites that use color-scheme without a background-color (Sage Abdullah)
|
||||
* Docs: Fix typo in the headless documentation page (Mahmoud Nasser)
|
||||
* Docs: Fix typo in `Page.get_route_paths` docstring (Baptiste Mispelon)
|
||||
* Docs: Upgrade sphinx-wagtail-theme to v6.5.0 (Sage Abdullah)
|
||||
* Maintenance: Remove upper version boundary for django-filter (Dan Braghis)
|
||||
* Maintenance: Relax upper version boundaries for django-taggit and beautifulsoup4 (Matt Westcott)
|
||||
|
||||
|
||||
6.4 (03.02.2025)
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
* Support for background tasks using `django-tasks` (Jake Howard)
|
||||
* Add search terms report (Noah van der Meer, Sage Abdullah)
|
||||
* Add the ability to apply basic Page QuerySet optimizations to `specific()` sub-queries using `select_related` & `prefetch_related` (Andy Babic)
|
||||
* Increase `DATA_UPLOAD_MAX_NUMBER_FIELDS` in project template (Matt Westcott)
|
||||
* Stop invalid Site hostname records from breaking preview (Matt Westcott)
|
||||
* Set sensible defaults for InlinePanel heading and label (Matt Westcott)
|
||||
* Limit tags autocompletion to 10 items and add delay to avoid performance issues with large number of matching tags (Aayushman Singh)
|
||||
* Add the ability to restrict what types of requests a Pages supports via `allowed_http_methods` (Andy Babic)
|
||||
* Allow plain strings in panel definitions as shorthand for `FieldPanel` / `InlinePanel` (Matt Westcott)
|
||||
* Only allow selection of valid new parents within the copy Page view (Mauro Soche)
|
||||
* Add `on_serve_page` hook to modify the serving chain of pages (Krystian Magdziarz, Dawid Bugajewski)
|
||||
* Add support for `WAGTAIL_GRAVATAR_PROVIDER_URL` URLs with query string parameters (Ayaan Qadri, Guilhem Saurel)
|
||||
* Add `get_avatar_url` hook to customise user avatars (James Harrington)
|
||||
* Set content security policy (CSP) headers to block embedded content when serving images and documents (Jake Howard, with thanks to Ali İltizar for the initial report)
|
||||
* Add `page` as a third parameter to the `construct_wagtail_userbar` hook (claudobahn)
|
||||
* Enable breadcrumbs in revisions compare view (Sage Abdullah)
|
||||
* Skip loading of unused JavaScript to speed up 404 page rendering (Sage Abdullah)
|
||||
* Replace l18n library with JavaScript Intl API for time zone options in Account view (Sage Abdullah)
|
||||
* Use explicit label for defaulting to server language in account settings (Sage Abdullah)
|
||||
* Add support for specifying an operator on `Fuzzy` queries (Tom Usher)
|
||||
* Remove support for Safari 15 (Thibaud Colas)
|
||||
* Populate the ImageBlock alt text from the image’s default alt text when selecting a new image (Matt Westcott)
|
||||
* Prevent main menu from re-rendering when clicking outside while the menu is closed (Sage Abdullah)
|
||||
* Fill in the ImageBlock alt text from the image’s default alt text when converting from ImageChooserBlock (Cynthia Kiser)
|
||||
* Make sure typing text at the bottom of the page editor always scrolls enough to keep the text into view (Jatin Bhardwaj)
|
||||
* Add StreamField and InlinePanel interfaces support for drag-and-drop reordering of items (Thibaud Colas, Sage Abdullah)
|
||||
* Add previews support for StreamField blocks inside the block picker (Sage Abdullah, Thibaud Colas)
|
||||
* Fix: Improve handling of translations for bulk page action confirmation messages (Matt Westcott)
|
||||
* Fix: Ensure custom rich text feature icons are correctly handled when provided as a list of SVG paths (Temidayo Azeez, Joel William, LB (Ben) Johnston)
|
||||
* Fix: Prevent error on lazily loading StreamField blocks after the stream has been modified (Stefan Hammer)
|
||||
* Fix: Fix sub-menus within the main menu cannot be closed on mobile (Bojan Mihelac)
|
||||
* Fix: Fix animation overflow transition when navigating through subpages in the sidebar page explorer (manu)
|
||||
* Fix: Ensure form builder supports custom admin form validation (John-Scott Atlakson, LB (Ben) Johnston)
|
||||
* Fix: Ensure form builder correctly checks for duplicate field names when using a custom related name (John-Scott Atlakson, LB (Ben) Johnston)
|
||||
* Fix: Normalize `StreamField.get_default()` to prevent creation forms from breaking (Matt Westcott)
|
||||
* Fix: Prevent out-of-order migrations from skipping creation of image/document choose permissions (Matt Westcott)
|
||||
* Fix: Use correct connections on multi-database setups in database search backends (Jake Howard)
|
||||
* Fix: Ensure CloudFront cache invalidation is called with a list, for compatibility with current botocore versions (Jake Howard)
|
||||
* Fix: Show the correct privacy status in the sidebar when creating a new page (Joel William)
|
||||
* Fix: Prevent generic model edit view from unquoting non-integer primary keys multiple times (Matt Westcott)
|
||||
* Fix: Ensure comments are functional when editing Page models with `read_only` `Fieldpanel`s in use (Strapchay)
|
||||
* Fix: Ensure the accessible labels and tooltips reflect the correct private/public status on the live link button within pages after changing the privacy (Ayaan Qadri)
|
||||
* Fix: Fix empty `th` (table heading) elements that are not compliant with accessibility standards (Jai Vignesh J)
|
||||
* Fix: Ensure `MultipleChooserPanel` using images or documents work when nested within an `InlinePanel` when no other choosers are in use within the model (Elhussein Almasri)
|
||||
* Fix: Ensure `MultipleChooserPanel` works after doing a search in the page chooser modal (Matt Westcott)
|
||||
* Fix: Ensure new `ListBlock` instances get created with unique IDs in the admin client for accessibility and mini-map element references (Srishti Jaiswal)
|
||||
* Fix: Return never-cache HTTP headers when serving pages and documents with view restrictions (Krystian Magdziarz, Dawid Bugajewski)
|
||||
* Fix: Implement `get_block_by_content_path` on `ImageBlock` to prevent errors on commenting (Matt Westcott)
|
||||
* Fix: Add `aria-expanded` attribute to new column button on `TypedTableBlock` to reflect menu state (Ayaan Qadri, Scott Cranfill)
|
||||
* Fix: Allow page models to extend base `Page` panel definitions without importing `wagtail.admin` (Matt Westcott)
|
||||
* Fix: Fix crash when loading the dashboard with only the "unlock" or "bulk delete" page permissions (Unyime Emmanuel Udoh, Sage Abdullah)
|
||||
* Fix: Improve deprecation warning for `WidgetWithScript` by raising it with `stacklevel=3` (Joren Hammudoglu)
|
||||
* Fix: Correctly place comment buttons next to date / datetime / time fields. (Srishti Jaiswal)
|
||||
* Fix: Add missing heading and breadcrumbs in Account view (Sage Abdullah)
|
||||
* Fix: Reduce confusing spacing below StreamField blocks help text (Rishabh Sharma)
|
||||
* Fix: Prevent redundant calls to `Site.find_for_request()` from `Page.get_url_parts()` (Andy Babic)
|
||||
* Fix: Prevent error on listings when searching and filtering by locale (Matt Westcott, Sage Abdullah)
|
||||
* Fix: Add missing space in panels check warning message (Stéphane Blondon)
|
||||
* Fix: Make sure alt text quality check is on by default as documented (Thibaud Colas)
|
||||
* Fix: Prevent `StreamChildrenToListBlockOperation` from duplicating data across multiple StreamField instances (Joshua Munn)
|
||||
* Fix: Prevent database error when calling permission_order.register on app ready (Daniel Kirkham, Matt Westcott)
|
||||
* Fix: Prevent syntax error on MySQL search when query includes symbols (Matt Westcott)
|
||||
* Docs: Move the model reference page from reference/pages to the references section as it covers all Wagtail core models (Srishti Jaiswal)
|
||||
* Docs: Move the panels reference page from references/pages to the references section as panels are available for any model editing, merge panels API into this page (Srishti Jaiswal)
|
||||
* Docs: Move the tags documentation to standalone advanced topic, instead of being inside the reference/pages section (Srishti Jaiswal)
|
||||
* Docs: Refine the adding reports page so that common (page/non-page) class references are at the top and the full page only example has correct heading nesting (Alessandro Chitarrini)
|
||||
* Docs: Add the `wagtail start` command to the management commands reference page (Damilola Oladele)
|
||||
* Docs: Refine the project template page sections and document common issues encountered when creating custom templates (Damilola Oladele)
|
||||
* Docs: Refine titles, references and URLS to better align with the documentation style guide, including US spelling (Srishti Jaiswal)
|
||||
* Docs: Recommend a larger `DATA_UPLOAD_MAX_NUMBER_FIELDS` when integrating Wagtail into Django (Matt Westcott)
|
||||
* Docs: Improve code highlighting and formatting for Python docstrings in core models (Srishti Jaiswal)
|
||||
* Docs: Update all JavaScript inline scripts & some CSS inline style tags to a CSP compliant approach by using external scripts/styles (Aayushman Singh)
|
||||
* Docs: Update usage of `mark_safe` to `format_html` for any script inclusions, to better avoid XSS issues from example code (Aayushman Singh)
|
||||
* Docs: Update documentation writing guidelines to encourage better considerations of security, accessibility and good practice when writing code examples (Aayushman Singh, LB (Ben) Johnston)
|
||||
* Docs: Update documentation guidelines on writing links and API reference (Sage Abdullah)
|
||||
* Docs: Replace absolute URLs with intersphinx links where possible to avoid broken links (Sage Abdullah)
|
||||
* Docs: Update upgrading guide and release process to better reflect the current practices (Sage Abdullah)
|
||||
* Docs: Document usage of custom validation for admin form pages when using `AbstractEmailForm` or `AbstractForm` pages (John-Scott Atlakson, LB (Ben) Johnston)
|
||||
* Docs: Reword `BlogTagIndexPage` example for clarity (Clifford Gama)
|
||||
* Docs: Change title of blog index page in tutorial to avoid slug issues (Thibaud Colas)
|
||||
* Docs: Fix `wagtailcache` and `wagtailpagecache` examples to not use quotes for the `fragment_name` (Shiv)
|
||||
* Docs: Update tutorial to reflect the move of the "Add child page" action to a top-level button in the header as a '+' icon (Clifford Gama)
|
||||
* Docs: Fix link to `HTTPMethod` in `Page.handle_options_request()` docs (Sage Abdullah)
|
||||
* Docs: Improve the Pages Theory page with added & more consistent section headings and admonitions to aid in readability (Clifford Gama)
|
||||
* Docs: Fix non-functional link to the community guidelines in the Your first contribution page (Ankit Kumar)
|
||||
* Docs: Introduce tags and filters by name in "Writing templates" docs (Clifford Gama)
|
||||
* Docs: Add a new headless section to the documentation, incorporating parts of the 'are we headless' website content (Sævar Öfjörð Magnússon, Alex Fulcher)
|
||||
* Docs: Fix Django HTML syntax formatting issue on the documents overview page (LB (Ben) Johnston)
|
||||
* Docs: Separate virtual environment creation and activation steps in tutorial (Ankit Kumar)
|
||||
* Docs: Update tutorial to use plain strings in place of `FieldPanel` / `InlinePanel` where appropriate (Unyime Emmanuel Udoh)
|
||||
* Docs: Update example for customizing "p-as-heading" accessibility check without overriding built-in checks (Cynthia Kiser)
|
||||
* Docs: Document `get_template` method on StreamField blocks (Matt Westcott)
|
||||
* Docs: Update accessibility considerations on alt text in light of contextual alt text improvements (Cynthia Kiser)
|
||||
* Docs: Revert incorrect example of appending a `RichTextBlock` to a `StreamField` (Matt Westcott)
|
||||
* Maintenance: Close open files when reading within utils/setup.py (Ataf Fazledin Ahamed)
|
||||
* Maintenance: Avoid redundant `ALLOWED_HOSTS` check in `Site.find_for_request` (Jake Howard)
|
||||
* Maintenance: Update `CloneController` to ensure that `added`/`cleared` events are not dispatched as cancelable (LB (Ben) Johnston)
|
||||
* Maintenance: Remove unused `uuid` UMD module as all code is now using the NPM module (LB (Ben) Johnston)
|
||||
* Maintenance: Clean up JS comments throughout codebase to be aligned to JSDoc where practical (LB (Ben) Johnston)
|
||||
* Maintenance: Replace `eslint-disable no-undef` linter directives with `global` comments (LB (Ben) Johnston)
|
||||
* Maintenance: Upgrade Node tooling to active LTS version 22 (LB (Ben) Johnston)
|
||||
* Maintenance: Remove defunct oEmbed providers (Rahul Samant)
|
||||
* Maintenance: Remove obsolete non-upsert-based code for Postgres search indexing (Jake Howard)
|
||||
* Maintenance: Remove unused Rangy JS library (LB (Ben) Johnston)
|
||||
* Maintenance: Update `PreviewController` usage to leverage Stimulus actions instead of calling `preventDefault` manually (Ayaan Qadri)
|
||||
* Maintenance: Various performance optimizations to page publishing (Jake Howard)
|
||||
* Maintenance: Remove unnecessary DOM canvas.toBlob polyfill (LB (Ben) Johnston)
|
||||
* Maintenance: Ensure Storybook core files are correctly running through Eslint (LB (Ben) Johnston)
|
||||
* Maintenance: Add a new Stimulus `ZoneController` (`w-zone`) to support dynamic class name changes & event handling on container elements (Ayaan Qadri)
|
||||
* Maintenance: Migrate jQuery class toggling & drag/drop event handling within the multiple upload views to the Stimulus ZoneController usage (Ayaan Qadri)
|
||||
* Maintenance: Test project template for warnings when run against Django pre-release versions (Sage Abdullah)
|
||||
* Maintenance: Refactor redirects create/delete views to use generic views (Sage Abdullah)
|
||||
* Maintenance: Add JSDoc description, adopt linting recommendations, and add more unit tests for `ModalWorkflow` (LB (Ben) Johnston)
|
||||
* Maintenance: Add support for for a `delay` value in `TagController` to debounce async autocomplete tag fetch requests (Aayushman Singh)
|
||||
* Maintenance: Add unit tests, Storybook stories & JSDoc items for the Stimulus `DrilldownController` (Srishti Jaiswal)
|
||||
* Maintenance: Enhance sidebar preview performance by eliminating duplicate asset loads on preview error (Sage Abdullah)
|
||||
* Maintenance: Remove unused `LinkController` (`w-link`) (Sage Abdullah)
|
||||
* Maintenance: Refactor settings `EditView` to make better use of generic `EditView` (Sage Abdullah)
|
||||
* Maintenance: Add a new Stimulus `RulesController` (`w-rules`) to support declarative conditional field enabling from other field values in a form (LB (Ben) Johnston)
|
||||
* Maintenance: Migrate the conditional enabling of fields in the image URL builder view away from ad-hoc jQuery to use the `RulesController` (`w-rules`) approach (LB (Ben) Johnston)
|
||||
* Maintenance: Enhance the Stimulus `ZoneController` (`w-zone`) to support inactive class and a mechanism to switch the mode based on data within events (Ayaan Qadri)
|
||||
* Maintenance: Use the Stimulus `ZoneController` (`w-zone`) to remove ad-hoc jQuery for the privacy switch when toggling visibility of private/public elements (Ayaan Qadri)
|
||||
* Maintenance: Remove unused `is_active` & `active_menu_items` from `wagtail.admin.menu.MenuItem` (Srishti Jaiswal)
|
||||
* Maintenance: Only call `openpyxl` at runtime to improve performance for projects that do not use `ReportView`, `SpreadsheetExportMixin` and `wagtail.contrib.redirects` (Sébastien Corbin)
|
||||
* Maintenance: Adopt the update value `mp` instead of `mm` for 'mystery person' as the default Gravatar if no avatar found (Harsh Dange)
|
||||
* Maintenance: Refactor search promotions views to use generic views and templates (Sage Abdullah, Rohit Sharma)
|
||||
* Maintenance: Use built-in `venv` instead of `pipenv` in CircleCI (Sage Abdullah)
|
||||
* Maintenance: Add a new Stimulus `FormsetController` (`w-formset`) to support dynamic formset insertion/deletion behavior (LB (Ben) Johnston)
|
||||
* Maintenance: Enable breadcrumbs by default on admin views using generic templates (Sage Abdullah)
|
||||
* Maintenance: Refactor pages `revisions_revert` view to be a subclass of `EditView` (Sage Abdullah)
|
||||
* Maintenance: Move images and documents `get_usage().count()` call to view code (Sage Abdullah)
|
||||
* Maintenance: Upgrade sass-loader to resolve Sass deprecation warnings (Ayaan Qadri)
|
||||
|
||||
|
||||
6.3.4 (xx.xx.xxxx) - IN DEVELOPMENT
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* Added support for Django 5.2
|
||||
* Fix: Add missing “Close” label to the upgrade notification dismiss button (Sage Abdullah)
|
||||
* Fix: Fix white text on white background in previews for sites that use color-scheme without a background-color (Sage Abdullah)
|
||||
* Maintenance: Remove upper version boundary for django-filter (Dan Braghis)
|
||||
|
||||
|
||||
6.3.3 (03.02.2025)
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* Fix: Correctly place comment buttons next to date / datetime / time fields. (Srishti Jaiswal)
|
||||
* Fix: Reduce confusing spacing below StreamField blocks help text (Rishabh Sharma)
|
||||
* Fix: Make sure alt text quality check is on by default as documented (Thibaud Colas)
|
||||
* Fix: Prevent `StreamChildrenToListBlockOperation` from duplicating data across multiple StreamField instances (Joshua Munn)
|
||||
* Fix: Prevent database error when calling permission_order.register on app ready (Daniel Kirkham, Matt Westcott)
|
||||
* Fix: Prevent error on lazily loading StreamField blocks after the stream has been modified (Stefan Hammer)
|
||||
* Fix: Prevent syntax error on MySQL search when query includes symbols (Matt Westcott)
|
||||
* Docs: Update example for customizing "p-as-heading" accessibility check without overriding built-in checks (Cynthia Kiser)
|
||||
* Docs: Update accessibility considerations on alt text in light of contextual alt text improvements (Cynthia Kiser)
|
||||
* Docs: Revert incorrect example of appending a `RichTextBlock` to a `StreamField` (Matt Westcott)
|
||||
|
||||
|
||||
6.3.2 (02.01.2025)
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* Fix: Ensure CloudFront cache invalidation is called with a list, for compatibility with current botocore versions (Jake Howard)
|
||||
* Fix: Ensure Draftail features wrap when a large amount of features are added (Bart Cieliński)
|
||||
* Fix: Implement `get_block_by_content_path` on `ImageBlock` to prevent errors on commenting (Matt Westcott)
|
||||
* Docs: Update tutorial to reflect the move of the "Add child page" action to a top-level button in the header as a '+' icon (Clifford Gama)
|
||||
|
||||
|
||||
6.3.1 (19.11.2024)
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* Fix: Restore ability to upload profile picture through account settings (Sage Abdullah)
|
||||
* Fix: Correctly handle `ImageChooserBlock` to `ImageBlock` data conversions where all inputs to `bulk_to_python` are null (Storm Heg, Matt Westcott)
|
||||
* Fix: Improve spacing of page / collection permissions table in Group settings (Sage Abdullah)
|
||||
* Fix: Remove forced capitalization of site name on admin dashboard (Thibaud Colas)
|
||||
* Docs: Reword `BlogTagIndexPage` example for clarity (Clifford Gama)
|
||||
* Docs: Change title of blog index page in tutorial to avoid slug issues (Thibaud Colas)
|
||||
* Docs: Fix `wagtailcache` and `wagtailpagecache` examples to not use quotes for the `fragment_name` (Shiv)
|
||||
* Docs: Lower search result ranking for release notes on readthedocs search (Sage Abdullah)
|
||||
|
||||
|
||||
6.3 LTS (01.11.2024)
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* Add support for Python 3.13 (Matt Westcott)
|
||||
|
@ -32,6 +291,7 @@ Changelog
|
|||
* Secondary form actions such as "Delete" are now in the header actions menu (Sage Abdullah)
|
||||
* Allow setting page privacy rules when a restriction already exists on an ancestor page (Bojan Mihelac)
|
||||
* Automatically create links when pasting content that contain URLs into a rich text input (Thibaud Colas)
|
||||
* Add Uyghur language support
|
||||
* Fix: Prevent page type business rules from blocking reordering of pages (Andy Babic, Sage Abdullah)
|
||||
* Fix: Improve layout of object permissions table (Sage Abdullah)
|
||||
* Fix: Fix typo in aria-label attribute of page explorer navigation link (Sébastien Corbin)
|
||||
|
@ -47,7 +307,7 @@ Changelog
|
|||
* Fix: Fix content path links in usage view to scroll to the correct element (Sage Abdullah)
|
||||
* Fix: Always show the minimap toggle button (Albina Starykova)
|
||||
* Fix: Ensure that dropdown button toggles show with a border in high contrast mode (Ishwari8104, LB (Ben) Johnston)
|
||||
* Fix: Update email notification header to the new logo design (rahulsamant37)
|
||||
* Fix: Update email notification header to the new logo design (Rahul Samant)
|
||||
* Fix: Change `file_size` field on document model to avoid artificial 2Gb limit (Gabriel Getzie)
|
||||
* Fix: Ensure that `TypedTableBlock` uses the correct API representations of child blocks (Matt Westcott)
|
||||
* Fix: Footer action buttons now include their `media` definitions (Sage Abdullah)
|
||||
|
@ -56,13 +316,19 @@ Changelog
|
|||
* Fix: Fix datetime fields overflowing its parent wrapper in listing filters (Rohit Singh)
|
||||
* Fix: Prevent multiple URLs from being combined into one when pasting links into a rich text input (Thibaud Colas)
|
||||
* Fix: Improve layout of report listing tables (Sage Abdullah)
|
||||
* Fix: Fix regression from creation of `AbstractGroupApprovalTask` to ensure `can_handle` checks for the abstract class correctly (Sumana Sree Angajala)
|
||||
* Docs: Upgrade Sphinx to 7.3 (Matt Westcott)
|
||||
* Docs: Upgrade sphinx-wagtail-theme to v6.4.0, with a new search integration and Read the Docs Addons bug fixes (Thibaud Colas)
|
||||
* Docs: Document how to customize date/time format settings (Vince Salvino)
|
||||
* Docs: Create a new documentation section for deployment and move fly.io deployment from the tutorial to this section (Vince Salvino)
|
||||
* Docs: Clarify process for UserViewSet customization (Sage Abdullah)
|
||||
* Docs: Correct `WAGTAIL_WORKFLOW_REQUIRE_REAPPROVAL_ON_EDIT` documentation to state that it defaults to `False` (Matt Westcott)
|
||||
* Docs: Add an example of customizing a default accessibility check (Cynthia Kiser)
|
||||
* Docs: Demonstrate access protection with `TokenAuthentication` in the Wagtail API v2 Configuration Guide (Krzysztof Jeziorny)
|
||||
* Docs: Replace X links with Mastodon in the README (Alex Morega)
|
||||
* Docs: Re-enable building offline formats in online documentation (Read the docs) for EPUB/PDF/HTML downloads (Joel William, Sage Abdullah)
|
||||
* Docs: Resolve multiple output errors in the documentation ePub format (Sage Abdullah)
|
||||
* Docs: Update social media examples to use LinkedIn, Reddit, Facebook (Ayaan Qadri)
|
||||
* Maintenance: Removed support for Python 3.8 (Matt Westcott)
|
||||
* Maintenance: Drop pytz dependency in favour of `zoneinfo.available_timezones` (Sage Abdullah)
|
||||
* Maintenance: Relax django-taggit dependency to allow 6.0 (Matt Westcott)
|
||||
|
@ -85,6 +351,16 @@ Changelog
|
|||
* Maintenance: Remove `image_format_name_to_content_type` helper function that duplicates Willow functionality (Matt Westcott)
|
||||
* Maintenance: Improve code reuse for footer actions markup across generic views (Sage Abdullah)
|
||||
* Maintenance: Deprecate internal `DeleteMenuItem` API for footer actions (Sage Abdullah)
|
||||
* Maintenance: Update Pillow dependency to allow 11.x (Storm Heg)
|
||||
|
||||
|
||||
6.2.3 (01.11.2024)
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* Fix: Prevent multiple URLs from being combined into one when pasting links into a rich text input (Thibaud Colas)
|
||||
* Fix: Fix error on workflow settings view with multiple snippet types assigned to the same workflow on Postgres (Sage Abdullah)
|
||||
* Fix: Prevent history view from breaking if a log entry's revision is missing (Matt Westcott)
|
||||
* Docs: Upgrade sphinx-wagtail-theme to v6.4.0, with a new search integration and Read the Docs Addons bug fixes (Thibaud Colas)
|
||||
|
||||
|
||||
6.2.2 (24.09.2024)
|
||||
|
@ -542,6 +818,23 @@ Changelog
|
|||
* Maintenance: Remove support for Django 4.1 and below (Sage Abdullah)
|
||||
|
||||
|
||||
5.2.8 (03.02.2025)
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* Fix: Prevent database error when calling permission_order.register on app ready (Daniel Kirkham, Matt Westcott)
|
||||
* Fix: Handle StreamField migrations where the field value is null (Joshua Munn)
|
||||
* Fix: Prevent `StreamChildrenToListBlockOperation` from duplicating data across multiple StreamField instances (Joshua Munn)
|
||||
* Fix: Prevent error on lazily loading StreamField blocks after the stream has been modified (Stefan Hammer)
|
||||
* Fix: Prevent syntax error on MySQL search when query includes symbols (Matt Westcott)
|
||||
|
||||
|
||||
5.2.7 (01.11.2024)
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* Fix: Prevent multiple URLs from being combined into one when pasting links into a rich text input (Thibaud Colas)
|
||||
* Fix: Fix error on workflow settings view with multiple snippet types assigned to the same workflow on Postgres (Sage Abdullah)
|
||||
|
||||
|
||||
5.2.6 (11.07.2024)
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -4098,7 +4391,7 @@ Changelog
|
|||
* Fix: Fixed TypeError when getting embed HTML with oembed on Python 3 (John-Scott Atlakson)
|
||||
* Fix: Made HTML whitelisting in rich text fields more robust at catching disallowed URL schemes such as "jav\tascript:" (Tim Heap)
|
||||
* Fix: created_at timestamps on page revisions were not being preserved on page copy, causing revisions to get out of sequence
|
||||
* Fix: When copying pages recursively, revisions of sub-pages were being copied regardless of the copy_revisions flag
|
||||
* Fix: When copying pages recursively, revisions of subpages were being copied regardless of the copy_revisions flag
|
||||
* Fix: Updated the migration dependencies within the project template to ensure that Wagtail's own migrations consistently apply first.
|
||||
* Fix: The cache of site root paths is now cleared when a site is deleted.
|
||||
* Fix: Search indexing now prevents pages from being indexed multiple times, as both the base Page model and the specific subclass
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* Cynthia Kiser (Caltech)
|
||||
* Dan Braghis (Torchbox)
|
||||
* Dawn Wages (The Wharton School)
|
||||
* Jacob Topp-Mugglestone (Torchbox)
|
||||
* Emily Topp-Mugglestone (Torchbox)
|
||||
* Jake Howard (Torchbox)
|
||||
* Kalob Taulien
|
||||
* LB Johnston
|
||||
|
@ -15,6 +15,7 @@
|
|||
* Sævar Öfjörð Magnússon (Overcast)
|
||||
* Sage Abdullah (Torchbox)
|
||||
* Scott Cranfill (JPL)
|
||||
* Sébastien Corbin
|
||||
* Stefan Hammer (wunderweiss)
|
||||
* Storm Heg
|
||||
* Thibaud Colas (Torchbox)
|
||||
|
@ -719,7 +720,6 @@
|
|||
* Kevin Chung (kev-odin)
|
||||
* valnuro
|
||||
* Vitaly Babiy
|
||||
* Sébastien Corbin
|
||||
* Sahil Jangra
|
||||
* Henry Harutyunyan
|
||||
* Alex Morega
|
||||
|
@ -743,7 +743,6 @@
|
|||
* Sandro Rodrigues
|
||||
* Brian Mugo
|
||||
* Panagiotis H.M. Issaris
|
||||
* Damilola Oladele
|
||||
* Olumide Micheal
|
||||
* Chiemezuo Akujobi
|
||||
* Krish Soni
|
||||
|
@ -836,7 +835,7 @@
|
|||
* Shubham Mukati
|
||||
* Matthew Scouten
|
||||
* Ishwari8104
|
||||
* rahulsamant37
|
||||
* Rahul Samant
|
||||
* Gabriel Getzie
|
||||
* Rohit Singh
|
||||
* Robin Varghese
|
||||
|
@ -846,11 +845,44 @@
|
|||
* Ankit Kumar
|
||||
* Frank Yiu
|
||||
* Shaurya Panchal
|
||||
* Sumana Sree Angajala
|
||||
* Srishti Jaiswal
|
||||
* Alessandro Chitarrini
|
||||
* Joel William
|
||||
* Ataf Fazledin Ahamed
|
||||
* Ayaan Qadri
|
||||
* manu
|
||||
* Aayushman Singh
|
||||
* Steven Steinwand
|
||||
* Clifford Gama
|
||||
* Noah van der Meer
|
||||
* Strapchay
|
||||
* Alex Fulcher
|
||||
* Harsh Dange
|
||||
* Mauro Soche
|
||||
* Krystian Magdziarz
|
||||
* Guilhem Saurel
|
||||
* James Harrington
|
||||
* Unyime Emmanuel Udoh
|
||||
* Joren Hammudoglu
|
||||
* Rishabh Sharma
|
||||
* Mike Gifford
|
||||
* Stéphane Blondon
|
||||
* Jatin Bhardwaj
|
||||
* Mohamed Rabiaa
|
||||
* Bernhard Bliem
|
||||
* Mahmoud Nasser
|
||||
* Prabhpreet Kaur
|
||||
* Baptiste Mispelon
|
||||
* Mohammad Fathi Rahman
|
||||
* Ashish Nagmoti
|
||||
* Dhruvi Patel
|
||||
* Sylvain Boissel
|
||||
|
||||
## Translators
|
||||
|
||||
* Afrikaans: Jaco du Plessis, Jared Osborn
|
||||
* Arabic: Bashar Al-Abdulhadi, Abdulaziz Alfuhigi, Roger Allen, Khaled Arnaout, Amr Awad, Mohammed Abdul Gadir, Mohamed HossamElDin, Ahmad Kiswani, Waseem Kntar, Mahmoud Marayef, Mohamed Mayla, Ahmed Miske Sidi Med, Younes Oumakhou, Ultraify Media
|
||||
* Arabic: Bashar Al-Abdulhadi, Abdulaziz Alfuhigi, Roger Allen, Khaled Arnaout, Amr Awad, Tarek Berkane, Mohammed Abdul Gadir, Mohamed HossamElDin, Ahmad Kiswani, Waseem Kntar, Mahmoud Marayef, Mohamed Mayla, Ahmed Miske Sidi Med, Younes Oumakhou, Ultraify Media
|
||||
* Armenian: Vachagan
|
||||
* Azerbaijani: Mirza Iskandarov
|
||||
* Bangla: Mahmud Abdur Rahman
|
||||
|
@ -866,11 +898,11 @@
|
|||
* Czech: Ales Dvorak, Jan Feřtek, Martin Galda, IT Management, Tomáš Jeřábek, Vláďa Macek, Eva Mikesova, Mořeplavec, Sophy O, Martina Oleksakova, Kryštof Pilnáček, Tomáš Podivínský, Ivan Pomykacz, Jiri Stepanek, Marek Turnovec, Mirek Zvolský
|
||||
* Danish: Benjamin Bach, Mads Kronborg, MRostgaard, Asger Sørensen
|
||||
* Divehi: Fauzaan Gasim
|
||||
* Dutch: benny_AT_it_digin.com, Bram, Ramon de Jezus Brecht Dervaux, Harmen, Storm Heg, Kees Hink, Huib Keemink, Franklin Kingma, Maarten Kling, Thijs Kramer, Samuel Leeuwenburg, mahulst, Meteor0id, Rob Moorman, Benjamin van Renterghem, Michael van Tellingen, Arne Turpyn, Coen van der Kamp, Richard Voorhorst
|
||||
* Dutch: benny_AT_it_digin.com, Bram, Ramon de Jezus Brecht Dervaux, Harmen, Storm Heg, Kees Hink, Huib Keemink, Franklin Kingma, Maarten Kling, Thijs Kramer, Samuel Leeuwenburg, mahulst, Meteor0id, Rob Moorman, Benjamin van Renterghem, Michael van Tellingen, Arne Turpyn, Coen van der Kamp, Joeri Vlekken, Richard Voorhorst
|
||||
* English (India): Neeraj PY, Apoorv Saini
|
||||
* Estonian: Erlend Eelmets, Martin, Ragnar Rebase
|
||||
* Finnish: Jiri Grönroos, Eetu Häivälä, Niklas Jerva, Aarni Koskela, Rauli Laine, Valter Maasalo, Glen Somerville, Juha Yrjölä
|
||||
* French: Adrien, Timothy Allen, Sebastien Andrivet, Bertrand Bordage, André Bouatchidzé, Sébastien Corbin, Aurélien Debord, Romain Dorgueil, Tom Dyson, Antonin Enfrun, Axel Haustant, Renaud Kern, Fabien Le Frapper, Léo, Pierre Marfoure, nahuel, Sophy O, Aurel Pere, Dominique Peretti, fpoulain, Loïc Teixeira, Benoît Vogel
|
||||
* French: Adrien, Timothy Allen, Sebastien Andrivet, Bertrand Bordage, André Bouatchidzé, Christophe Chauvet, Sébastien Corbin, Aurélien Debord, Romain Dorgueil, Tom Dyson, Antonin Enfrun, Axel Haustant, Renaud Kern, Fabien Le Frapper, Léo, Pierre Marfoure, nahuel, Sophy O, Aurel Pere, Dominique Peretti, fpoulain, Loïc Teixeira, Benoît Vogel
|
||||
* Galician: X Bello, Amós Oviedo
|
||||
* Georgian: André Bouatchidzé
|
||||
* German: Ettore Atalan, Bohreromir, Matti Borchers, Benedikt Breinbauer, Donald Buczek, Patrick Craston, Peter Dreuw, Oliver Engel, Stefan Hammer, Patrick Hebner, Krzysztof Jeziorny, Benjamin Kaspar, Henrik Kröger, Tibor L, Tammo van Lessen, Martin Löhle, Wasilis Mandratzis-Walz, Daniel Manser, Matthias Martin, m0rph3u5, Max Pfeiffer, Moritz Pfeiffer, Herbert Poul, Karl Sander, Tobias Schmidt, Scriptim, Johannes Spielmann, Raphael Stolt, Benjamin Thurm, Norman Uekermann, unicode_it, Jannis Vajen, Florian Vogt, Alexander Weiß, Matthew Westcott, Benedikt Willi
|
||||
|
|
2
Makefile
2
Makefile
|
@ -14,7 +14,7 @@ clean-pyc:
|
|||
find . -name '*~' -exec rm -f {} +
|
||||
|
||||
develop: clean-pyc
|
||||
pip install -e .[testing,docs]
|
||||
pip install -e .[testing,docs] --config-settings editable-mode=strict
|
||||
npm install --no-save && npm run build
|
||||
|
||||
lint-server:
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
<a href="https://pypi.python.org/pypi/wagtail/">
|
||||
<img src="https://img.shields.io/pypi/dm/wagtail?logo=Downloads" alt="Monthly downloads" />
|
||||
</a>
|
||||
<a href="https://x.com/WagtailCMS">
|
||||
<img src="https://img.shields.io/twitter/follow/WagtailCMS?style=social&logo=twitter" alt="follow on X">
|
||||
<a href="https://fosstodon.org/@wagtail">
|
||||
<img src="https://img.shields.io/mastodon/follow/109308882653647818?domain=https%3A%2F%2Ffosstodon.org&style=social" alt="Follow @wagtail@fosstodon.org">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
|
@ -84,7 +84,7 @@ _(If you are reading this on GitHub, the details here may not be indicative of t
|
|||
|
||||
Wagtail supports:
|
||||
|
||||
- Django 4.2.x, 5.0.x and 5.1.x
|
||||
- Django 4.2.x and 5.1.x
|
||||
- Python 3.9, 3.10, 3.11, 3.12 and 3.13
|
||||
- PostgreSQL, MySQL, MariaDB and SQLite (with JSON1) as database backends
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ The features below were developed thanks to the sponsorship of these organsation
|
|||
|
||||
- Page aliases - [The Mozilla Foundation](https://foundation.mozilla.org/en/)
|
||||
|
||||
- Hooks for Snippet customisation - [The Mozilla Foundation](https://foundation.mozilla.org/en/)
|
||||
- Hooks for Snippet customization - [The Mozilla Foundation](https://foundation.mozilla.org/en/)
|
||||
|
||||
- Utility for testing hooks - [The Mozilla Foundation](https://foundation.mozilla.org/en/)
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
@import 'settings/variables';
|
||||
@forward 'settings/variables';
|
||||
|
|
|
@ -3,8 +3,8 @@ These are functions and mixins.
|
|||
No CSS should be produced by these files.
|
||||
*/
|
||||
|
||||
@import 'tools/functions.breakpoints';
|
||||
@import 'tools/mixins.breakpoints';
|
||||
@import 'tools/mixins.general';
|
||||
@import 'tools/mixins.grid';
|
||||
@import 'tools/mixins.guide-line';
|
||||
@forward 'tools/functions.breakpoints';
|
||||
@forward 'tools/mixins.breakpoints';
|
||||
@forward 'tools/mixins.general';
|
||||
@forward 'tools/mixins.grid';
|
||||
@forward 'tools/mixins.guide-line';
|
||||
|
|
|
@ -1,8 +1,13 @@
|
|||
@use '../tools' as *;
|
||||
|
||||
.w-a11y-result__row {
|
||||
@include box;
|
||||
padding: theme('spacing.4');
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
background-color: theme('colors.surface-page');
|
||||
padding: theme('spacing.4');
|
||||
border-radius: theme('borderRadius.DEFAULT');
|
||||
color: theme('colors.text-context');
|
||||
border: 1px solid theme('colors.border-furniture');
|
||||
|
||||
// Shows additional details within the CMS only.
|
||||
.form-side--checks & {
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
@use '../tools' as *;
|
||||
|
||||
// user avatars
|
||||
.avatar {
|
||||
border-radius: 100%;
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
@use '../tools' as *;
|
||||
|
||||
.w-breadcrumbs:not(.editor-view .w-breadcrumbs) {
|
||||
@apply sm:w-py-2.5;
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
@use '../tools' as *;
|
||||
|
||||
.bulk-actions-filter-checkbox {
|
||||
.table-headers & {
|
||||
> div {
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
// Core button styles
|
||||
|
||||
@use 'sass:color';
|
||||
@use '../tools' as *;
|
||||
@use '../settings' as *;
|
||||
|
||||
.button {
|
||||
border-radius: theme('borderRadius.sm');
|
||||
|
@ -321,7 +323,6 @@
|
|||
}
|
||||
|
||||
.w-header-button {
|
||||
@include more-contrast-interactive();
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
@ -337,6 +338,8 @@
|
|||
font-weight: theme('fontWeight.medium');
|
||||
cursor: pointer;
|
||||
|
||||
@include more-contrast-interactive();
|
||||
|
||||
.icon {
|
||||
width: theme('spacing.4');
|
||||
height: theme('spacing.4');
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
@use 'sass:math';
|
||||
@use '../tools' as *;
|
||||
|
||||
$preview-size: 2.625rem; // 42px
|
||||
|
||||
|
@ -15,7 +16,6 @@ $preview-size: 2.625rem; // 42px
|
|||
// Very subdued button style specifically for choosers, as there can be a lot of
|
||||
// chooser fields left unused on a page editing form.
|
||||
.button.chooser__choose-button {
|
||||
@include more-contrast-interactive();
|
||||
@apply w-label-3;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
@ -23,6 +23,8 @@ $preview-size: 2.625rem; // 42px
|
|||
border-color: transparent;
|
||||
padding: theme('spacing.[1.5]');
|
||||
|
||||
@include more-contrast-interactive();
|
||||
|
||||
.icon {
|
||||
@include svg-icon(theme('spacing.4'), initial);
|
||||
color: inherit;
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
@use '../tools' as *;
|
||||
|
||||
.w-dialog {
|
||||
--w-dialog-close-icon-color: theme('colors.icon-primary');
|
||||
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
// stylelint-disable selector-attribute-name-disallowed-list
|
||||
@use '../tools' as *;
|
||||
@use '../settings' as *;
|
||||
|
||||
$separator: 1px solid theme('colors.white-15');
|
||||
$radius: theme('borderRadius.sm');
|
||||
|
||||
|
@ -26,16 +29,6 @@ $radius: theme('borderRadius.sm');
|
|||
width: 100%;
|
||||
}
|
||||
|
||||
@supports not selector(:has(*)) {
|
||||
// Use no corner radius and always-on borders if `:has` is not supported.
|
||||
--primary-button-radius-top: 0;
|
||||
--primary-button-radius-bottom: 0;
|
||||
--toggle-button-radius-top: 0;
|
||||
--toggle-button-radius-bottom: 0;
|
||||
--first-item-border-top: #{$separator};
|
||||
--last-item-border-top: #{$separator};
|
||||
}
|
||||
|
||||
&:has(:not([hidden]) > [data-placement^='bottom']) {
|
||||
--primary-button-radius-top: #{$radius};
|
||||
--primary-button-radius-bottom: 0;
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
@use '../tools' as *;
|
||||
|
||||
.filterable {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr minmax(theme('spacing.48'), theme('spacing.64'));
|
||||
|
@ -25,7 +27,6 @@
|
|||
}
|
||||
|
||||
.w-filter-button {
|
||||
@include more-contrast-interactive();
|
||||
position: relative;
|
||||
width: theme('spacing.10');
|
||||
height: theme('spacing.10');
|
||||
|
@ -35,6 +36,8 @@
|
|||
color: theme('colors.text-link-default');
|
||||
background-color: theme('backgroundColor.surface-header');
|
||||
|
||||
@include more-contrast-interactive();
|
||||
|
||||
.icon {
|
||||
width: theme('fontSize.16');
|
||||
height: theme('fontSize.16');
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
@use 'sass:math';
|
||||
@use '../tools' as *;
|
||||
@use '../settings' as *;
|
||||
|
||||
.footer {
|
||||
@include transition(bottom 0.5s ease 1s);
|
||||
|
@ -116,7 +118,6 @@
|
|||
|
||||
.actions .button {
|
||||
@apply w-leading-none w-inline-flex w-items-center;
|
||||
font-size: theme('fontSize.16');
|
||||
font-weight: 600;
|
||||
padding: 0 theme('spacing.3');
|
||||
white-space: initial;
|
||||
|
@ -138,6 +139,7 @@
|
|||
}
|
||||
|
||||
> .button {
|
||||
font-size: theme('fontSize.16');
|
||||
flex-grow: 1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
@use 'sass:color';
|
||||
@use 'sass:map';
|
||||
@use 'sass:math';
|
||||
@use '../tools' as *;
|
||||
|
||||
.side-panel-open {
|
||||
@apply w-overflow-y-hidden sm:w-overflow-y-auto;
|
||||
|
@ -85,13 +86,6 @@
|
|||
&:focus-within:has(:focus-visible) {
|
||||
@include focus-outline;
|
||||
}
|
||||
|
||||
@supports not selector(:focus-visible) {
|
||||
&:focus-within {
|
||||
/* Fallback for browsers without :focus-visible support */
|
||||
@include focus-outline;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__resize-grip-icon {
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
@use '../tools' as *;
|
||||
@use '../settings' as *;
|
||||
|
||||
.wrapper {
|
||||
@include clearfix();
|
||||
@apply w-transition-sidebar;
|
||||
|
@ -14,27 +17,30 @@
|
|||
}
|
||||
|
||||
/**
|
||||
* Increase the scroll offset to account for pages with a sticky header.
|
||||
* Increase the scroll offset to account for pages with sticky areas - header or footer.
|
||||
* We apply this to all pages for simplicity.
|
||||
*/
|
||||
@mixin slim-header-scroll-offset() {
|
||||
@mixin sticky-areas-scroll-offset() {
|
||||
$gap: theme('spacing.4');
|
||||
// For mobile viewports, expect a sticky header over two rows.
|
||||
scroll-padding-top: calc(theme('spacing.slim-header') * 2 + $gap);
|
||||
|
||||
@include media-breakpoint-up(sm) {
|
||||
scroll-padding-top: calc(theme('spacing.slim-header') + $gap);
|
||||
// Increase the scroll offset to account for pages with sticky bottom button
|
||||
scroll-padding-bottom: 100px;
|
||||
}
|
||||
}
|
||||
|
||||
.content-wrapper {
|
||||
@include slim-header-scroll-offset();
|
||||
scroll-behavior: smooth;
|
||||
width: 100%;
|
||||
height: 100%; // this has no effect on desktop, but on mobile it helps aesthetics of menu popout action
|
||||
float: inline-start;
|
||||
position: relative;
|
||||
border-bottom: 1px solid theme('colors.border-furniture');
|
||||
|
||||
@include sticky-areas-scroll-offset();
|
||||
}
|
||||
|
||||
.content {
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
@use 'sass:math';
|
||||
@use 'sass:color';
|
||||
@use '../tools' as *;
|
||||
@use '../settings' as *;
|
||||
|
||||
.w-header {
|
||||
@apply w-text-text-label;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
@use 'sass:color';
|
||||
@use 'sass:map';
|
||||
@use '../tools' as *;
|
||||
// Help text formatters
|
||||
.help-block {
|
||||
padding: 1em;
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
@use 'sass:string';
|
||||
@use '../tools' as *;
|
||||
@use '../settings' as *;
|
||||
|
||||
// Set SVG icons to use the current text color in the location they appear as
|
||||
// their default fill color. Can be overridden for a specific icon by either
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
@use '../tools' as *;
|
||||
|
||||
/* stylelint-disable selector-max-combinators */
|
||||
// General listings, like for pages, images or snippets
|
||||
ul.listing {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
@use 'sass:map';
|
||||
@use '../settings' as *;
|
||||
// Loading mask: overlays a certain area with a loading spinner and a faded out cover to prevent interaction
|
||||
.loading-mask {
|
||||
&.loading {
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
@use '../tools' as *;
|
||||
|
||||
// Messages are specific to Django's 'Messaging' system which adds messages into the session,
|
||||
// for display on the next page visited. These appear as an animated banner at the top of the page.
|
||||
// For inline help text, see typography.scss
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
@use '../tools' as *;
|
||||
|
||||
$zindex-modal-background: 500;
|
||||
|
||||
.fade {
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
@use '../tools' as *;
|
||||
@use '../settings' as *;
|
||||
|
||||
$header-icon-size: theme('spacing.4');
|
||||
$header-button-size: theme('spacing.6');
|
||||
|
||||
|
@ -61,7 +64,6 @@ $header-button-size: theme('spacing.6');
|
|||
.w-panel__toggle,
|
||||
.w-panel__controls .button.button--icon {
|
||||
@include show-focus-outline-inside();
|
||||
@include more-contrast-interactive();
|
||||
display: inline-grid;
|
||||
justify-content: center;
|
||||
align-content: center;
|
||||
|
@ -72,6 +74,8 @@ $header-button-size: theme('spacing.6');
|
|||
width: $header-button-size;
|
||||
height: $header-button-size;
|
||||
|
||||
@include more-contrast-interactive();
|
||||
|
||||
&:focus-visible,
|
||||
&:hover {
|
||||
color: theme('colors.icon-primary-hover');
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
@use '../tools' as *;
|
||||
|
||||
.w-preview {
|
||||
--w-preview-background-color: var(--w-color-white);
|
||||
--w-preview-color-scheme: normal;
|
||||
--preview-width-ratio: min(
|
||||
1,
|
||||
var(--preview-panel-width, 450) / var(--preview-device-width, 375)
|
||||
|
@ -37,6 +40,16 @@
|
|||
&:empty {
|
||||
// Ensure that sites without a background show with a fallback, only when iframe has loaded
|
||||
background-color: var(--w-preview-background-color);
|
||||
// Sites that do not have a background but have color-scheme will have the
|
||||
// colors (background, text, etc.) automatically styled by the browser.
|
||||
// If the color-scheme matches Wagtail's current color-scheme, the browser
|
||||
// will give the iframe a transparent background. If we only set the
|
||||
// white background-color above, the white background will be used
|
||||
// while the rest of the content follows the color-scheme of the site,
|
||||
// which might result in white text on a white background.
|
||||
// Since we cannot know the actual value of the content's color-scheme,
|
||||
// we set the color-scheme to normal to ensure the iframe stays opaque.
|
||||
color-scheme: var(--w-preview-color-scheme);
|
||||
}
|
||||
|
||||
[dir='rtl'] & {
|
||||
|
@ -198,5 +211,12 @@
|
|||
width: 0;
|
||||
height: 0;
|
||||
opacity: 0;
|
||||
|
||||
// Remove mask-image from radio inputs to avoid loading the default icon,
|
||||
// use extra specificity to beat the default styles
|
||||
&:is(input[type='radio'])::before {
|
||||
content: none;
|
||||
mask-image: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
@use '../tools' as *;
|
||||
|
||||
.progress {
|
||||
border-radius: 1.2em;
|
||||
background-color: theme('colors.surface-button-hover');
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
@use 'sass:color';
|
||||
@use '../settings' as *;
|
||||
|
||||
.w-status {
|
||||
border-radius: 2px;
|
||||
|
@ -56,8 +57,10 @@ button.w-status:hover {
|
|||
color: theme('colors.text-button-outline-hover');
|
||||
}
|
||||
|
||||
// Special case for text-transform: uppercase.
|
||||
.page-status-tag {
|
||||
@apply w-inline-flex w-items-center w-justify-center w-whitespace-nowrap w-px-1 w-ml-3 w-text-11 w-rounded-sm w-bg-transparent w-text-text-meta w-border w-border-border-furniture w-no-underline w-font-semibold hover:w-border-surface-menus hover:w-text-text-label w-transition more-contrast:w-border more-contrast:w-border-border-interactive-more-contrast hover:more-contrast:w-border-border-interactive-more-contrast-hover;
|
||||
|
||||
// Special case for text-transform: uppercase.
|
||||
// stylelint-disable-next-line property-disallowed-list
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
@use '../tools' as *;
|
||||
|
||||
.w-summary {
|
||||
color: theme('colors.text-link-default');
|
||||
margin-bottom: theme('spacing.3');
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
@use 'sass:map';
|
||||
@use '../tools' as *;
|
||||
@use '../settings' as *;
|
||||
|
||||
// free tagging tags from taggit
|
||||
.tag {
|
||||
border-radius: 2px;
|
||||
|
@ -37,16 +40,16 @@ a.tag:hover {
|
|||
|
||||
.tagfilter {
|
||||
legend {
|
||||
@include media-breakpoint-up(sm) {
|
||||
@include column(2);
|
||||
padding-inline-start: 0;
|
||||
}
|
||||
|
||||
font-weight: 700;
|
||||
color: theme('colors.text-context');
|
||||
font-size: 1.1em;
|
||||
display: block;
|
||||
padding: 0 0 0.8em;
|
||||
|
||||
@include media-breakpoint-up(sm) {
|
||||
@include column(2);
|
||||
padding-inline-start: 0;
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
@use 'sass:map';
|
||||
@use 'sass:math';
|
||||
@use 'sass:string';
|
||||
@use '../tools' as *;
|
||||
|
||||
// =============================================================================
|
||||
// Variables
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
@use '../tools' as *;
|
||||
|
||||
.workflow-timeline {
|
||||
@apply w-label-3;
|
||||
padding: 0;
|
||||
|
@ -41,13 +43,14 @@
|
|||
position: relative;
|
||||
flex-shrink: 0;
|
||||
background: theme('colors.surface-page');
|
||||
@media (forced-colors: active) {
|
||||
background: Canvas;
|
||||
}
|
||||
margin-inline-end: theme('spacing.[2.5]');
|
||||
width: theme('spacing.5');
|
||||
height: theme('spacing.5');
|
||||
z-index: theme('zIndex.10');
|
||||
|
||||
@media (forced-colors: active) {
|
||||
background: Canvas;
|
||||
}
|
||||
}
|
||||
|
||||
&__line {
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
@use '../tools' as *;
|
||||
|
||||
@include media-breakpoint-up(sm) {
|
||||
.browsermessage {
|
||||
margin: 0 0 0 -150px;
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
@use '../../settings' as *;
|
||||
|
||||
// file drop zones
|
||||
.drop-zone {
|
||||
border-radius: 5px;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
@use 'sass:map';
|
||||
@use '../../settings' as *;
|
||||
|
||||
.error-message {
|
||||
border: 1px solid transparent; // ensure visible separation in Windows High Contrast mode
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// Comments
|
||||
@use '../../tools' as *;
|
||||
|
||||
$icon-size: theme('spacing.4');
|
||||
$button-padding: theme('spacing.2');
|
||||
|
||||
|
@ -53,14 +54,6 @@ $button-padding: theme('spacing.2');
|
|||
transform: translateY(0);
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.w-field--date_field &,
|
||||
.w-field--date_time_field &,
|
||||
.w-field--time_field & {
|
||||
position: relative;
|
||||
transform: translateY(0);
|
||||
top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.w-field__comment-button--add {
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
@use '../../tools' as *;
|
||||
|
||||
.w-field-row {
|
||||
@include max-form-width();
|
||||
gap: theme('spacing.5');
|
||||
// Ensure there is enough room for a comment button within the gap.
|
||||
gap: theme('spacing.7');
|
||||
// For mobile viewports, we attempt to display all items in the row side by side even if not at the desired size.
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
@use 'sass:map';
|
||||
@use '../../settings' as *;
|
||||
@use './input-base' as *;
|
||||
|
||||
/**
|
||||
* A container for rendering human-readable field values in forms in a way
|
||||
|
@ -6,9 +8,7 @@
|
|||
*/
|
||||
|
||||
.w-field__textoutput {
|
||||
@include input-base();
|
||||
@apply w-body-text-large;
|
||||
background-color: theme('colors.surface-field-inactive');
|
||||
width: 100%;
|
||||
padding: theme('spacing.[1.5]') theme('spacing.5');
|
||||
min-height: $text-input-height;
|
||||
|
@ -16,6 +16,13 @@
|
|||
overflow: hidden;
|
||||
overflow-wrap: break-word;
|
||||
|
||||
@include input-base();
|
||||
|
||||
// stylelint-disable-next-line no-duplicate-selectors, scss/selector-no-redundant-nesting-selector
|
||||
& {
|
||||
background-color: theme('colors.surface-field-inactive');
|
||||
}
|
||||
|
||||
&,
|
||||
&:hover {
|
||||
border-color: theme('colors.border-field-inactive');
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
@use 'sass:map';
|
||||
@use '../../tools' as *;
|
||||
@use '../../settings' as *;
|
||||
|
||||
/**
|
||||
* The field component handles form fields’ layout and ancillary elements such as error messages and help text.
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
@use '../../tools' as *;
|
||||
@use '../../settings' as *;
|
||||
|
||||
.w-form-width {
|
||||
@include max-form-width();
|
||||
}
|
||||
|
|
|
@ -1,15 +1,18 @@
|
|||
@use '../../tools' as *;
|
||||
|
||||
/**
|
||||
* Field styles reusable across **all** fields, including:
|
||||
* Text input, textarea, checkbox, radio, select, etc.
|
||||
*/
|
||||
@mixin input-base() {
|
||||
@include more-contrast-interactive();
|
||||
appearance: none;
|
||||
border-radius: theme('borderRadius.DEFAULT');
|
||||
color: theme('colors.text-context');
|
||||
background-color: theme('colors.surface-field');
|
||||
border: 1px solid theme('colors.border-field-default');
|
||||
|
||||
@include more-contrast-interactive();
|
||||
|
||||
&:hover {
|
||||
border-color: theme('colors.border-field-hover');
|
||||
}
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
@use '../../settings' as *;
|
||||
@use './input-base' as *;
|
||||
|
||||
// All HTML5 input types, with irrelevant ones commented out.
|
||||
// input[type="button"],
|
||||
// input[type="checkbox"],
|
||||
|
@ -22,11 +25,12 @@ input[type="time"],
|
|||
input[type="url"],
|
||||
input[type="week"],
|
||||
textarea {
|
||||
@include input-base();
|
||||
@apply w-body-text-large;
|
||||
width: 100%;
|
||||
padding: theme('spacing.[1.5]') theme('spacing.5');
|
||||
min-height: $text-input-height;
|
||||
|
||||
@include input-base();
|
||||
}
|
||||
|
||||
// Multiline text fields have larger top-bottom padding.
|
||||
|
@ -39,10 +43,13 @@ textarea {
|
|||
resize: none;
|
||||
}
|
||||
|
||||
// Make non-text field types with custom widgets have a smaller width.
|
||||
.w-field--date_field,
|
||||
.w-field--date_time_field,
|
||||
.w-field--time_field {
|
||||
// Make sure comment buttons are as close as possible.
|
||||
display: inline-block;
|
||||
|
||||
// Make non-text field types with custom widgets have a smaller width.
|
||||
input {
|
||||
width: auto;
|
||||
max-width: 100%;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
@use '../../tools' as *;
|
||||
@use '../../settings' as *;
|
||||
|
||||
$header-icon-size: theme('spacing.4');
|
||||
$icon-center-offset: 2px;
|
||||
$guide-line-bottom-margin: calc($form-field-spacing / 3);
|
||||
|
@ -18,11 +21,11 @@ $guide-line-bottom-margin: calc($form-field-spacing / 3);
|
|||
}
|
||||
|
||||
.w-panel__content {
|
||||
@include guide-line-vertical();
|
||||
// Center the vertical line.
|
||||
margin-inline-start: calc(-1 * var(--nesting-indent));
|
||||
padding-inline-start: var(--nesting-indent);
|
||||
margin-bottom: $guide-line-bottom-margin;
|
||||
@include guide-line-vertical();
|
||||
|
||||
@include media-breakpoint-up(sm) {
|
||||
// Extra pixels for better alignment with center of icon.
|
||||
|
@ -54,10 +57,11 @@ $guide-line-bottom-margin: calc($form-field-spacing / 3);
|
|||
|
||||
// Styles for nested panels excluding the top level.
|
||||
.w-panel--nested .w-panel {
|
||||
@include guide-line-nested();
|
||||
margin-inline-start: var(--nesting-indent);
|
||||
margin-bottom: 0;
|
||||
|
||||
@include guide-line-nested();
|
||||
|
||||
.w-panel__content {
|
||||
margin-inline-start: calc(
|
||||
-1 * (var(--nesting-indent) + $icon-center-offset - var(--header-gap) / 2)
|
||||
|
@ -80,9 +84,10 @@ $guide-line-bottom-margin: calc($form-field-spacing / 3);
|
|||
}
|
||||
|
||||
.w-panel__divider {
|
||||
@include guide-line-horizontal();
|
||||
// Slightly nicer text alignment.
|
||||
margin-top: 1px;
|
||||
|
||||
@include guide-line-horizontal();
|
||||
}
|
||||
|
||||
.w-panel__heading--label {
|
||||
|
|
|
@ -7,6 +7,9 @@
|
|||
.w-field--checkbox_select_multiple_with_disabled_options,
|
||||
.w-field--boolean_radio_select,
|
||||
.w-field--radio_select {
|
||||
// Make sure comment buttons are as close as possible.
|
||||
display: inline-block;
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
@use 'sass:math';
|
||||
@use '../../settings' as *;
|
||||
@use './input-base' as *;
|
||||
|
||||
// 24px input widget size.
|
||||
$size: 1.5rem;
|
||||
|
@ -9,7 +11,6 @@ $radio-checkbox-label-gap: theme('spacing.[2.5]');
|
|||
|
||||
// Both input types are very similar in appearance and layout.
|
||||
@mixin radio-checkbox-base() {
|
||||
@include input-base();
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
height: $size;
|
||||
|
@ -19,6 +20,8 @@ $radio-checkbox-label-gap: theme('spacing.[2.5]');
|
|||
// Prevent the checkbox or radio button from shrinking when the label is long.
|
||||
flex-shrink: 0;
|
||||
|
||||
@include input-base();
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
|
@ -39,8 +42,11 @@ $radio-checkbox-label-gap: theme('spacing.[2.5]');
|
|||
|
||||
input[type='radio'] {
|
||||
@include radio-checkbox-base();
|
||||
display: inline-block;
|
||||
border-radius: theme('borderRadius.full');
|
||||
|
||||
// stylelint-disable-next-line no-duplicate-selectors, scss/selector-no-redundant-nesting-selector
|
||||
& {
|
||||
border-radius: theme('borderRadius.full');
|
||||
}
|
||||
|
||||
&:checked::before {
|
||||
mask-image: url('#{$images-root}icons/radio-full.svg');
|
||||
|
@ -49,9 +55,13 @@ input[type='radio'] {
|
|||
|
||||
input[type='checkbox'] {
|
||||
@include radio-checkbox-base();
|
||||
border-radius: theme('borderRadius.sm');
|
||||
// Legacy alignment for checkboxes, particularly within listings.
|
||||
vertical-align: bottom;
|
||||
|
||||
// stylelint-disable-next-line no-duplicate-selectors, scss/selector-no-redundant-nesting-selector
|
||||
& {
|
||||
border-radius: theme('borderRadius.sm');
|
||||
// Legacy alignment for checkboxes, particularly within listings.
|
||||
vertical-align: bottom;
|
||||
}
|
||||
|
||||
&:checked::before {
|
||||
mask-image: url('#{$images-root}icons/check.svg');
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
@use '../../tools' as *;
|
||||
|
||||
.w-required-mark {
|
||||
color: theme('colors.text-error');
|
||||
margin-inline-start: 0.25ch;
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
@use 'sass:map';
|
||||
@use 'sass:math';
|
||||
@use '../../settings' as *;
|
||||
@use './input-base' as *;
|
||||
|
||||
$select-size: $text-input-height;
|
||||
$chevron-size: 0.375rem;
|
||||
|
@ -36,7 +38,6 @@ $chevron-offset: math.div($select-size - $chevron-size, 2);
|
|||
}
|
||||
|
||||
select {
|
||||
@include input-base();
|
||||
@include select-arrow();
|
||||
@apply w-body-text-large;
|
||||
// Firefox workaround – Set a large line height (but smaller than min height) so the field’s text has enough top padding.
|
||||
|
@ -47,6 +48,8 @@ select {
|
|||
// Prevent the element from overflowing the container.
|
||||
max-width: 100%;
|
||||
|
||||
@include input-base();
|
||||
|
||||
@media (forced-colors: active) {
|
||||
appearance: auto;
|
||||
}
|
||||
|
@ -61,3 +64,8 @@ select[multiple] {
|
|||
padding: 0 theme('spacing.5');
|
||||
}
|
||||
}
|
||||
|
||||
.w-field--select {
|
||||
// Make sure comment buttons are as close as possible.
|
||||
display: inline-block;
|
||||
}
|
||||
|
|
|
@ -93,12 +93,6 @@ $switch-border-radius: math.div(($switch-height + $switch-border * 2), 2);
|
|||
outline: theme('colors.focus') solid $switch-outline;
|
||||
}
|
||||
|
||||
@supports not selector(:focus-visible) {
|
||||
[type='checkbox']:focus + &__toggle {
|
||||
outline: theme('colors.focus') solid $switch-outline;
|
||||
}
|
||||
}
|
||||
|
||||
[type='checkbox'] {
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
@use './input-base' as *;
|
||||
|
||||
.tagit {
|
||||
@include input-base();
|
||||
|
||||
|
|
|
@ -33,22 +33,22 @@ BEM: https://getbem.com/
|
|||
/* Legacy vendor styles. Do not add new styles here. */
|
||||
@use 'generic/normalize';
|
||||
@use 'vendor/jquery-ui-1.10.3.verdant';
|
||||
@use 'vendor/jquery.tagit' as tagit;
|
||||
@use 'vendor/jquery.Jcrop.min' as jcrop;
|
||||
@use 'vendor/jquery.tagit' as jquery-tagit;
|
||||
@use 'vendor/jquery.Jcrop.min' as jquery-jcrop;
|
||||
|
||||
/* SETTINGS
|
||||
These are variables, maps, and fonts.
|
||||
* No CSS should be produced by these files
|
||||
*/
|
||||
|
||||
@import 'settings';
|
||||
@use 'settings';
|
||||
|
||||
/* TOOLS
|
||||
These are functions and mixins.
|
||||
* No CSS should be produced by these files.
|
||||
*/
|
||||
|
||||
@import 'tools';
|
||||
@use 'tools';
|
||||
|
||||
/* GENERIC
|
||||
This is for resets and other rules that affect large collections of bare elements.
|
||||
|
@ -60,14 +60,9 @@ These are base styles for bare HTML elements.
|
|||
* Changes to them should be very rare.
|
||||
*/
|
||||
|
||||
// These inject Tailwind's base, component and utility styles and any styles registered by plugins of each layer.
|
||||
// Unused styles created within tailwinds layers won't be compiled into the compiled stylesheet
|
||||
// https://tailwindcss.com/docs/adding-custom-styles#using-css-and-layer
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@import 'elements/elements';
|
||||
@import 'elements/typography';
|
||||
@import 'elements/forms';
|
||||
@use 'elements/elements';
|
||||
@use 'elements/typography';
|
||||
@use 'elements/forms';
|
||||
|
||||
/* COMPONENTS
|
||||
These are classes for components.
|
||||
|
@ -76,81 +71,87 @@ These are classes for components.
|
|||
which is the preferred pattern over housing them in the scss folder.
|
||||
*/
|
||||
|
||||
@import '../src/components/Transition/Transition';
|
||||
@import '../src/components/LoadingSpinner/LoadingSpinner';
|
||||
@import '../src/components/PublicationStatus/PublicationStatus';
|
||||
@import '../src/components/ComboBox/ComboBox';
|
||||
@import '../src/components/PageExplorer/PageExplorer';
|
||||
@import '../src/components/CommentApp/main';
|
||||
@use '../src/components/Transition/Transition';
|
||||
@use '../src/components/LoadingSpinner/LoadingSpinner';
|
||||
@use '../src/components/PublicationStatus/PublicationStatus';
|
||||
@use '../src/components/ComboBox/ComboBox';
|
||||
@use '../src/components/ComboBoxPreview/ComboBoxPreview';
|
||||
@use '../src/components/PageExplorer/PageExplorer';
|
||||
@use '../src/components/CommentApp/main';
|
||||
|
||||
@import 'components/avatar';
|
||||
@import 'components/icons';
|
||||
@import 'components/forms/input-base';
|
||||
@import 'components/forms/input-text';
|
||||
@import 'components/forms/radio-checkbox';
|
||||
@import 'components/forms/select';
|
||||
@import 'components/forms/tagit';
|
||||
@import 'components/forms/radio-checkbox-multiple';
|
||||
@import 'components/forms/error-message';
|
||||
@import 'components/forms/required-mark';
|
||||
@import 'components/forms/help';
|
||||
@import 'components/forms/drop-zone';
|
||||
@import 'components/forms/daterange';
|
||||
@import 'components/forms/file';
|
||||
@import 'components/forms/publishing';
|
||||
@import 'components/forms/switch';
|
||||
@import 'components/forms/title';
|
||||
@import 'components/forms/field';
|
||||
@import 'components/forms/field-row';
|
||||
@import 'components/forms/field-comment-control';
|
||||
@import 'components/forms/field-textoutput';
|
||||
@import 'components/forms/form-width';
|
||||
@import 'components/forms/nested-panel';
|
||||
@import 'components/tabs';
|
||||
@import 'components/panel';
|
||||
@import 'components/dialog';
|
||||
@import 'components/dismissible';
|
||||
@import 'components/drilldown';
|
||||
@import 'components/dropdown';
|
||||
@import 'components/dropdown-button';
|
||||
@import 'components/help-block';
|
||||
@import 'components/button';
|
||||
@import 'components/keyboard-shortcuts';
|
||||
@import 'components/modals';
|
||||
@import 'components/chooser';
|
||||
@import 'components/tag';
|
||||
@import 'components/listing';
|
||||
@import 'components/filters';
|
||||
@import 'components/messages';
|
||||
@import 'components/messages.capability';
|
||||
@import 'components/messages.status';
|
||||
@import 'components/header';
|
||||
@import 'components/progressbar';
|
||||
@import 'components/summary';
|
||||
@import 'components/whats-new';
|
||||
@import 'components/grid.legacy';
|
||||
@import 'components/footer';
|
||||
@import 'components/loading-mask';
|
||||
@import 'components/human-readable-date';
|
||||
@import 'components/link.legacy';
|
||||
@import 'components/indicator';
|
||||
@import 'components/status-tag';
|
||||
@import 'components/skiplink';
|
||||
@import 'components/workflow-tasks';
|
||||
@import 'components/workflow-timeline';
|
||||
@import 'components/bulk_actions';
|
||||
@import 'components/preview-panel';
|
||||
@import 'components/preview-error';
|
||||
@import 'components/form-side';
|
||||
@import 'components/a11y-result';
|
||||
@import 'components/userbar';
|
||||
@import 'components/breadcrumbs';
|
||||
@import 'components/pill';
|
||||
@import 'components/ping';
|
||||
@import 'components/editing-sessions';
|
||||
@use 'components/avatar';
|
||||
@use 'components/icons';
|
||||
@use 'components/forms/input-base';
|
||||
@use 'components/forms/input-text';
|
||||
@use 'components/forms/radio-checkbox';
|
||||
@use 'components/forms/select';
|
||||
@use 'components/forms/tagit';
|
||||
@use 'components/forms/radio-checkbox-multiple';
|
||||
@use 'components/forms/error-message';
|
||||
@use 'components/forms/required-mark';
|
||||
@use 'components/forms/help';
|
||||
@use 'components/forms/drop-zone';
|
||||
@use 'components/forms/daterange';
|
||||
@use 'components/forms/file';
|
||||
@use 'components/forms/publishing';
|
||||
@use 'components/forms/switch';
|
||||
@use 'components/forms/title';
|
||||
@use 'components/forms/field';
|
||||
@use 'components/forms/field-row';
|
||||
@use 'components/forms/field-comment-control';
|
||||
@use 'components/forms/field-textoutput';
|
||||
@use 'components/forms/form-width';
|
||||
@use 'components/forms/nested-panel';
|
||||
@use 'components/tabs';
|
||||
@use 'components/panel';
|
||||
@use 'components/dialog';
|
||||
@use 'components/dismissible';
|
||||
@use 'components/drilldown';
|
||||
@use 'components/dropdown';
|
||||
@use 'components/dropdown-button';
|
||||
@use 'components/help-block';
|
||||
@use 'components/button';
|
||||
@use 'components/keyboard-shortcuts';
|
||||
@use 'components/modals';
|
||||
@use 'components/chooser';
|
||||
@use 'components/tag';
|
||||
@use 'components/listing';
|
||||
@use 'components/filters';
|
||||
@use 'components/messages';
|
||||
@use 'components/messages.capability' as messages-capability;
|
||||
@use 'components/messages.status' as messages-status;
|
||||
@use 'components/header';
|
||||
@use 'components/progressbar';
|
||||
@use 'components/summary';
|
||||
@use 'components/whats-new';
|
||||
@use 'components/grid.legacy';
|
||||
@use 'components/footer';
|
||||
@use 'components/loading-mask';
|
||||
@use 'components/human-readable-date';
|
||||
@use 'components/link.legacy';
|
||||
@use 'components/indicator';
|
||||
@use 'components/status-tag';
|
||||
@use 'components/skiplink';
|
||||
@use 'components/workflow-tasks';
|
||||
@use 'components/workflow-timeline';
|
||||
@use 'components/bulk_actions';
|
||||
@use 'components/preview-panel';
|
||||
@use 'components/preview-error';
|
||||
@use 'components/form-side';
|
||||
@use 'components/a11y-result';
|
||||
@use 'components/userbar';
|
||||
@use 'components/breadcrumbs';
|
||||
@use 'components/pill';
|
||||
@use 'components/ping';
|
||||
@use 'components/editing-sessions';
|
||||
|
||||
@import '../src/components/Sidebar/Sidebar';
|
||||
@import '../src/components/Minimap/Minimap';
|
||||
@use '../src/components/Sidebar/Sidebar';
|
||||
@use '../src/components/Sidebar/SidebarPanel';
|
||||
@use '../src/components/Sidebar/menu/MenuItem';
|
||||
@use '../src/components/Sidebar/menu/SubMenuItem';
|
||||
@use '../src/components/Sidebar/modules/MainMenu';
|
||||
@use '../src/components/Sidebar/modules/WagtailBranding';
|
||||
@use '../src/components/Minimap/Minimap';
|
||||
|
||||
/* OVERRIDES
|
||||
These are classes that provide overrides.
|
||||
|
@ -158,29 +159,28 @@ These are classes that provide overrides.
|
|||
*/
|
||||
|
||||
// VENDOR: overrides of vendor styles.
|
||||
@import 'overrides/vendor.datetimepicker';
|
||||
@import 'overrides/vendor.handsontable';
|
||||
@import 'overrides/vendor.tagit';
|
||||
@import 'overrides/vendor.tippy';
|
||||
@use 'overrides/vendor.datetimepicker' as vendor-datetimepicker;
|
||||
@use 'overrides/vendor.handsontable' as vendor-handsontable;
|
||||
@use 'overrides/vendor.tagit' as vendor-tagit;
|
||||
@use 'overrides/vendor.tippy' as vendor-tippy;
|
||||
|
||||
// UTILITIES: classes that do one simple thing.
|
||||
@import 'overrides/utilities.focus';
|
||||
@use 'overrides/utilities.focus' as utilities-focus;
|
||||
|
||||
// Legacy utilities
|
||||
@import 'overrides/utilities.legacy';
|
||||
|
||||
@use 'overrides/utilities.legacy' as utilities-legacy;
|
||||
// TAILWIND: This is at the bottom so it can take precedence over other css classes
|
||||
@tailwind utilities;
|
||||
@use 'overrides/utilities.tailwind' as utilities-tailwind;
|
||||
|
||||
/* Legacy layout-specific styles. Do not add new styles here. */
|
||||
|
||||
@import 'layouts/404';
|
||||
@import 'layouts/compare-revisions';
|
||||
@import 'layouts/login';
|
||||
@import 'layouts/account';
|
||||
@import 'layouts/workflow-progress';
|
||||
@import 'layouts/report';
|
||||
@import 'layouts/add-multiple';
|
||||
@import 'layouts/chooser-duplicate-upload';
|
||||
@import 'layouts/focal-point-chooser';
|
||||
@import 'layouts/redirects';
|
||||
@use 'layouts/404' as layout-404;
|
||||
@use 'layouts/compare-revisions';
|
||||
@use 'layouts/login';
|
||||
@use 'layouts/account';
|
||||
@use 'layouts/workflow-progress';
|
||||
@use 'layouts/report';
|
||||
@use 'layouts/add-multiple';
|
||||
@use 'layouts/chooser-duplicate-upload';
|
||||
@use 'layouts/focal-point-chooser';
|
||||
@use 'layouts/redirects';
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
// These inject Tailwind's base and component styles and any styles registered by plugins of each layer.
|
||||
// Unused styles created within tailwinds layers won't be compiled into the compiled stylesheet
|
||||
// https://tailwindcss.com/docs/adding-custom-styles#using-css-and-layer
|
||||
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
|
||||
*,
|
||||
::before,
|
||||
::after {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
@use 'sass:map';
|
||||
@use '../tools' as *;
|
||||
// Legacy form reset styles. Avoid adding any new styles here.
|
||||
form {
|
||||
// Historically, Wagtail forms rendered all fields as list items.
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
@use '../tools' as *;
|
||||
|
||||
.page404__bg {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
@use '../tools' as *;
|
||||
|
||||
$color-addition-dark: var(--color-addition-dark);
|
||||
$color-addition-light: var(--color-addition-light);
|
||||
$color-deletion-dark: var(--color-deletion-dark);
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
@use '../tools' as *;
|
||||
|
||||
.focal-point-chooser {
|
||||
position: relative;
|
||||
margin-bottom: 20px;
|
||||
|
|
|
@ -1,30 +1,19 @@
|
|||
@mixin login-fullscreen-background() {
|
||||
@at-root {
|
||||
:root {
|
||||
--w-login-fullscreen-background: radial-gradient(
|
||||
100% 300.28% at 100% 0%,
|
||||
theme('colors.primary.DEFAULT') 0%,
|
||||
theme('colors.primary.DEFAULT') 32.94%,
|
||||
theme('colors.primary.DEFAULT') 49.9%,
|
||||
theme('colors.primary.DEFAULT') 50.2%,
|
||||
theme('colors.secondary.DEFAULT') 100%
|
||||
);
|
||||
}
|
||||
}
|
||||
@use '../tools' as *;
|
||||
|
||||
// support older browsers that do not support radial gradient 'at' usage
|
||||
background: theme('colors.surface-menus');
|
||||
/* stylelint-disable-next-line declaration-block-no-duplicate-properties */
|
||||
background: var(
|
||||
--w-login-fullscreen-background,
|
||||
theme('colors.primary.DEFAULT')
|
||||
:root {
|
||||
--w-login-fullscreen-background: radial-gradient(
|
||||
100% 300.28% at 100% 0%,
|
||||
theme('colors.primary.DEFAULT') 0%,
|
||||
theme('colors.primary.DEFAULT') 32.94%,
|
||||
theme('colors.primary.DEFAULT') 49.9%,
|
||||
theme('colors.primary.DEFAULT') 50.2%,
|
||||
theme('colors.secondary.DEFAULT') 100%
|
||||
);
|
||||
}
|
||||
|
||||
.login {
|
||||
@include login-fullscreen-background;
|
||||
|
||||
color: theme('colors.text-label');
|
||||
background: var(--w-login-fullscreen-background);
|
||||
|
||||
.wrapper {
|
||||
align-items: center;
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
@use '../tools' as *;
|
||||
|
||||
.report {
|
||||
@include nice-margin();
|
||||
display: grid;
|
||||
grid-column-gap: theme('spacing.12');
|
||||
|
||||
@include nice-margin();
|
||||
|
||||
&__results {
|
||||
&--text {
|
||||
margin: 0 theme('spacing.[1.5]') theme('spacing.[1.5]') 0;
|
||||
|
|
|
@ -1,16 +1,9 @@
|
|||
@use '../settings' as *;
|
||||
|
||||
// stylelint-disable declaration-no-important
|
||||
// Set global focus outline styles so they are consistent across the UI,
|
||||
// without individual components having to explicitly define focus styles.
|
||||
// Using !important because we want to enforce only one style is used across the UI.
|
||||
// Remove :focus selectors once we stop supporting Safari 15.4.
|
||||
*:focus {
|
||||
outline: $focus-outline-width solid theme('colors.focus') !important;
|
||||
}
|
||||
|
||||
*:focus:not(:focus-visible) {
|
||||
outline: none !important;
|
||||
}
|
||||
|
||||
*:focus-visible {
|
||||
outline: $focus-outline-width solid theme('colors.focus') !important;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
@use '../tools' as *;
|
||||
@use '../settings' as *;
|
||||
|
||||
.nice-padding {
|
||||
padding-inline-start: $mobile-nice-padding;
|
||||
padding-inline-end: $mobile-nice-padding;
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
@tailwind utilities;
|
|
@ -1,5 +1,6 @@
|
|||
// stylelint-disable selector-max-combinators, max-nesting-depth
|
||||
@use 'sass:map';
|
||||
@use '../settings' as *;
|
||||
|
||||
.xdsoft_datetimepicker {
|
||||
box-shadow: 0 5px 10px -5px theme('colors.black-35');
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
@use 'sass:map';
|
||||
@use '../settings' as *;
|
||||
|
||||
// taggit tagging
|
||||
.tagit {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// stylelint-disable selector-attribute-name-disallowed-list
|
||||
@import '../../../node_modules/tippy.js/dist/tippy';
|
||||
@use '../../../node_modules/tippy.js/dist/tippy';
|
||||
|
||||
.tippy-box {
|
||||
// Special font size 12px for tooltips
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
@use 'sass:list';
|
||||
@use 'sass:map';
|
||||
@use '../settings' as *;
|
||||
// Based upon the fine work and thoughts from Bootstrap v4.
|
||||
// Copyright 2011-2018 The Bootstrap Authors
|
||||
// Copyright 2011-2018 Twitter, Inc.
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
@use 'functions.breakpoints' as *;
|
||||
|
||||
// Based upon the fine work and thoughts from Bootstrap v4.
|
||||
// Copyright 2011-2018 The Bootstrap Authors
|
||||
// Copyright 2011-2018 Twitter, Inc.
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
// Please note that the mixins partial shouldn't include any classes. This is so
|
||||
// it can be included in any file without accidentally producing output
|
||||
|
||||
@use '../settings' as *;
|
||||
|
||||
// Turns on font-smoothing when used. Use sparingly.
|
||||
@mixin font-smoothing {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
|
@ -167,3 +169,7 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
@mixin focus-outline {
|
||||
outline: $focus-outline-width solid theme('colors.focus');
|
||||
}
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
@use 'sass:math';
|
||||
@use '../settings' as *;
|
||||
@use '../tools/mixins.breakpoints' as *;
|
||||
@use '../tools/mixins.general' as *;
|
||||
|
||||
// grid settings
|
||||
$grid-columns: 12;
|
||||
|
|
|
@ -14,8 +14,11 @@ const checkStatus = (response) => {
|
|||
|
||||
const parseJSON = (response) => response.json();
|
||||
|
||||
// Response timeout cancelling the promise (not the request).
|
||||
// See https://github.com/github/fetch/issues/175#issuecomment-216791333.
|
||||
/**
|
||||
* Response timeout cancelling the promise (not the request).
|
||||
*
|
||||
* @see https://github.com/github/fetch/issues/175#issuecomment-216791333.
|
||||
*/
|
||||
const timeout = (ms, promise) => {
|
||||
const race = new Promise((resolve, reject) => {
|
||||
const timeoutId = setTimeout(() => {
|
||||
|
@ -38,7 +41,7 @@ const timeout = (ms, promise) => {
|
|||
};
|
||||
|
||||
/**
|
||||
* Wrapper around fetch with sane defaults for behaviour in the face of
|
||||
* Wrapper around fetch with sane defaults for behavior in the face of
|
||||
* errors.
|
||||
*/
|
||||
const request = (method, url) => {
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
/* global DocumentChooserModal */
|
||||
|
||||
import { Chooser, ChooserFactory } from '.';
|
||||
|
||||
export class DocumentChooser extends Chooser {
|
||||
// eslint-disable-next-line no-undef
|
||||
chooserModalClass = DocumentChooserModal;
|
||||
}
|
||||
window.DocumentChooser = DocumentChooser;
|
||||
|
||||
export class DocumentChooserFactory extends ChooserFactory {
|
||||
widgetClass = DocumentChooser;
|
||||
// eslint-disable-next-line no-undef
|
||||
chooserModalClass = DocumentChooserModal;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
/* global ImageChooserModal */
|
||||
|
||||
import { Chooser, ChooserFactory } from '.';
|
||||
|
||||
export class ImageChooser extends Chooser {
|
||||
// eslint-disable-next-line no-undef
|
||||
chooserModalClass = ImageChooserModal;
|
||||
|
||||
initHTMLElements(id) {
|
||||
|
@ -11,12 +12,21 @@ export class ImageChooser extends Chooser {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs the initial state of the chooser from the rendered (static) HTML.
|
||||
* The state is either null (no image chosen) or an object containing the image details.
|
||||
*
|
||||
* @returns {Object|null} The initial state of the chooser. If an image is chosen,
|
||||
* the state object contains the following properties:
|
||||
* - id: {number} The ID of the chosen image.
|
||||
* - edit_url: {string} The URL to edit the chosen image.
|
||||
* - title: {string} The title of the chosen image.
|
||||
* - preview: {Object} An object containing the preview details of the chosen image:
|
||||
* - url: {string} The URL of the preview image.
|
||||
* - width: {string} The width of the preview image.
|
||||
* - height: {string} The height of the preview image.
|
||||
*/
|
||||
getStateFromHTML() {
|
||||
/*
|
||||
Construct initial state of the chooser from the rendered (static) HTML.
|
||||
State is either null (= no image chosen) or a dict of id, edit_url, title
|
||||
and preview (= a dict of url, width, height).
|
||||
*/
|
||||
const state = super.getStateFromHTML();
|
||||
if (state) {
|
||||
state.preview = {
|
||||
|
@ -24,6 +34,9 @@ export class ImageChooser extends Chooser {
|
|||
width: this.previewImage.getAttribute('width'),
|
||||
height: this.previewImage.getAttribute('height'),
|
||||
};
|
||||
state.default_alt_text = this.previewImage.getAttribute(
|
||||
'data-default-alt-text',
|
||||
);
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
@ -32,11 +45,14 @@ export class ImageChooser extends Chooser {
|
|||
super.renderState(newState);
|
||||
this.previewImage.setAttribute('src', newState.preview.url);
|
||||
this.previewImage.setAttribute('width', newState.preview.width);
|
||||
this.previewImage.setAttribute(
|
||||
'data-default-alt-text',
|
||||
newState.default_alt_text,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export class ImageChooserFactory extends ChooserFactory {
|
||||
widgetClass = ImageChooser;
|
||||
// eslint-disable-next-line no-undef
|
||||
chooserModalClass = ImageChooserModal;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
/* global PageChooserModal */
|
||||
|
||||
import { Chooser, ChooserFactory } from '.';
|
||||
|
||||
export class PageChooser extends Chooser {
|
||||
// eslint-disable-next-line no-undef
|
||||
chooserModalClass = PageChooserModal;
|
||||
|
||||
titleStateKey = 'adminTitle';
|
||||
|
@ -44,7 +45,6 @@ export class PageChooser extends Chooser {
|
|||
|
||||
export class PageChooserFactory extends ChooserFactory {
|
||||
widgetClass = PageChooser;
|
||||
// eslint-disable-next-line no-undef
|
||||
chooserModalClass = PageChooserModal;
|
||||
|
||||
getModalOptions() {
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
import EventEmitter from 'events';
|
||||
import { ChooserModal } from '../../includes/chooserModal';
|
||||
|
||||
export class Chooser {
|
||||
export class Chooser extends EventEmitter {
|
||||
chooserModalClass = ChooserModal;
|
||||
titleStateKey = 'title'; // key used in the 'state' dictionary to hold the human-readable title
|
||||
editUrlStateKey = 'edit_url'; // key used in the 'state' dictionary to hold the URL of the edit page
|
||||
|
||||
constructor(id, opts = {}) {
|
||||
super();
|
||||
this.opts = opts;
|
||||
this.initHTMLElements(id);
|
||||
this.state = this.getStateFromHTML();
|
||||
|
@ -83,6 +85,7 @@ export class Chooser {
|
|||
|
||||
setStateFromModalData(data) {
|
||||
this.setState(data);
|
||||
this.emit('chosen', data);
|
||||
}
|
||||
|
||||
clear() {
|
||||
|
@ -210,8 +213,10 @@ export class ChooserFactory {
|
|||
this.modal.open(options, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* retrieve the widget object corresponding to the given HTML ID
|
||||
*/
|
||||
getById(id) {
|
||||
/* retrieve the widget object corresponding to the given HTML ID */
|
||||
return document.getElementById(`${id}-chooser`).widget;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,24 +1,70 @@
|
|||
@use '../../../scss/tools' as *;
|
||||
|
||||
// Ensure consistent spacing across the whole component.
|
||||
// With the scrolling and show/hide of the field, correct spacing is critical.
|
||||
$spacing: theme('spacing.[2.5]');
|
||||
$spacing-sm: theme('spacing.5');
|
||||
$spacing-sm: theme('spacing.4');
|
||||
$width: clamp(300px, 75vw, 1000px);
|
||||
|
||||
.w-combobox {
|
||||
width: min(400px, 80vw);
|
||||
@include dark-theme() {
|
||||
background-color: theme('colors.surface-tooltip');
|
||||
}
|
||||
.w-combobox-container {
|
||||
background: theme('colors.surface-page');
|
||||
color: theme('colors.text-context');
|
||||
border-radius: theme('borderRadius.DEFAULT');
|
||||
font-size: theme('fontSize.18');
|
||||
box-shadow: theme('boxShadow.md');
|
||||
outline: 10px solid transparent;
|
||||
|
||||
// Use a single column grid on smaller screens,
|
||||
// and two columns on larger screens.
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
// Case 1: base case
|
||||
// Use max-content width to minimize shifting due to content wrapping,
|
||||
// constraining width to 75% of viewport for devices above 400px width.
|
||||
width: max-content;
|
||||
max-width: max(300px, 75vw);
|
||||
|
||||
@include media-breakpoint-up(md) {
|
||||
grid-template-columns: min(400px, 80vw) 1fr;
|
||||
}
|
||||
@include media-breakpoint-up(lg) {
|
||||
grid-template-columns: min(512px, 80vw) 1fr;
|
||||
}
|
||||
|
||||
// Case 2: there's a previewable block, but the preview may or may not be active
|
||||
// On smaller screens, the preview will be shown below. We don't want the
|
||||
// combobox to change width when the preview is shown or hidden (e.g. due to
|
||||
// a long description), so set a fixed width. It's OK that this will take up
|
||||
// more than the necessary width for the combobox, as we know it's not going
|
||||
// to be wider than 75% of the small screen anyway.
|
||||
&:has(.w-combobox__option-preview) {
|
||||
width: $width;
|
||||
|
||||
@include media-breakpoint-up(md) {
|
||||
// On medium-up screens, the preview will be shown to the right. Revert
|
||||
// the width back to max-content so it doesn't take up the whole `$width`
|
||||
// when the preview is not active.
|
||||
width: max-content;
|
||||
}
|
||||
}
|
||||
|
||||
// Case 3: the preview is currently active
|
||||
&:has(.w-combobox-preview) {
|
||||
@include media-breakpoint-up(md) {
|
||||
// On larger screens, use the fixed `$width` so the width doesn't change
|
||||
// for different blocks, which may have different description lengths.
|
||||
width: $width;
|
||||
}
|
||||
}
|
||||
|
||||
@include dark-theme() {
|
||||
background-color: theme('colors.surface-tooltip');
|
||||
}
|
||||
}
|
||||
|
||||
.w-combobox__field {
|
||||
padding: $spacing;
|
||||
padding-bottom: 0;
|
||||
font-size: theme('fontSize.18');
|
||||
|
||||
@include media-breakpoint-up(sm) {
|
||||
padding: $spacing-sm;
|
||||
|
@ -43,12 +89,13 @@ $spacing-sm: theme('spacing.5');
|
|||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
grid-auto-flow: column;
|
||||
gap: theme('spacing.[0.5]');
|
||||
gap: theme('spacing.1');
|
||||
padding: $spacing;
|
||||
padding-top: 0;
|
||||
|
||||
@include media-breakpoint-up(sm) {
|
||||
width: 400px;
|
||||
width: 100%;
|
||||
column-gap: theme('spacing.5');
|
||||
padding: $spacing-sm;
|
||||
padding-top: 0;
|
||||
}
|
||||
|
@ -70,21 +117,32 @@ $spacing-sm: theme('spacing.5');
|
|||
}
|
||||
}
|
||||
|
||||
.w-combobox__option {
|
||||
.w-combobox__option-row {
|
||||
display: grid;
|
||||
grid-template-columns: theme('spacing.8') 1fr;
|
||||
align-items: center;
|
||||
padding: theme('spacing.2');
|
||||
border: 1px solid transparent;
|
||||
font-size: 0.875rem;
|
||||
line-height: theme('lineHeight.tight');
|
||||
border-radius: theme('borderRadius.sm');
|
||||
grid-template-columns: 1fr theme('spacing.6');
|
||||
}
|
||||
|
||||
&[aria-selected='true'] {
|
||||
border-color: theme('colors.border-button-outline-default');
|
||||
.w-combobox__option-preview {
|
||||
@include show-focus-outline-inside();
|
||||
color: theme('colors.icon-secondary');
|
||||
background: none;
|
||||
border: 1px solid transparent;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
|
||||
@include more-contrast-interactive();
|
||||
|
||||
.icon {
|
||||
width: theme('spacing.3');
|
||||
height: theme('spacing.3');
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: theme('colors.icon-secondary-hover');
|
||||
}
|
||||
|
||||
&[aria-expanded='true'] {
|
||||
color: theme('colors.text-link-default');
|
||||
background: transparent;
|
||||
cursor: pointer;
|
||||
|
||||
@media (forced-colors: active) {
|
||||
background: Highlight;
|
||||
|
@ -93,14 +151,37 @@ $spacing-sm: theme('spacing.5');
|
|||
}
|
||||
}
|
||||
|
||||
.w-combobox__option--col1 {
|
||||
.w-combobox__option-row--col1 {
|
||||
grid-column: 1 / span 1;
|
||||
}
|
||||
|
||||
.w-combobox__option--col2 {
|
||||
.w-combobox__option-row--col2 {
|
||||
grid-column: 2 / span 1;
|
||||
}
|
||||
|
||||
.w-combobox__option {
|
||||
display: grid;
|
||||
grid-template-columns: theme('spacing.8') 1fr;
|
||||
align-items: center;
|
||||
padding: theme('spacing.[2.5]');
|
||||
border: 1px dotted theme('colors.border-button-small-outline-default');
|
||||
font-size: 0.875rem;
|
||||
line-height: theme('lineHeight.tight');
|
||||
border-radius: theme('borderRadius.sm');
|
||||
cursor: pointer;
|
||||
|
||||
&[aria-selected='true'] {
|
||||
border-color: theme('colors.border-button-outline-default');
|
||||
color: theme('colors.text-link-default');
|
||||
background: transparent;
|
||||
|
||||
@media (forced-colors: active) {
|
||||
background: Highlight;
|
||||
color: HighlightText;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.w-combobox__option-icon {
|
||||
color: theme('colors.icon-secondary');
|
||||
height: theme('spacing.4');
|
||||
|
|
|
@ -40,12 +40,13 @@ describe('ComboBox', () => {
|
|||
{
|
||||
type: 'paragraph',
|
||||
description: 'Paragraph',
|
||||
icon: <span className="custom-icon">P</span>,
|
||||
icon: <span className="my-icon">P</span>,
|
||||
},
|
||||
{
|
||||
type: 'heading-one',
|
||||
label: 'H1',
|
||||
description: 'Heading 1',
|
||||
icon: ['M 83.625 ', 'L 232.535156 '],
|
||||
},
|
||||
{
|
||||
type: 'heading-two',
|
||||
|
@ -70,6 +71,10 @@ describe('ComboBox', () => {
|
|||
wrapper = shallow(<ComboBox {...testProps} items={items} />);
|
||||
});
|
||||
|
||||
it('matches the snapshot', () => {
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('shows items', () => {
|
||||
const options = wrapper.find('.w-combobox__option-text');
|
||||
expect(options).toHaveLength(
|
||||
|
@ -82,8 +87,24 @@ describe('ComboBox', () => {
|
|||
expect(wrapper.find(Icon).at(0).prop('name')).toBe('blockquote');
|
||||
});
|
||||
|
||||
it('supports custom icons', () => {
|
||||
expect(wrapper.find('.custom-icon').text()).toBe('P');
|
||||
it('supports custom icons (as provided React component)', () => {
|
||||
const paragraphOption = wrapper.findWhere(
|
||||
(el) => el.key() === 'paragraph',
|
||||
);
|
||||
const icon = paragraphOption.find('.w-combobox__option-icon').render();
|
||||
|
||||
expect(icon.find('.my-icon')).toHaveLength(1);
|
||||
expect(icon.text()).toBe('P');
|
||||
});
|
||||
|
||||
it('supports custom icons (as provided path)', () => {
|
||||
const paragraphOption = wrapper.findWhere(
|
||||
(el) => el.key() === 'heading-one',
|
||||
);
|
||||
const icon = paragraphOption.find('.w-combobox__option-icon').render();
|
||||
|
||||
expect(icon.find('svg').hasClass('icon-custom')).toBe(true);
|
||||
expect(icon.find('.icon-custom').html()).toContain('M 83.625');
|
||||
});
|
||||
|
||||
it('supports label as icon', () => {
|
||||
|
@ -92,8 +113,8 @@ describe('ComboBox', () => {
|
|||
|
||||
it('combines two categories into one, with two columns', () => {
|
||||
expect(wrapper.find('.w-combobox__optgroup-label')).toHaveLength(1);
|
||||
expect(wrapper.find('.w-combobox__option--col1')).toHaveLength(3);
|
||||
expect(wrapper.find('.w-combobox__option--col2')).toHaveLength(2);
|
||||
expect(wrapper.find('.w-combobox__option-row--col1')).toHaveLength(3);
|
||||
expect(wrapper.find('.w-combobox__option-row--col2')).toHaveLength(2);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -2,6 +2,7 @@ import React, { useEffect, useState } from 'react';
|
|||
import { useCombobox, UseComboboxStateChange } from 'downshift';
|
||||
|
||||
import { gettext } from '../../utils/gettext';
|
||||
import ComboBoxPreview from '../ComboBoxPreview/ComboBoxPreview';
|
||||
import Icon from '../Icon/Icon';
|
||||
|
||||
import findMatches from './findMatches';
|
||||
|
@ -9,6 +10,7 @@ import findMatches from './findMatches';
|
|||
export const comboBoxTriggerLabel = gettext('Insert a block');
|
||||
export const comboBoxLabel = gettext('Search options…');
|
||||
export const comboBoxNoResults = gettext('No results');
|
||||
const comboBoxPreviewLabel = gettext('Preview');
|
||||
|
||||
export interface ComboBoxCategory<ItemType> {
|
||||
type: string;
|
||||
|
@ -21,6 +23,8 @@ export interface ComboBoxItem {
|
|||
label?: string | null;
|
||||
description?: string | null;
|
||||
icon?: string | JSX.Element | null;
|
||||
blockDefId?: string;
|
||||
isPreviewable?: boolean;
|
||||
category?: string;
|
||||
render?: (props: { option: ComboBoxItem }) => JSX.Element | string;
|
||||
}
|
||||
|
@ -64,6 +68,7 @@ export default function ComboBox<ComboBoxOption extends ComboBoxItem>({
|
|||
(category) => category.items || [],
|
||||
);
|
||||
const [inputItems, setInputItems] = useState<ComboBoxOption[]>(flatItems);
|
||||
const [previewedIndex, setPreviewedIndex] = useState<number>(-1);
|
||||
// Re-create the categories so the two-column layout flows as expected.
|
||||
const categories = items.reduce<ComboBoxCategory<ComboBoxOption>[]>(
|
||||
(cats, cat, index) => {
|
||||
|
@ -114,8 +119,10 @@ export default function ComboBox<ComboBoxOption extends ComboBoxItem>({
|
|||
}
|
||||
},
|
||||
|
||||
// For not re-setting and not removing focus from combobox when pressing `Alt+Tab`
|
||||
// to switch windows.
|
||||
/**
|
||||
* For not re-setting and not removing focus from combobox when pressing `Alt+Tab`
|
||||
* to switch windows.
|
||||
*/
|
||||
stateReducer: (state, actionAndChanges) => {
|
||||
const { type, changes } = actionAndChanges;
|
||||
switch (type) {
|
||||
|
@ -132,6 +139,9 @@ export default function ComboBox<ComboBoxOption extends ComboBoxItem>({
|
|||
},
|
||||
|
||||
onInputValueChange: (changes) => {
|
||||
// Hide any preview when the user types or clears the search input.
|
||||
setPreviewedIndex(-1);
|
||||
|
||||
const { inputValue: val } = changes;
|
||||
if (!val) {
|
||||
setInputItems(flatItems);
|
||||
|
@ -168,86 +178,129 @@ export default function ComboBox<ComboBoxOption extends ComboBoxItem>({
|
|||
}
|
||||
}, [inputValue]);
|
||||
|
||||
const previewedBlock =
|
||||
previewedIndex >= 0 ? inputItems[previewedIndex] : null;
|
||||
|
||||
return (
|
||||
<div className="w-combobox">
|
||||
{/* downshift does the label-field association itself. */}
|
||||
{/* eslint-disable-next-line jsx-a11y/label-has-associated-control */}
|
||||
<label {...getLabelProps()} className="w-sr-only">
|
||||
{label}
|
||||
</label>
|
||||
<div className="w-combobox__field">
|
||||
<input
|
||||
{...getInputProps()}
|
||||
type="text"
|
||||
// Prevent the field from receiving focus if it’s not visible.
|
||||
disabled={inlineCombobox}
|
||||
placeholder={placeholder}
|
||||
/>
|
||||
</div>
|
||||
{noResults ? (
|
||||
<div className="w-combobox__status">{noResultsText}</div>
|
||||
) : null}
|
||||
<div {...getMenuProps()} className="w-combobox__menu">
|
||||
{categories.map((category) => {
|
||||
const categoryItems = (category.items || []).filter((item) =>
|
||||
inputItems.find((i) => i.type === item.type),
|
||||
);
|
||||
const itemColumns = Math.ceil(categoryItems.length / 2);
|
||||
<div className="w-combobox-container">
|
||||
<div className="w-combobox">
|
||||
{/* downshift does the label-field association itself. */}
|
||||
{/* eslint-disable-next-line jsx-a11y/label-has-associated-control */}
|
||||
<label {...getLabelProps()} className="w-sr-only">
|
||||
{label}
|
||||
</label>
|
||||
<div className="w-combobox__field">
|
||||
<input
|
||||
{...getInputProps()}
|
||||
type="text"
|
||||
// Prevent the field from receiving focus if it’s not visible.
|
||||
disabled={inlineCombobox}
|
||||
placeholder={placeholder}
|
||||
/>
|
||||
</div>
|
||||
{noResults ? (
|
||||
<div className="w-combobox__status">{noResultsText}</div>
|
||||
) : null}
|
||||
<div {...getMenuProps()} className="w-combobox__menu">
|
||||
{categories.map((category) => {
|
||||
const categoryItems = (category.items || []).filter((item) =>
|
||||
inputItems.find((i) => i.type === item.type),
|
||||
);
|
||||
const itemColumns = Math.ceil(categoryItems.length / 2);
|
||||
|
||||
if (categoryItems.length === 0) {
|
||||
return null;
|
||||
}
|
||||
if (categoryItems.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="w-combobox__optgroup" key={category.type}>
|
||||
{category.label ? (
|
||||
<div className="w-combobox__optgroup-label">
|
||||
{category.label}
|
||||
</div>
|
||||
) : null}
|
||||
{categoryItems.map((item, index) => {
|
||||
const itemLabel = getItemLabel(item.type, item);
|
||||
const description = getItemDescription(item);
|
||||
const itemIndex = inputItems.findIndex(
|
||||
(i) => i.type === item.type,
|
||||
);
|
||||
const itemColumn = index + 1 <= itemColumns ? 1 : 2;
|
||||
const hasIcon =
|
||||
typeof item.icon !== 'undefined' && item.icon !== null;
|
||||
let icon: JSX.Element | null | undefined = null;
|
||||
|
||||
if (hasIcon) {
|
||||
icon =
|
||||
typeof item.icon === 'string' ? (
|
||||
<Icon name={item.icon} />
|
||||
) : (
|
||||
item.icon
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
key={item.type}
|
||||
{...getItemProps({ item, index: itemIndex })}
|
||||
className={`w-combobox__option w-combobox__option--col${itemColumn}`}
|
||||
>
|
||||
<div className="w-combobox__option-icon">
|
||||
{icon}
|
||||
{/* Support for rich text options using text as an icon (for example "B" for bold). */}
|
||||
{itemLabel && !hasIcon ? <span>{itemLabel}</span> : null}
|
||||
</div>
|
||||
<div className="w-combobox__option-text">
|
||||
{item.render
|
||||
? item.render({ option: item })
|
||||
: description}
|
||||
</div>
|
||||
return (
|
||||
<div className="w-combobox__optgroup" key={category.type}>
|
||||
{category.label ? (
|
||||
<div className="w-combobox__optgroup-label">
|
||||
{category.label}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
) : null}
|
||||
{categoryItems.map((item, index) => {
|
||||
const itemLabel = getItemLabel(item.type, item);
|
||||
const description = getItemDescription(item);
|
||||
const itemIndex = inputItems.findIndex(
|
||||
(i) => i.type === item.type,
|
||||
);
|
||||
const itemColumn = index + 1 <= itemColumns ? 1 : 2;
|
||||
const hasIcon =
|
||||
typeof item.icon !== 'undefined' && item.icon !== null;
|
||||
let icon: JSX.Element | null | undefined = null;
|
||||
|
||||
if (hasIcon) {
|
||||
if (Array.isArray(item.icon)) {
|
||||
icon = (
|
||||
<Icon name="custom" viewBox="0 0 1024 1024">
|
||||
{item.icon.map((pathData: string) => (
|
||||
<path key={pathData} d={pathData} />
|
||||
))}
|
||||
</Icon>
|
||||
);
|
||||
} else {
|
||||
icon =
|
||||
typeof item.icon === 'string' ? (
|
||||
<Icon name={item.icon} />
|
||||
) : (
|
||||
item.icon
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
key={item.type}
|
||||
className={`w-combobox__option-row w-combobox__option-row--col${itemColumn}`}
|
||||
>
|
||||
<div
|
||||
{...getItemProps({ item, index: itemIndex })}
|
||||
className="w-combobox__option"
|
||||
>
|
||||
<div className="w-combobox__option-icon">
|
||||
{icon}
|
||||
{/* Support for rich text options using text as an icon (for example "B" for bold). */}
|
||||
{itemLabel && !hasIcon ? (
|
||||
<span>{itemLabel}</span>
|
||||
) : null}
|
||||
</div>
|
||||
<div className="w-combobox__option-text">
|
||||
{item.render
|
||||
? item.render({ option: item })
|
||||
: description}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{item.isPreviewable ? (
|
||||
<button
|
||||
className="w-combobox__option-preview"
|
||||
aria-label={comboBoxPreviewLabel}
|
||||
aria-expanded={previewedIndex === itemIndex}
|
||||
type="button"
|
||||
onClick={() =>
|
||||
setPreviewedIndex(
|
||||
previewedIndex === itemIndex ? -1 : itemIndex,
|
||||
)
|
||||
}
|
||||
>
|
||||
<Icon name="view" />
|
||||
</button>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
{previewedBlock?.isPreviewable ? (
|
||||
<ComboBoxPreview
|
||||
item={previewedBlock}
|
||||
previewLabel={comboBoxPreviewLabel}
|
||||
/>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,215 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`ComboBox rendering matches the snapshot 1`] = `
|
||||
<div
|
||||
className="w-combobox-container"
|
||||
>
|
||||
<div
|
||||
className="w-combobox"
|
||||
>
|
||||
<label
|
||||
className="w-sr-only"
|
||||
htmlFor="downshift-1-input"
|
||||
id="downshift-1-label"
|
||||
>
|
||||
Search options…
|
||||
</label>
|
||||
<div
|
||||
className="w-combobox__field"
|
||||
>
|
||||
<input
|
||||
aria-activedescendant=""
|
||||
aria-autocomplete="list"
|
||||
aria-controls="downshift-1-menu"
|
||||
aria-expanded={false}
|
||||
aria-labelledby="downshift-1-label"
|
||||
autoComplete="off"
|
||||
disabled={false}
|
||||
id="downshift-1-input"
|
||||
onBlur={[Function]}
|
||||
onChange={[Function]}
|
||||
onClick={[Function]}
|
||||
onKeyDown={[Function]}
|
||||
placeholder="Search options…"
|
||||
role="combobox"
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
aria-labelledby="downshift-1-label"
|
||||
className="w-combobox__menu"
|
||||
id="downshift-1-menu"
|
||||
onMouseLeave={[Function]}
|
||||
role="listbox"
|
||||
>
|
||||
<div
|
||||
className="w-combobox__optgroup"
|
||||
key="blockTypes"
|
||||
>
|
||||
<div
|
||||
className="w-combobox__optgroup-label"
|
||||
>
|
||||
Blocks
|
||||
</div>
|
||||
<div
|
||||
className="w-combobox__option-row w-combobox__option-row--col1"
|
||||
key="blockquote"
|
||||
>
|
||||
<div
|
||||
aria-disabled={false}
|
||||
aria-selected={false}
|
||||
className="w-combobox__option"
|
||||
id="downshift-1-item-0"
|
||||
onClick={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseMove={[Function]}
|
||||
role="option"
|
||||
>
|
||||
<div
|
||||
className="w-combobox__option-icon"
|
||||
>
|
||||
<Icon
|
||||
name="blockquote"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
className="w-combobox__option-text"
|
||||
>
|
||||
Blockquote
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="w-combobox__option-row w-combobox__option-row--col1"
|
||||
key="paragraph"
|
||||
>
|
||||
<div
|
||||
aria-disabled={false}
|
||||
aria-selected={false}
|
||||
className="w-combobox__option"
|
||||
id="downshift-1-item-1"
|
||||
onClick={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseMove={[Function]}
|
||||
role="option"
|
||||
>
|
||||
<div
|
||||
className="w-combobox__option-icon"
|
||||
>
|
||||
<span
|
||||
className="my-icon"
|
||||
>
|
||||
P
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
className="w-combobox__option-text"
|
||||
>
|
||||
Paragraph
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="w-combobox__option-row w-combobox__option-row--col1"
|
||||
key="heading-one"
|
||||
>
|
||||
<div
|
||||
aria-disabled={false}
|
||||
aria-selected={false}
|
||||
className="w-combobox__option"
|
||||
id="downshift-1-item-2"
|
||||
onClick={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseMove={[Function]}
|
||||
role="option"
|
||||
>
|
||||
<div
|
||||
className="w-combobox__option-icon"
|
||||
>
|
||||
<Icon
|
||||
name="custom"
|
||||
viewBox="0 0 1024 1024"
|
||||
>
|
||||
<path
|
||||
d="M 83.625 "
|
||||
key="M 83.625 "
|
||||
/>
|
||||
<path
|
||||
d="L 232.535156 "
|
||||
key="L 232.535156 "
|
||||
/>
|
||||
</Icon>
|
||||
</div>
|
||||
<div
|
||||
className="w-combobox__option-text"
|
||||
>
|
||||
Heading 1
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="w-combobox__option-row w-combobox__option-row--col2"
|
||||
key="heading-two"
|
||||
>
|
||||
<div
|
||||
aria-disabled={false}
|
||||
aria-selected={false}
|
||||
className="w-combobox__option"
|
||||
id="downshift-1-item-3"
|
||||
onClick={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseMove={[Function]}
|
||||
role="option"
|
||||
>
|
||||
<div
|
||||
className="w-combobox__option-icon"
|
||||
>
|
||||
<span>
|
||||
H2
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
className="w-combobox__option-text"
|
||||
>
|
||||
<span
|
||||
className="custom-text"
|
||||
>
|
||||
H2
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="w-combobox__option-row w-combobox__option-row--col2"
|
||||
key="link"
|
||||
>
|
||||
<div
|
||||
aria-disabled={false}
|
||||
aria-selected={false}
|
||||
className="w-combobox__option"
|
||||
id="downshift-1-item-4"
|
||||
onClick={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseMove={[Function]}
|
||||
role="option"
|
||||
>
|
||||
<div
|
||||
className="w-combobox__option-icon"
|
||||
>
|
||||
<span>
|
||||
🔗
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
className="w-combobox__option-text"
|
||||
>
|
||||
Link
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
|
@ -0,0 +1,59 @@
|
|||
@use '../../../scss/tools' as *;
|
||||
|
||||
.w-combobox-preview {
|
||||
padding: theme('spacing.5');
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: theme('spacing.5');
|
||||
// Set a min-height to ensure it's big enough to be useful
|
||||
min-height: 400px;
|
||||
background-color: theme('colors.surface-header');
|
||||
border-block-start: 1px solid theme('colors.border-furniture');
|
||||
border-end-end-radius: inherit;
|
||||
border-end-start-radius: inherit;
|
||||
@include media-breakpoint-up(md) {
|
||||
border-block-start: 0;
|
||||
border-start-end-radius: inherit;
|
||||
border-end-start-radius: 0;
|
||||
border-inline-start: 1px solid theme('colors.border-furniture');
|
||||
}
|
||||
}
|
||||
|
||||
.w-combobox-preview__iframe {
|
||||
// Take up remaining space
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
border: 1px solid theme('colors.border-furniture');
|
||||
border-radius: theme('borderRadius.sm');
|
||||
|
||||
// Ensure iframe is always opaque
|
||||
color-scheme: normal;
|
||||
background-color: Canvas;
|
||||
|
||||
@include more-contrast() {
|
||||
border-color: theme('colors.border-furniture-more-contrast');
|
||||
}
|
||||
}
|
||||
|
||||
.w-combobox-preview__details {
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
// Use 65:35 ratio between the iframe and the details, but allow the details
|
||||
// to grow to a minimum of 100px in case the container is very small
|
||||
// (i.e. when there are only a few blocks)
|
||||
min-height: max(35%, 100px);
|
||||
}
|
||||
|
||||
.w-combobox-preview__label {
|
||||
@apply w-label-1;
|
||||
}
|
||||
|
||||
.w-combobox-preview__description {
|
||||
@apply w-help-text;
|
||||
margin-top: theme('spacing.3');
|
||||
margin-bottom: 0;
|
||||
overflow: auto;
|
||||
min-height: 0;
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
import React from 'react';
|
||||
import { WAGTAIL_CONFIG } from '../../config/wagtailConfig';
|
||||
|
||||
interface ComboBoxItem {
|
||||
label?: string | null;
|
||||
description?: string | null;
|
||||
// icon?: string | JSX.Element | null;
|
||||
blockDefId?: string;
|
||||
}
|
||||
|
||||
export interface ComboBoxPreviewProps {
|
||||
item: ComboBoxItem;
|
||||
previewLabel: string;
|
||||
}
|
||||
|
||||
export default function ComboBoxPreview({
|
||||
item: { label, description, blockDefId },
|
||||
previewLabel,
|
||||
}: ComboBoxPreviewProps) {
|
||||
const previewURL = blockDefId
|
||||
? new URL(WAGTAIL_CONFIG.ADMIN_URLS.BLOCK_PREVIEW, window.location.href)
|
||||
: undefined;
|
||||
previewURL?.searchParams.append('id', blockDefId || '');
|
||||
return (
|
||||
<div className="w-combobox-preview">
|
||||
<iframe
|
||||
className="w-combobox-preview__iframe"
|
||||
title={previewLabel}
|
||||
src={previewURL?.toString()}
|
||||
/>
|
||||
<div className="w-combobox-preview__details">
|
||||
<div className="w-combobox-preview__label">{label}</div>
|
||||
{description ? (
|
||||
<p className="w-combobox-preview__description">{description}</p>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import { createStore } from 'redux';
|
||||
import { legacy_createStore as createStore } from 'redux';
|
||||
|
||||
import { Store, reducer } from '../../state';
|
||||
|
||||
|
|
|
@ -1,7 +1,19 @@
|
|||
.comment {
|
||||
@include box;
|
||||
@include more-contrast-interactive();
|
||||
@use '../../../../../scss/tools' as *;
|
||||
|
||||
$color-box-background: theme('colors.surface-page');
|
||||
$color-box-background-focused: theme('colors.surface-page');
|
||||
$color-box-border: theme('colors.border-furniture');
|
||||
$color-box-border-focused: theme('colors.border-field-hover');
|
||||
$color-box-text: theme('colors.text-context');
|
||||
$box-border-radius: 5px;
|
||||
$box-padding: 20px;
|
||||
|
||||
.comment {
|
||||
background-color: $color-box-background;
|
||||
padding: $box-padding;
|
||||
border-radius: $box-border-radius;
|
||||
color: $color-box-text;
|
||||
border: 1px solid $color-box-border;
|
||||
width: 300px;
|
||||
display: block;
|
||||
transition:
|
||||
|
@ -12,8 +24,57 @@
|
|||
padding-bottom: 0;
|
||||
inset-inline-end: 0;
|
||||
|
||||
@include more-contrast-interactive();
|
||||
|
||||
&--focused {
|
||||
inset-inline-end: 25px;
|
||||
background-color: $color-box-background-focused;
|
||||
border: 1px solid $color-box-border-focused;
|
||||
box-shadow: 3px 2px 3px -1px theme('colors.black-10');
|
||||
}
|
||||
|
||||
textarea {
|
||||
margin: 0;
|
||||
padding: 12px;
|
||||
width: 100%;
|
||||
background-color: theme('colors.surface-field');
|
||||
border: 1px solid theme('colors.border-field-default');
|
||||
border-radius: 5px;
|
||||
color: $color-box-text;
|
||||
|
||||
&::placeholder {
|
||||
color: theme('colors.text-placeholder');
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
&__notice-placeholder {
|
||||
position: relative;
|
||||
padding-bottom: 40px;
|
||||
}
|
||||
|
||||
&__notice {
|
||||
background-color: theme('colors.warning.50');
|
||||
color: theme('colors.grey.600');
|
||||
position: absolute;
|
||||
inset-inline-start: -$box-padding;
|
||||
bottom: 0;
|
||||
width: calc(100% + #{$box-padding} * 2);
|
||||
padding: 5px 10px;
|
||||
|
||||
svg.icon {
|
||||
color: theme('colors.warning.100');
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
margin-inline-end: 10px;
|
||||
vertical-align: text-bottom;
|
||||
}
|
||||
}
|
||||
|
||||
& > &__notice-placeholder:last-child &__notice,
|
||||
&__replies:last-child > :last-child &__notice {
|
||||
border-end-start-radius: $box-border-radius;
|
||||
border-end-end-radius: $box-border-radius;
|
||||
}
|
||||
|
||||
&__text {
|
||||
|
@ -26,14 +87,10 @@
|
|||
padding-bottom: 10px;
|
||||
word-break: break-all;
|
||||
white-space: pre-wrap;
|
||||
|
||||
&--mode-deleting {
|
||||
color: theme('colors.text-context');
|
||||
}
|
||||
}
|
||||
|
||||
form {
|
||||
border-top: 1px solid $color-comment-separator;
|
||||
border-top: 1px solid theme('colors.border-furniture');
|
||||
}
|
||||
|
||||
&--mode-creating form {
|
||||
|
@ -56,7 +113,25 @@
|
|||
}
|
||||
|
||||
&__button {
|
||||
@include button;
|
||||
background-color: inherit;
|
||||
border: 1px solid theme('colors.border-button-small-outline-default');
|
||||
border-radius: 3px;
|
||||
color: theme('colors.surface-button-default');
|
||||
cursor: pointer;
|
||||
font-weight: 700;
|
||||
height: 30px;
|
||||
padding-inline-start: 10px;
|
||||
padding-inline-end: 10px;
|
||||
|
||||
&--primary {
|
||||
color: theme('colors.text-button');
|
||||
border: 1px solid theme('colors.surface-button-default');
|
||||
background-color: theme('colors.surface-button-default');
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
opacity: 0.3;
|
||||
}
|
||||
}
|
||||
|
||||
&__actions,
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
@use '../../../../../scss/tools' as *;
|
||||
|
||||
.comment-header {
|
||||
position: relative;
|
||||
|
||||
|
@ -40,7 +42,6 @@
|
|||
|
||||
> button,
|
||||
> details > summary {
|
||||
@include more-contrast-interactive();
|
||||
border-radius: theme('borderRadius.sm');
|
||||
list-style-type: none; // Hides triangle on Firefox
|
||||
width: 30px;
|
||||
|
@ -50,6 +51,8 @@
|
|||
border: unset;
|
||||
padding: 0;
|
||||
|
||||
@include more-contrast-interactive();
|
||||
|
||||
&::-webkit-details-marker {
|
||||
display: none; // Hides triangle on Chrome
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import { createStore } from 'redux';
|
||||
import { legacy_createStore as createStore } from 'redux';
|
||||
|
||||
import { Store, reducer } from '../../state';
|
||||
|
||||
|
|
|
@ -105,17 +105,17 @@ export default class CommentReplyComponent extends React.Component<CommentReplyP
|
|||
value={reply.newText}
|
||||
onChange={onChangeText}
|
||||
/>
|
||||
<div className="comment-reply__actions">
|
||||
<div className="comment__actions">
|
||||
<button
|
||||
type="submit"
|
||||
disabled={reply.newText.length === 0}
|
||||
className="comment-reply__button comment-reply__button--primary"
|
||||
className="comment__button comment__button--primary"
|
||||
>
|
||||
{gettext('Save')}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="comment-reply__button"
|
||||
className="comment__button"
|
||||
onClick={onCancel}
|
||||
>
|
||||
{gettext('Cancel')}
|
||||
|
@ -132,8 +132,8 @@ export default class CommentReplyComponent extends React.Component<CommentReplyP
|
|||
return (
|
||||
<>
|
||||
<CommentHeader commentReply={reply} store={store} focused={isFocused} />
|
||||
<p className="comment-reply__text">{reply.text}</p>
|
||||
<div className="comment-reply__progress">{gettext('Saving...')}</div>
|
||||
<p className="comment__text">{reply.text}</p>
|
||||
<div className="comment__progress">{gettext('Saving...')}</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -150,12 +150,12 @@ export default class CommentReplyComponent extends React.Component<CommentReplyP
|
|||
return (
|
||||
<>
|
||||
<CommentHeader commentReply={reply} store={store} focused={isFocused} />
|
||||
<p className="comment-reply__text">{reply.text}</p>
|
||||
<div className="comment-reply__error">
|
||||
<p className="comment__text">{reply.text}</p>
|
||||
<div className="comment__error">
|
||||
{gettext('Save error')}
|
||||
<button
|
||||
type="button"
|
||||
className="comment-reply__button"
|
||||
className="comment__button"
|
||||
onClick={onClickRetry}
|
||||
>
|
||||
{gettext('Retry')}
|
||||
|
@ -187,19 +187,19 @@ export default class CommentReplyComponent extends React.Component<CommentReplyP
|
|||
return (
|
||||
<>
|
||||
<CommentHeader commentReply={reply} store={store} focused={isFocused} />
|
||||
<p className="comment-reply__text">{reply.text}</p>
|
||||
<div className="comment-reply__confirm-delete">
|
||||
<p className="comment__text">{reply.text}</p>
|
||||
<div className="comment__confirm-delete">
|
||||
{gettext('Are you sure?')}
|
||||
<button
|
||||
type="button"
|
||||
className="comment-reply__button"
|
||||
className="comment__button button button-small"
|
||||
onClick={onClickCancel}
|
||||
>
|
||||
{gettext('Cancel')}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="comment-reply__button comment-reply__button--primary"
|
||||
className="comment__button button button-small no"
|
||||
onClick={onClickDelete}
|
||||
>
|
||||
{gettext('Delete')}
|
||||
|
@ -215,8 +215,8 @@ export default class CommentReplyComponent extends React.Component<CommentReplyP
|
|||
return (
|
||||
<>
|
||||
<CommentHeader commentReply={reply} store={store} focused={isFocused} />
|
||||
<p className="comment-reply__text">{reply.text}</p>
|
||||
<div className="comment-reply__progress">{gettext('Deleting')}</div>
|
||||
<p className="comment__text">{reply.text}</p>
|
||||
<div className="comment__progress">{gettext('Deleting')}</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -243,19 +243,19 @@ export default class CommentReplyComponent extends React.Component<CommentReplyP
|
|||
return (
|
||||
<>
|
||||
<CommentHeader commentReply={reply} store={store} focused={isFocused} />
|
||||
<p className="comment-reply__text">{reply.text}</p>
|
||||
<div className="comment-reply__error">
|
||||
<p className="comment__text">{reply.text}</p>
|
||||
<div className="comment__error">
|
||||
{gettext('Delete error')}
|
||||
<button
|
||||
type="button"
|
||||
className="comment-reply__button"
|
||||
className="comment__button"
|
||||
onClick={onClickCancel}
|
||||
>
|
||||
{gettext('Cancel')}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="comment-reply__button"
|
||||
className="comment__button"
|
||||
onClick={onClickRetry}
|
||||
>
|
||||
{gettext('Retry')}
|
||||
|
@ -308,7 +308,7 @@ export default class CommentReplyComponent extends React.Component<CommentReplyP
|
|||
onDelete={onDelete}
|
||||
focused={isFocused}
|
||||
/>
|
||||
<p className="comment-reply__text">{reply.text}</p>
|
||||
<p className="comment__text">{reply.text}</p>
|
||||
{notice && (
|
||||
<div className="comment__notice-placeholder">
|
||||
<div className="comment__notice" role="status">
|
||||
|
|
|
@ -2,111 +2,13 @@
|
|||
padding-top: 20px;
|
||||
pointer-events: auto;
|
||||
position: relative;
|
||||
border-top: 1px solid $color-comment-separator;
|
||||
border-top: 1px solid theme('colors.border-furniture');
|
||||
|
||||
&__text {
|
||||
color: $color-box-text;
|
||||
font-weight: 400;
|
||||
font-size: 16px;
|
||||
line-height: 150%;
|
||||
margin-bottom: 0;
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
word-break: break-all;
|
||||
white-space: pre-wrap;
|
||||
|
||||
&--mode-deleting {
|
||||
color: theme('colors.text-context');
|
||||
}
|
||||
}
|
||||
|
||||
&--mode-deleting &__avatar {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
&--mode-deleting &__text {
|
||||
&--mode-deleting .comment__text {
|
||||
color: theme('colors.text-meta');
|
||||
}
|
||||
|
||||
form {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
&__button {
|
||||
@include button;
|
||||
}
|
||||
|
||||
&__actions,
|
||||
&__confirm-delete,
|
||||
&__progress,
|
||||
&__error {
|
||||
&::after {
|
||||
display: block;
|
||||
content: '';
|
||||
clear: both;
|
||||
}
|
||||
}
|
||||
|
||||
&__actions {
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
&__actions &__button {
|
||||
margin-inline-end: 10px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
&__confirm-delete &__button {
|
||||
margin-inline-start: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
&__confirm-delete,
|
||||
&__error {
|
||||
color: $color-box-text;
|
||||
font-weight: bold;
|
||||
font-size: 13px;
|
||||
margin-top: 10px;
|
||||
|
||||
button {
|
||||
float: inline-end;
|
||||
}
|
||||
|
||||
&::after {
|
||||
display: block;
|
||||
content: ' ';
|
||||
clear: both;
|
||||
}
|
||||
}
|
||||
|
||||
&__error {
|
||||
color: theme('colors.white.DEFAULT');
|
||||
background-color: theme('colors.critical.200');
|
||||
border-radius: 3px;
|
||||
padding: 5px;
|
||||
padding-inline-start: 10px;
|
||||
height: 26px;
|
||||
line-height: 26px;
|
||||
vertical-align: middle;
|
||||
|
||||
button {
|
||||
height: 26px;
|
||||
float: inline-end;
|
||||
margin-inline-start: 5px;
|
||||
color: theme('colors.white.DEFAULT');
|
||||
background-color: theme('colors.critical.200');
|
||||
border-color: theme('colors.white.DEFAULT');
|
||||
padding: 2px;
|
||||
padding-inline-start: 10px;
|
||||
padding-inline-end: 10px;
|
||||
font-size: 0.65em;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
&__progress {
|
||||
margin-top: 20px;
|
||||
font-weight: bold;
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,113 +1,6 @@
|
|||
@import '../../../scss/settings/variables';
|
||||
|
||||
$color-comment-separator: theme('colors.border-furniture');
|
||||
|
||||
$color-box-background: theme('colors.surface-page');
|
||||
$color-box-background-focused: theme('colors.surface-page');
|
||||
$color-box-border: theme('colors.border-furniture');
|
||||
$color-box-border-focused: theme('colors.border-field-hover');
|
||||
$color-box-text: theme('colors.text-context');
|
||||
$box-border-radius: 5px;
|
||||
$box-padding: 20px;
|
||||
|
||||
@mixin focus-outline {
|
||||
outline: theme('colors.focus') solid 3px;
|
||||
}
|
||||
|
||||
@mixin box {
|
||||
background-color: $color-box-background;
|
||||
padding: $box-padding;
|
||||
border-radius: $box-border-radius;
|
||||
color: $color-box-text;
|
||||
border: 1px solid $color-box-border;
|
||||
|
||||
&--focused {
|
||||
background-color: $color-box-background-focused;
|
||||
border: 1px solid $color-box-border-focused;
|
||||
box-shadow: 3px 2px 3px -1px theme('colors.black-10');
|
||||
}
|
||||
|
||||
textarea {
|
||||
margin: 0;
|
||||
padding: 12px;
|
||||
width: 100%;
|
||||
background-color: theme('colors.surface-field');
|
||||
border: 1px solid theme('colors.border-field-default');
|
||||
border-radius: 5px;
|
||||
color: $color-box-text;
|
||||
|
||||
&::placeholder {
|
||||
color: theme('colors.text-placeholder');
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
*:focus {
|
||||
@include focus-outline;
|
||||
}
|
||||
|
||||
&__notice-placeholder {
|
||||
position: relative;
|
||||
padding-bottom: 40px;
|
||||
}
|
||||
|
||||
&__notice {
|
||||
background-color: theme('colors.warning.50');
|
||||
color: theme('colors.grey.600');
|
||||
position: absolute;
|
||||
inset-inline-start: -$box-padding;
|
||||
bottom: 0;
|
||||
width: calc(100% + #{$box-padding} * 2);
|
||||
padding: 5px 10px;
|
||||
|
||||
svg.icon {
|
||||
color: theme('colors.warning.100');
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
margin-inline-end: 10px;
|
||||
vertical-align: text-bottom;
|
||||
}
|
||||
}
|
||||
|
||||
& > &__notice-placeholder:last-child &__notice,
|
||||
&__replies:last-child > :last-child &__notice {
|
||||
border-end-start-radius: $box-border-radius;
|
||||
border-end-end-radius: $box-border-radius;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin button {
|
||||
background-color: inherit;
|
||||
border: 1px solid theme('colors.border-button-small-outline-default');
|
||||
border-radius: 3px;
|
||||
color: theme('colors.surface-button-default');
|
||||
cursor: pointer;
|
||||
font-weight: 700;
|
||||
height: 30px;
|
||||
padding-inline-start: 10px;
|
||||
padding-inline-end: 10px;
|
||||
|
||||
&--primary {
|
||||
color: theme('colors.text-button');
|
||||
border: 1px solid theme('colors.surface-button-default');
|
||||
background-color: theme('colors.surface-button-default');
|
||||
}
|
||||
|
||||
&--red {
|
||||
color: theme('colors.text-button');
|
||||
border: 1px solid theme('colors.critical.200');
|
||||
background-color: theme('colors.critical.200');
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
// Disable Firefox's focus styling because we add our own.
|
||||
&::-moz-focus-inner {
|
||||
border: 0;
|
||||
}
|
||||
}
|
||||
@use 'components/CommentHeader/style' as CommentHeader;
|
||||
@use 'components/Comment/style' as Comment;
|
||||
@use 'components/CommentReply/style' as CommentReply;
|
||||
|
||||
.comments-list {
|
||||
position: relative;
|
||||
|
@ -115,8 +8,3 @@ $box-padding: 20px;
|
|||
inset-inline-end: 20px;
|
||||
z-index: calc(theme('zIndex.header') + 5);
|
||||
}
|
||||
|
||||
// stylelint-disable no-invalid-position-at-import-rule
|
||||
@import 'components/CommentHeader/style';
|
||||
@import 'components/Comment/style';
|
||||
@import 'components/CommentReply/style';
|
||||
|
|
|
@ -1,13 +1,20 @@
|
|||
import React, { useCallback } from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { createStore } from 'redux';
|
||||
import { legacy_createStore as createStore } from 'redux';
|
||||
|
||||
import type { Annotation } from './utils/annotation';
|
||||
import { LayoutController } from './utils/layout';
|
||||
import { getOrDefault } from './utils/maps';
|
||||
import { getNextCommentId, getNextReplyId } from './utils/sequences';
|
||||
import { Store, reducer } from './state';
|
||||
import { Comment, newCommentReply, newComment, Author } from './state/comments';
|
||||
import {
|
||||
Comment,
|
||||
newCommentReply,
|
||||
newComment,
|
||||
Author,
|
||||
INITIAL_STATE as INITIAL_COMMENTS_STATE,
|
||||
} from './state/comments';
|
||||
import { INITIAL_STATE as INITIAL_SETTINGS_STATE } from './state/settings';
|
||||
import {
|
||||
addComment,
|
||||
addReply,
|
||||
|
@ -27,7 +34,6 @@ import {
|
|||
} from './selectors';
|
||||
import CommentComponent from './components/Comment';
|
||||
import { CommentFormSetComponent } from './components/Form';
|
||||
import { INITIAL_STATE as INITIAL_SETTINGS_STATE } from './state/settings';
|
||||
|
||||
// This is done as this is serialized pretty directly from the Django model
|
||||
export interface InitialCommentReply {
|
||||
|
@ -168,8 +174,9 @@ export class CommentApp {
|
|||
|
||||
constructor() {
|
||||
this.store = createStore(reducer, {
|
||||
comments: INITIAL_COMMENTS_STATE,
|
||||
settings: INITIAL_SETTINGS_STATE,
|
||||
});
|
||||
} as any);
|
||||
this.layout = new LayoutController();
|
||||
}
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Ładowanie…
Reference in New Issue