Compare commits
770
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9ad1e261a4 | ||
|
|
97a14ed926 | ||
|
|
5018c56d0d | ||
|
|
c7799ca7dc | ||
|
|
78b5cc9c6f | ||
|
|
ab3e6cdff9 | ||
|
|
1cc01e6952 | ||
|
|
fb90f193b1 | ||
|
|
1bacab89bb | ||
|
|
7378f2e33b | ||
|
|
d0bb2b2ad5 | ||
|
|
376da7c70e | ||
|
|
d58e5cf7ee | ||
|
|
e02eb2e30c | ||
|
|
c4906d069a | ||
|
|
d4ed535454 | ||
|
|
f9d0ab5e07 | ||
|
|
0a5efc75cd | ||
|
|
aae1fefb31 | ||
|
|
86bb28e239 | ||
|
|
16b68b3d00 | ||
|
|
a700f446fd | ||
|
|
2246f227d1 | ||
|
|
29fbf0a362 | ||
|
|
8a1fc94c31 | ||
|
|
abadc99bf1 | ||
|
|
7af7647bbf | ||
|
|
9a24090337 | ||
|
|
d81a4ef0ee | ||
|
|
cfb1830b55 | ||
|
|
f7c094317a | ||
|
|
56e0ac9640 | ||
|
|
61651a0f4d | ||
|
|
7c3a05077c | ||
|
|
2d29bce97b | ||
|
|
4f45baab00 | ||
|
|
6def64d38e | ||
|
|
32b31076e6 | ||
|
|
91a4911d42 | ||
|
|
7298faac2b | ||
|
|
711253beb2 | ||
|
|
a380389386 | ||
|
|
f6b97c691e | ||
|
|
f31ff994fe | ||
|
|
a46ef5c9dd | ||
|
|
0018c452bb | ||
|
|
6c6fc28f6e | ||
|
|
575cf31c78 | ||
|
|
938d9b6642 | ||
|
|
9d68d35ca8 | ||
|
|
8033eea267 | ||
|
|
469c4d7e99 | ||
|
|
5159d43cad | ||
|
|
c5bbb7aa2c | ||
|
|
4317d1a47e | ||
|
|
a1c04ba35e | ||
|
|
95ad3e71ca | ||
|
|
080a33fac7 | ||
|
|
851d722746 | ||
|
|
5dbfb3b8c5 | ||
|
|
735054b4e1 | ||
|
|
3ae2f857d4 | ||
|
|
220abb8579 | ||
|
|
468a67f937 | ||
|
|
99b3e3c516 | ||
|
|
8d48b2cc8a | ||
|
|
d63731fced | ||
|
|
7a352cdcb3 | ||
|
|
4744c05f07 | ||
|
|
c6cf7a4639 | ||
|
|
7f2318da01 | ||
|
|
fc9018e314 | ||
|
|
c30d6019df | ||
|
|
b57ed47592 | ||
|
|
6234be17cd | ||
|
|
5cab842f0a | ||
|
|
ca84c60614 | ||
|
|
09fbc6b0b2 | ||
|
|
f8b1998564 | ||
|
|
4d254b004d | ||
|
|
1d5f2427ed | ||
|
|
0249f89a8c | ||
|
|
ce0aaa7ac7 | ||
|
|
b7db3f96ba | ||
|
|
ad5ab82c3b | ||
|
|
0567569faa | ||
|
|
a8f111b399 | ||
|
|
7c2f789a31 | ||
|
|
77c76b6b6d | ||
|
|
60a90ce424 | ||
|
|
3f581ae1b0 | ||
|
|
277aff3898 | ||
|
|
0c5b9a863b | ||
|
|
cb1e10f0a9 | ||
|
|
659162d60c | ||
|
|
28ef465b3a | ||
|
|
e29f7af858 | ||
|
|
17b84cbe8a | ||
|
|
4d89213e1c | ||
|
|
879cbb8886 | ||
|
|
5957479d03 | ||
|
|
d7bc9bdb90 | ||
|
|
811a6bf222 | ||
|
|
6d0c560948 | ||
|
|
f4b76baaa2 | ||
|
|
76f4e974db | ||
|
|
66e5441bdf | ||
|
|
68f4adfbfe | ||
|
|
35a712eafb | ||
|
|
2d12fbdff1 | ||
|
|
c0ff162ed9 | ||
|
|
059408f098 | ||
|
|
b118a321b9 | ||
|
|
b3b6f1d834 | ||
|
|
1383d8b59a | ||
|
|
990aed9f2e | ||
|
|
003d419a64 | ||
|
|
7368cb2567 | ||
|
|
f945a27011 | ||
|
|
72882fded9 | ||
|
|
0030394008 | ||
|
|
bfb299cfca | ||
|
|
b06d5c10ea | ||
|
|
2a0d4195a1 | ||
|
|
11ff99613a | ||
|
|
0b646ee64f | ||
|
|
23126a92cd | ||
|
|
f767125acd | ||
|
|
d8ed9abebf | ||
|
|
e4e75632c5 | ||
|
|
ddb7c24832 | ||
|
|
4a824dec81 | ||
|
|
b35fee1be8 | ||
|
|
1b167af12b | ||
|
|
f2962e34ae | ||
|
|
386db5029a | ||
|
|
0e6e54a124 | ||
|
|
c666cb3879 | ||
|
|
4039517683 | ||
|
|
00fc7b8038 | ||
|
|
81d283ec8d | ||
|
|
105100e349 | ||
|
|
4598690dbf | ||
|
|
f68341c315 | ||
|
|
e8a8cea909 | ||
|
|
bf53f107e3 | ||
|
|
00de974528 | ||
|
|
0445398e94 | ||
|
|
272e2ba955 | ||
|
|
0a2adc2d92 | ||
|
|
7008fc1770 | ||
|
|
041a261540 | ||
|
|
05442af050 | ||
|
|
1008d819f7 | ||
|
|
25d538504c | ||
|
|
e823533809 | ||
|
|
fb84a79a04 | ||
|
|
45bfdbdce0 | ||
|
|
1537c2141f | ||
|
|
3ba1a52644 | ||
|
|
a015cc6706 | ||
|
|
5bad362793 | ||
|
|
5520756edd | ||
|
|
ba954a1d6e | ||
|
|
2944ff298c | ||
|
|
80d121e87a | ||
|
|
ed8352d857 | ||
|
|
41f64ca9fe | ||
|
|
738e49dc92 | ||
|
|
68a16257c6 | ||
|
|
5dcbae55f4 | ||
|
|
e0d963256c | ||
|
|
2bff4bbd15 | ||
|
|
a0eba89f34 | ||
|
|
4e78de9da2 | ||
|
|
85f00eb7e8 | ||
|
|
8e13855b66 | ||
|
|
06f49e24c2 | ||
|
|
e598ae45f7 | ||
|
|
ad7f469e06 | ||
|
|
cb57ff5cc2 | ||
|
|
72f070fbcb | ||
|
|
fb0a86d37c | ||
|
|
36402dfefa | ||
|
|
c61874dbdd | ||
|
|
20848f28d5 | ||
|
|
5d23966f00 | ||
|
|
294cc66e4a | ||
|
|
0fd2e7032a | ||
|
|
340b85043e | ||
|
|
1821ae3c2b | ||
|
|
c536cb2afa | ||
|
|
3f79b4c2f6 | ||
|
|
137ba9185e | ||
|
|
2f6a0913dc | ||
|
|
2c7336d440 | ||
|
|
5a022ff3f6 | ||
|
|
fe4855500e | ||
|
|
ce8f5cbe0c | ||
|
|
b6bebe33fe | ||
|
|
9cf8072c1e | ||
|
|
0ca00ca6a1 | ||
|
|
619c5242db | ||
|
|
ff07854590 | ||
|
|
ba99989c66 | ||
|
|
3c75933cf2 | ||
|
|
ea9ef7afd3 | ||
|
|
f5e633a781 | ||
|
|
90b94816dd | ||
|
|
11dcaef3ff | ||
|
|
3f3e7f71ec | ||
|
|
b6070572cf | ||
|
|
e818a02a2a | ||
|
|
d8c8e222c8 | ||
|
|
f12b9715bc | ||
|
|
31c65d3e0b | ||
|
|
fcd6741cf9 | ||
|
|
d663b9230f | ||
|
|
5f2d61ad7a | ||
|
|
ec80a2dc0b | ||
|
|
2cece3de59 | ||
|
|
79eb580802 | ||
|
|
b93e3327a7 | ||
|
|
f01030a47a | ||
|
|
3cbd907c09 | ||
|
|
8fae69b7a4 | ||
|
|
e45dd4240e | ||
|
|
16a8552e6c | ||
|
|
c953ec6152 | ||
|
|
a433f10240 | ||
|
|
b73b97b5e9 | ||
|
|
0607e0b228 | ||
|
|
3bd4f67ec7 | ||
|
|
845d5a5d51 | ||
|
|
0101da731f | ||
|
|
68592acd39 | ||
|
|
b86fc5edb3 | ||
|
|
32b54ddf11 | ||
|
|
f8a0741e6c | ||
|
|
652d231771 | ||
|
|
1c3c5f4fec | ||
|
|
e7006a4a44 | ||
|
|
0f81d54f25 | ||
|
|
f3121c24c6 | ||
|
|
7abd0f2cd4 | ||
|
|
46b342005a | ||
|
|
4e0349bd58 | ||
|
|
30a569233b | ||
|
|
44ba6b4d0f | ||
|
|
9065070eb2 | ||
|
|
fd951bfdd5 | ||
|
|
27d613b594 | ||
|
|
ba757b9aa4 | ||
|
|
c445463c0c | ||
|
|
4693177e4b | ||
|
|
30b135eba3 | ||
|
|
bda48e07f1 | ||
|
|
7c8ab64e34 | ||
|
|
ec7855bd02 | ||
|
|
d401eefd6b | ||
|
|
0ad759a384 | ||
|
|
d3d20b29c3 | ||
|
|
fbb570c0d5 | ||
|
|
2318082bb8 | ||
|
|
05dd5f7de2 | ||
|
|
841251d09e | ||
|
|
a4dd8f70f0 | ||
|
|
9d0d1329b6 | ||
|
|
7a929777b4 | ||
|
|
ce3ec99c9f | ||
|
|
4f7847275e | ||
|
|
9a5ddb22b3 | ||
|
|
b1322cbec3 | ||
|
|
637bc84136 | ||
|
|
3147f02b6a | ||
|
|
dabff74946 | ||
|
|
de99577b9d | ||
|
|
1846432601 | ||
|
|
6f307dc822 | ||
|
|
f43210e29e | ||
|
|
50b9be4eca | ||
|
|
1a38222974 | ||
|
|
cb9cd0a43c | ||
|
|
c2e2ae8dbd | ||
|
|
df790a92be | ||
|
|
e1f9242b34 | ||
|
|
9d2a52e639 | ||
|
|
5cbca9457e | ||
|
|
25c66cff43 | ||
|
|
75a2e0deee | ||
|
|
b857137f1a | ||
|
|
40141cdcb0 | ||
|
|
c5c1d6903e | ||
|
|
f15c8188b9 | ||
|
|
8f971cfb02 | ||
|
|
32c811ec5a | ||
|
|
4febc56c30 | ||
|
|
f22ee4a68b | ||
|
|
87bec0399f | ||
|
|
1f29255dd1 | ||
|
|
4a11638182 | ||
|
|
10743372f8 | ||
|
|
d4b11bbb76 | ||
|
|
ced2417c98 | ||
|
|
27415aeca6 | ||
|
|
9bd2e336a6 | ||
|
|
d5778ec173 | ||
|
|
74e80f086a | ||
|
|
b1c6191fa1 | ||
|
|
8e0245c844 | ||
|
|
613fbf8c39 | ||
|
|
1788cda5c2 | ||
|
|
155adf549e | ||
|
|
5463542532 | ||
|
|
f5a25bc0e5 | ||
|
|
993339d0d1 | ||
|
|
bc4fe897cf | ||
|
|
c773bdaabd | ||
|
|
9f9a2be1d8 | ||
|
|
1e4b0c2f20 | ||
|
|
56025f6d56 | ||
|
|
5188b90f32 | ||
|
|
7178f537a8 | ||
|
|
45ac589975 | ||
|
|
9925e10ffc | ||
|
|
e3fde8d564 | ||
|
|
8aee01e008 | ||
|
|
cd203ff067 | ||
|
|
254cb6d80f | ||
|
|
9b3ad54d0a | ||
|
|
4ae3bb5780 | ||
|
|
b8aa1ef765 | ||
|
|
5e5daef49a | ||
|
|
88c478c533 | ||
|
|
1ecec115e4 | ||
|
|
8ff597eedb | ||
|
|
69f74488e5 | ||
|
|
ded9a27f42 | ||
|
|
43284ae625 | ||
|
|
f7b1ef9741 | ||
|
|
a6d445818f | ||
|
|
122a84b9e2 | ||
|
|
065a6cb1fd | ||
|
|
ae9eb494ae | ||
|
|
0241797e79 | ||
|
|
9d45947b08 | ||
|
|
f2c26c0eed | ||
|
|
f7a1416070 | ||
|
|
9e05d024a8 | ||
|
|
3bd4c8d747 | ||
|
|
9ae7314f54 | ||
|
|
c77d1e3322 | ||
|
|
0e767d6581 | ||
|
|
7ff5935f94 | ||
|
|
cb4566f829 | ||
|
|
52249d5b7e | ||
|
|
22e0507fbd | ||
|
|
e32e72de7a | ||
|
|
ff31ee773f | ||
|
|
a1cbbf5d42 | ||
|
|
ce667bc53b | ||
|
|
d5526b89d9 | ||
|
|
096cfccf40 | ||
|
|
f381b0ce4a | ||
|
|
867b530573 | ||
|
|
2141c3eacd | ||
|
|
13a5f699ba | ||
|
|
7ab5f4ab09 | ||
|
|
480ba034ce | ||
|
|
a03996d54b | ||
|
|
d560e923d2 | ||
|
|
235fc979b2 | ||
|
|
f5aefb1f0b | ||
|
|
e27cc8a12b | ||
|
|
f2e2d5c2ed | ||
|
|
6d999eccbd | ||
|
|
136144b8ec | ||
|
|
355a445ead | ||
|
|
c490508252 | ||
|
|
7b4160ac92 | ||
|
|
781854d85c | ||
|
|
86dc71687d | ||
|
|
f0e79121a7 | ||
|
|
ed1b88f1fd | ||
|
|
bb5a3e73c8 | ||
|
|
38b2025286 | ||
|
|
c12f5880e2 | ||
|
|
94cf22ab8e | ||
|
|
0bc8142e71 | ||
|
|
d890b972be | ||
|
|
05945a9a74 | ||
|
|
88b68a9df0 | ||
|
|
8b322a0ec0 | ||
|
|
7968ed8a19 | ||
|
|
2fba22d0f6 | ||
|
|
cce930b90a | ||
|
|
c5dd16511d | ||
|
|
65f437f08e | ||
|
|
47c231a214 | ||
|
|
f5d0b74ccf | ||
|
|
17cac37967 | ||
|
|
b7e7028b6f | ||
|
|
ea3df7be42 | ||
|
|
f0d7e82e22 | ||
|
|
c6d56b30e4 | ||
|
|
8225924da6 | ||
|
|
6517e9ee6c | ||
|
|
10ad3397a3 | ||
|
|
dd9468cb2e | ||
|
|
0b9ab0614f | ||
|
|
e13f495d71 | ||
|
|
029b8fac37 | ||
|
|
6e5ada79de | ||
|
|
59f050135a | ||
|
|
dc8b0aed9f | ||
|
|
424df24bf3 | ||
|
|
d451f725cd | ||
|
|
d04b8fddb0 | ||
|
|
bb592964ee | ||
|
|
786dd427bc | ||
|
|
4c2c452b91 | ||
|
|
1765bf7e55 | ||
|
|
e19de23770 | ||
|
|
765a1a24ed | ||
|
|
e42b4b2808 | ||
|
|
65f6925864 | ||
|
|
02b7dc080b | ||
|
|
d4e8381827 | ||
|
|
de34710c90 | ||
|
|
cd8752c1cb | ||
|
|
86a0b0b60c | ||
|
|
fc5ccf1cf8 | ||
|
|
45352b62e1 | ||
|
|
0ea3379397 | ||
|
|
281cbbc30f | ||
|
|
0de9e067c6 | ||
|
|
77c00558aa | ||
|
|
10c5463892 | ||
|
|
7b963ca877 | ||
|
|
aa35e9211b | ||
|
|
2fc0eb9460 | ||
|
|
91b4c976e5 | ||
|
|
950c5fdc92 | ||
|
|
114572024c | ||
|
|
8503b7ece4 | ||
|
|
b53650a50f | ||
|
|
9ad3b58fcd | ||
|
|
521c6988a5 | ||
|
|
7900e1104f | ||
|
|
035edd92f4 | ||
|
|
2c4c6a5024 | ||
|
|
12747bd95b | ||
|
|
7c22663250 | ||
|
|
eb4856901b | ||
|
|
da905169e1 | ||
|
|
fe9bf6375f | ||
|
|
800f988979 | ||
|
|
b4f42bb7d4 | ||
|
|
e58c5fdb86 | ||
|
|
4e3f552538 | ||
|
|
2d01205f70 | ||
|
|
ebfb25ebc0 | ||
|
|
d93fb48202 | ||
|
|
a73d0ef3b4 | ||
|
|
8274d4ffbe | ||
|
|
48990b860f | ||
|
|
b61a7ffc3c | ||
|
|
37a3028540 | ||
|
|
2e675f5dee | ||
|
|
6a2a79c086 | ||
|
|
a86e9ff480 | ||
|
|
3dc332010e | ||
|
|
61a1972c4c | ||
|
|
0779e5ea15 | ||
|
|
fab78f0cee | ||
|
|
ce49270cf8 | ||
|
|
7a190f7c69 | ||
|
|
126767ed5c | ||
|
|
7d5302cfcf | ||
|
|
87d3d6a8f0 | ||
|
|
927e8a88b8 | ||
|
|
73a6277feb | ||
|
|
94a7044b7b | ||
|
|
54d3392cf1 | ||
|
|
f1c9aad4e6 | ||
|
|
48cf8a5e73 | ||
|
|
b5f4c04165 | ||
|
|
a9c2549376 | ||
|
|
7bf96f6194 | ||
|
|
ae40cb8a54 | ||
|
|
16ebe4b1ab | ||
|
|
c7914a1c4f | ||
|
|
6b12246ec0 | ||
|
|
4a42b6eb43 | ||
|
|
de742068a7 | ||
|
|
b383ce5b11 | ||
|
|
ccb424eafe | ||
|
|
585fb4f700 | ||
|
|
00f5eaf44d | ||
|
|
8bacbcde89 | ||
|
|
245e436a88 | ||
|
|
2d6fdcb1e2 | ||
|
|
8adad64248 | ||
|
|
e7cf6d385c | ||
|
|
753a904c94 | ||
|
|
0ccbd17709 | ||
|
|
78a5b2e666 | ||
|
|
5e46a9f2d5 | ||
|
|
0ecbf48f5d | ||
|
|
d4ecb26ffe | ||
|
|
e04ac77ddd | ||
|
|
cd3702f5b5 | ||
|
|
ca02ed9d18 | ||
|
|
f934bbf829 | ||
|
|
da7d9c02c8 | ||
|
|
e55d8618bd | ||
|
|
af010e138d | ||
|
|
9d94b71583 | ||
|
|
38d31192ed | ||
|
|
a0799874e4 | ||
|
|
5ec2500310 | ||
|
|
0bd9aa1e3f | ||
|
|
20dd3ead3e | ||
|
|
b30a512d6e | ||
|
|
e63faebcb8 | ||
|
|
7e5cb1facc | ||
|
|
10c822c5d9 | ||
|
|
8761b3e28d | ||
|
|
19cccbbcad | ||
|
|
dbea93f9ba | ||
|
|
4629014922 | ||
|
|
24e7b1c224 | ||
|
|
ad06544a64 | ||
|
|
8d105e636d | ||
|
|
bf5d7f3c53 | ||
|
|
c5cd3512af | ||
|
|
2802cce6f1 | ||
|
|
6e49e19ba1 | ||
|
|
0c6d635b67 | ||
|
|
de80a530e5 | ||
|
|
63b106d844 | ||
|
|
ab96e321c9 | ||
|
|
0b7d1abb71 | ||
|
|
592c184ffe | ||
|
|
f3e50120ee | ||
|
|
850510b7e8 | ||
|
|
d1e9a1221f | ||
|
|
56ea28aa83 | ||
|
|
140ae1d049 | ||
|
|
6025323c4b | ||
|
|
261c83158b | ||
|
|
1a5f16c4e3 | ||
|
|
ab0bf5ca5f | ||
|
|
158b66e43b | ||
|
|
ec99b5e9b4 | ||
|
|
19fe41d738 | ||
|
|
5c147562b3 | ||
|
|
051c17f454 | ||
|
|
ab8868e6c4 | ||
|
|
b5b600db1f | ||
|
|
41f917ddf6 | ||
|
|
e5e02b553a | ||
|
|
729f107af2 | ||
|
|
8bfb187ef0 | ||
|
|
1c47c8ce2c | ||
|
|
acc910cbc0 | ||
|
|
1aedf21566 | ||
|
|
6cb538ce69 | ||
|
|
cafd9f9899 | ||
|
|
bb2ab8e08a | ||
|
|
3059e730e2 | ||
|
|
dc321580c3 | ||
|
|
6cfa77a335 | ||
|
|
ddf3e8251d | ||
|
|
0cfe9d60fb | ||
|
|
19d3ae119c | ||
|
|
d59e2796e7 | ||
|
|
12ff66fd3e | ||
|
|
35270e2761 | ||
|
|
47021fa55c | ||
|
|
89f5be2cc9 | ||
|
|
d3493a0af6 | ||
|
|
157343d152 | ||
|
|
5f36543d44 | ||
|
|
a004b7b450 | ||
|
|
56d8224fb9 | ||
|
|
dd6e7b7e7e | ||
|
|
6d5034e2a5 | ||
|
|
ed6882ba95 | ||
|
|
b3f8d77238 | ||
|
|
c287da92d9 | ||
|
|
aea79fec2e | ||
|
|
3239f555a1 | ||
|
|
da49e15589 | ||
|
|
cfebc770fd | ||
|
|
ffef14957f | ||
|
|
05666f70e0 | ||
|
|
c1dc575f53 | ||
|
|
bf861700fa | ||
|
|
627c2174a9 | ||
|
|
b27eccec88 | ||
|
|
8c0dfb2cc5 | ||
|
|
c766dc9f00 | ||
|
|
7236e85321 | ||
|
|
b7093b5de5 | ||
|
|
3650c400ca | ||
|
|
4933d11dfd | ||
|
|
08128279b4 | ||
|
|
181e149028 | ||
|
|
9bb9265a19 | ||
|
|
65f232161f | ||
|
|
df97b93a9a | ||
|
|
f58d05f1b3 | ||
|
|
06fa79e09d | ||
|
|
6da52adc74 | ||
|
|
0b4ec46f79 | ||
|
|
6e321afa72 | ||
|
|
a08ded4093 | ||
|
|
e76b44fcba | ||
|
|
1fa2dbcf85 | ||
|
|
74fd20cfa8 | ||
|
|
f90b5bab4b | ||
|
|
812cff0fd9 | ||
|
|
7127c28c35 | ||
|
|
4f186a6b49 | ||
|
|
fe76416059 | ||
|
|
ac2b7bd65d | ||
|
|
604b20855b | ||
|
|
e157ee7c53 | ||
|
|
91ccfe26b7 | ||
|
|
de88e1d442 | ||
|
|
baf5967dca | ||
|
|
df6a1b39e0 | ||
|
|
8fcaf721ad | ||
|
|
22d17708cd | ||
|
|
457408006b | ||
|
|
f74289fe49 | ||
|
|
86ece89cec | ||
|
|
22826afd21 | ||
|
|
73f2f29c2a | ||
|
|
a6eb2735aa | ||
|
|
c4d42dd9e3 | ||
|
|
e047309812 | ||
|
|
c11da04e13 | ||
|
|
4f68a76674 | ||
|
|
b2fdb11195 | ||
|
|
97082b30b9 | ||
|
|
43ac0174d1 | ||
|
|
cb02bb0de7 | ||
|
|
9c9eaca990 | ||
|
|
8336ea199d | ||
|
|
48848d1d43 | ||
|
|
1eea0b6862 | ||
|
|
2977c1f6db | ||
|
|
c70ee26c8a | ||
|
|
1b085236c7 | ||
|
|
78b371bfad | ||
|
|
fdff3be316 | ||
|
|
f2037bf5fe | ||
|
|
a28a8fe5f9 | ||
|
|
62f94cfb20 | ||
|
|
3e75972b02 | ||
|
|
d6d3b53846 | ||
|
|
87f843df1c | ||
|
|
5dbec377e5 | ||
|
|
a489c9ff45 | ||
|
|
4d989746fd | ||
|
|
ba48461417 | ||
|
|
55e2d5c0e3 | ||
|
|
8864f9799f | ||
|
|
e2ddffe24b | ||
|
|
12b7819791 | ||
|
|
bfa6832beb | ||
|
|
846564a17e | ||
|
|
46d7009837 | ||
|
|
0c04db3299 | ||
|
|
2d437e2016 | ||
|
|
37655a64c0 | ||
|
|
4921b17f11 | ||
|
|
dae0d6cc42 | ||
|
|
c392933e55 | ||
|
|
c915137ed7 | ||
|
|
945cff978b | ||
|
|
ae21b728bc | ||
|
|
8ffd9a5e2a | ||
|
|
b823f0f7db | ||
|
|
066df2c64f | ||
|
|
200a933647 | ||
|
|
4cd5cd4bae | ||
|
|
bfba1d148e | ||
|
|
c58801f6f7 | ||
|
|
616927d388 | ||
|
|
1cbebf322b | ||
|
|
a46c032979 | ||
|
|
f03f94c3dd | ||
|
|
1cee10842e | ||
|
|
55e9c74031 | ||
|
|
45a9495a51 | ||
|
|
c785704dd8 | ||
|
|
38bb915144 | ||
|
|
e2f99f52db | ||
|
|
c54feb9306 | ||
|
|
e11b09feac | ||
|
|
fe44bc989a | ||
|
|
93bf98fe72 | ||
|
|
5a2626b38b | ||
|
|
5d57138ea8 | ||
|
|
20519afe17 | ||
|
|
f23f7df147 | ||
|
|
b89ab5a192 | ||
|
|
35c59dc53b | ||
|
|
870cd6407e | ||
|
|
f62350fea0 | ||
|
|
39779b9dd5 | ||
|
|
9716e64c93 | ||
|
|
0f9f814b27 | ||
|
|
49b08e9e6f | ||
|
|
a879051454 | ||
|
|
a0439cd7f4 | ||
|
|
bc436da263 | ||
|
|
c86c5d8235 | ||
|
|
86160a103d | ||
|
|
f912c5eb5d | ||
|
|
84f0b936ca | ||
|
|
72d34fcc4f | ||
|
|
2bb7818116 | ||
|
|
39d666df6b | ||
|
|
a7dd23141c | ||
|
|
a7e26d553f | ||
|
|
95e82cf254 | ||
|
|
07c8334248 | ||
|
|
c54e6b0b34 | ||
|
|
f8a7b86ab7 | ||
|
|
5b395b96cd | ||
|
|
b1b4fd3f64 | ||
|
|
352d3a1647 | ||
|
|
f04fd8bea2 | ||
|
|
6e76e29768 | ||
|
|
2c1a01bb6a | ||
|
|
2d587a7d1b | ||
|
|
b7b7687608 | ||
|
|
840069b935 | ||
|
|
1cbec8220d | ||
|
|
1456c4f749 | ||
|
|
881944ab98 | ||
|
|
eaa85bb9c4 | ||
|
|
cc26601c06 | ||
|
|
643d160748 | ||
|
|
a71756a6ec | ||
|
|
db02f68095 | ||
|
|
a0f3db812e | ||
|
|
8c393f848b | ||
|
|
cf591a5a0b | ||
|
|
b45df68ece | ||
|
|
fdaaacc3af | ||
|
|
cb2016a5dc | ||
|
|
9040a99853 | ||
|
|
94ac24289e | ||
|
|
eb8cf1b6da | ||
|
|
1d816b0677 | ||
|
|
c3f5d249a0 | ||
|
|
f00d7275e5 | ||
|
|
4ed8d6b90c | ||
|
|
6e5550ba32 | ||
|
|
edd2346939 | ||
|
|
2b4727db0d | ||
|
|
ce103c6b59 | ||
|
|
38f5c41272 | ||
|
|
ca13185d84 | ||
|
|
f1c6beacf2 |
No files matched your search
@@ -0,0 +1 @@
|
||||
release_notes: false
|
||||
@@ -0,0 +1 @@
|
||||
* @ajhollid @mohicody @Br0wnHammer @Owaiseimdad @karenvicent @shanikauwu1
|
||||
@@ -6,7 +6,9 @@ import { URLSearchParams } from "url";
|
||||
// POEditor API information
|
||||
const API_TOKEN = process.env.POEDITOR_API;
|
||||
const PROJECT_ID = process.env.POEDITOR_PROJECT_ID;
|
||||
const LANGUAGES = (process.env.LANGUAGES || "tr,en").split(",");
|
||||
const LANGUAGES = (
|
||||
process.env.LANGUAGES || "ar,zh-tw,cs,en,fi,fr,de,pt-br,ru,es,tr,ja,zh-cn,th"
|
||||
).split(",");
|
||||
const EXPORT_FORMAT = process.env.EXPORT_FORMAT || "key_value_json";
|
||||
|
||||
// POEditor API endpoint
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
name: Build Check (Client & Server)
|
||||
on:
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build-client:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
|
||||
- name: Install client dependencies
|
||||
working-directory: client
|
||||
run: npm install
|
||||
|
||||
- name: Check client build
|
||||
working-directory: client
|
||||
run: npm run build
|
||||
build-server:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
|
||||
- name: Install server dependencies
|
||||
working-directory: server
|
||||
run: npm install
|
||||
|
||||
- name: Check server build
|
||||
working-directory: server
|
||||
run: npm run build
|
||||
@@ -16,7 +16,7 @@ jobs:
|
||||
|
||||
- name: Install client dependencies
|
||||
working-directory: client
|
||||
run: npm ci
|
||||
run: npm install
|
||||
|
||||
- name: Check client formatting
|
||||
working-directory: client
|
||||
@@ -34,29 +34,8 @@ jobs:
|
||||
|
||||
- name: Install server dependencies
|
||||
working-directory: server
|
||||
run: npm ci
|
||||
run: npm install
|
||||
|
||||
- name: Check server formatting
|
||||
working-directory: server
|
||||
run: npm run format-check
|
||||
close-pr-if-needed:
|
||||
if: always()
|
||||
runs-on: ubuntu-latest
|
||||
needs: [format-client, format-server]
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Get PR number
|
||||
id: pr
|
||||
run: echo "PR_NUMBER=$(jq -r .pull_request.number "$GITHUB_EVENT_PATH")" >> $GITHUB_ENV
|
||||
|
||||
- name: Close PR using GitHub CLI
|
||||
if: |
|
||||
needs.format-client.result == 'failure' ||
|
||||
needs.format-server.result == 'failure'
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
gh pr close "$PR_NUMBER" --delete-branch --comment "❌ Formatting check failed — PR auto-closed.
|
||||
Please run \`npm run format\` in both `client` and `server` directories and push again."
|
||||
@@ -79,18 +79,6 @@ jobs:
|
||||
run: |
|
||||
docker push ghcr.io/bluewave-labs/checkmate-mongo:${{ steps.extract_tag.outputs.version }}
|
||||
|
||||
- name: Build Redis Docker image
|
||||
run: |
|
||||
docker build \
|
||||
-t ghcr.io/bluewave-labs/checkmate-redis:${{ steps.extract_tag.outputs.version }} \
|
||||
-f ./docker/dist/redis.Dockerfile \
|
||||
--label org.opencontainers.image.source=https://github.com/bluewave-labs/checkmate \
|
||||
.
|
||||
|
||||
- name: Push Redis Docker image
|
||||
run: |
|
||||
docker push ghcr.io/bluewave-labs/checkmate-redis:${{ steps.extract_tag.outputs.version }}
|
||||
|
||||
docker-build-and-push-server-mono-multiarch:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
@@ -74,18 +74,6 @@ jobs:
|
||||
run: |
|
||||
docker push ghcr.io/bluewave-labs/checkmate-mongo:latest
|
||||
|
||||
- name: Build Redis Docker image
|
||||
run: |
|
||||
docker build \
|
||||
-t ghcr.io/bluewave-labs/checkmate-redis:latest \
|
||||
-f ./docker/dist/redis.Dockerfile \
|
||||
--label org.opencontainers.image.source=https://github.com/bluewave-labs/checkmate \
|
||||
.
|
||||
|
||||
- name: Push Redis Docker image
|
||||
run: |
|
||||
docker push ghcr.io/bluewave-labs/checkmate-redis:latest
|
||||
|
||||
docker-build-and-push-server-mono-multiarch:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
@@ -7,7 +7,7 @@ on:
|
||||
languages:
|
||||
description: "Languages to synchronize (comma separated, e.g.: tr,en,es)"
|
||||
required: false
|
||||
default: "ar,zh-tw,cs,en,fi,fr,de,pt-br,ru,es,tr"
|
||||
default: "ar,zh-tw,cs,en,fi,fr,de,pt-br,ru,es,tr,ja,zh-cn,th"
|
||||
format:
|
||||
description: "Export format (key_value_json or json)"
|
||||
required: false
|
||||
|
||||
@@ -71,17 +71,6 @@ jobs:
|
||||
- name: Push MongoDB Docker image
|
||||
run: docker push ghcr.io/bluewave-labs/checkmate:mongo-demo
|
||||
|
||||
- name: Build Redis Docker image
|
||||
run: |
|
||||
docker build \
|
||||
-t ghcr.io/bluewave-labs/checkmate:redis-demo \
|
||||
-f ./docker/prod/redis.Dockerfile \
|
||||
--label org.opencontainers.image.source=https://github.com/bluewave-labs/checkmate \
|
||||
.
|
||||
|
||||
- name: Push Redis Docker image
|
||||
run: docker push ghcr.io/bluewave-labs/checkmate:redis-demo
|
||||
|
||||
deploy-to-demo:
|
||||
needs: docker-build-and-push-server
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
@@ -71,17 +71,6 @@ jobs:
|
||||
- name: Push MongoDB Docker image
|
||||
run: docker push ghcr.io/bluewave-labs/checkmate:mongo-staging
|
||||
|
||||
- name: Build Redis Docker image
|
||||
run: |
|
||||
docker build \
|
||||
-t ghcr.io/bluewave-labs/checkmate:redis-staging \
|
||||
-f ./docker/staging/redis.Dockerfile \
|
||||
--label org.opencontainers.image.source=https://github.com/bluewave-labs/checkmate \
|
||||
.
|
||||
|
||||
- name: Push Redis Docker image
|
||||
run: docker push ghcr.io/bluewave-labs/checkmate:redis-staging
|
||||
|
||||
deploy-to-staging:
|
||||
needs: docker-build-and-push-server
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
.idea
|
||||
.vscode
|
||||
.VSCodeCounter
|
||||
+166
-12
@@ -6,7 +6,7 @@ We truly appreciate all kinds of contributions — code, ideas, translations or
|
||||
|
||||
Before you start, please take a moment to read the relevant section. It helps us review and accept contributions faster, and makes the whole process smoother for everyone. 💚
|
||||
|
||||
PS: **We work closely with contributors on our [Discord channel](https://discord.com/invite/NAb6H3UTjK)**. You’ll find community members, core maintainers, and first-timers helping each other out.
|
||||
PS: **We work closely with contributors on our [Discord channel](https://discord.com/invite/NAb6H3UTjK)**. You'll find community members, core maintainers, and first-timers helping each other out.
|
||||
|
||||
---
|
||||
|
||||
@@ -32,12 +32,12 @@ PS: **We work closely with contributors on our [Discord channel](https://discord
|
||||
|
||||
### Get help or ask a question?
|
||||
|
||||
Ask anything in our [Discord server](https://discord.com/invite/NAb6H3UTjK) — we’re friendly and happy to help. [Our core contributors](https://github.com/bluewave-labs/checkmate?tab=readme-ov-file#-contributing) are active and ready to support you. You can also use [GitHub Discussions](https://github.com/bluewave-labs/Checkmate/discussions) section to ask your questions.
|
||||
Ask anything in our [Discord server](https://discord.com/invite/NAb6H3UTjK) — we're friendly and happy to help. [Our core contributors](https://github.com/bluewave-labs/checkmate?tab=readme-ov-file#-contributing) are active and ready to support you. You can also use [GitHub Discussions](https://github.com/bluewave-labs/Checkmate/discussions) section to ask your questions.
|
||||
|
||||
### Report a bug?
|
||||
|
||||
1. Search [existing issues](https://github.com/bluewave-labs/checkmate/issues).
|
||||
2. If it’s not listed, open a **new issue**.
|
||||
2. If it's not listed, open a **new issue**.
|
||||
3. Include as much detail as possible: what happened, what you expected, and steps to reproduce. Logs and screenshots help.
|
||||
|
||||
### Suggest a new feature?
|
||||
@@ -48,19 +48,175 @@ Ask anything in our [Discord server](https://discord.com/invite/NAb6H3UTjK) —
|
||||
|
||||
### Set up Checkmate locally?
|
||||
|
||||
Frontend & backend:
|
||||
#### Prerequisites
|
||||
|
||||
- Node.js (with npm)
|
||||
- Docker
|
||||
- Git
|
||||
|
||||
#### Step 1: Clone the Repository
|
||||
|
||||
```bash
|
||||
git clone https://github.com/bluewave-labs/Checkmate.git
|
||||
cd Checkmate
|
||||
```
|
||||
|
||||
#### Step 2: Set Up Docker Containers (MongoDB)
|
||||
|
||||
Navigate to the Docker dev directory:
|
||||
|
||||
```bash
|
||||
cd server/docker/dev
|
||||
```
|
||||
|
||||
Build the Docker images:
|
||||
|
||||
```bash
|
||||
./build_images.sh
|
||||
```
|
||||
|
||||
Run MongoDB container:
|
||||
|
||||
```bash
|
||||
docker run -d -p 27017:27017 -v $(pwd)/mongo/data:/data/db --name uptime_database_mongo uptime_database_mongo
|
||||
```
|
||||
|
||||
Navigate back to the root directory:
|
||||
|
||||
```bash
|
||||
cd ../../..
|
||||
```
|
||||
|
||||
#### Step 3: Set Up the Backend (Server)
|
||||
|
||||
Navigate to the server directory:
|
||||
|
||||
```bash
|
||||
cd server
|
||||
```
|
||||
|
||||
Install dependencies:
|
||||
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
Create a `.env` file in the `server` directory with the following minimum required configuration:
|
||||
|
||||
```env
|
||||
CLIENT_HOST="http://localhost:5173"
|
||||
JWT_SECRET="my_secret_key_change_this"
|
||||
DB_CONNECTION_STRING="mongodb://localhost:27017/uptime_db"
|
||||
TOKEN_TTL="99d"
|
||||
ORIGIN="localhost"
|
||||
LOG_LEVEL="debug"
|
||||
```
|
||||
|
||||
**Environment Variables Explained:**
|
||||
|
||||
- `CLIENT_HOST`: Frontend URL (default: http://localhost:5173)
|
||||
- `JWT_SECRET`: Secret key for JWT tokens (change to something secure)
|
||||
- `DB_CONNECTION_STRING`: MongoDB connection URL
|
||||
- `ORIGIN`: Origin for CORS purposes
|
||||
- `TOKEN_TTL`: Token time to live (in vercel/ms format)
|
||||
- `LOG_LEVEL`: Debug level (debug, info, warn, error)
|
||||
|
||||
Start the backend server:
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
By default, the frontend expects the backend on `http://localhost:3001`. Update configs if needed.
|
||||
The server will run at `http://localhost:52345`.
|
||||
|
||||
#### Step 4: Set Up the Frontend (Client)
|
||||
|
||||
Open a new terminal window and navigate to the client directory from the root:
|
||||
|
||||
```bash
|
||||
cd client
|
||||
```
|
||||
|
||||
Install dependencies:
|
||||
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
Create a `.env` file in the `client` directory:
|
||||
|
||||
```env
|
||||
VITE_APP_API_BASE_URL="http://localhost:52345/api/v1"
|
||||
VITE_APP_LOG_LEVEL="debug"
|
||||
```
|
||||
|
||||
**Environment Variables Explained:**
|
||||
|
||||
- `VITE_APP_API_BASE_URL`: Backend API URL
|
||||
- `VITE_APP_LOG_LEVEL`: Log level (none, error, warn, debug, info)
|
||||
|
||||
Start the frontend:
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
The client will run at `http://localhost:5173`.
|
||||
|
||||
#### Step 5: Access the Application
|
||||
|
||||
Open your browser and navigate to:
|
||||
|
||||
- **Frontend**: http://localhost:5173
|
||||
- **Backend API**: http://localhost:52345
|
||||
- **API Documentation**: http://localhost:52345/api-docs
|
||||
|
||||
#### Managing Docker Containers
|
||||
|
||||
Stop containers:
|
||||
|
||||
```bash
|
||||
docker stop uptime_database_mongo
|
||||
```
|
||||
|
||||
Start containers:
|
||||
|
||||
```bash
|
||||
docker start uptime_database_mongo
|
||||
```
|
||||
|
||||
Remove containers (if needed):
|
||||
|
||||
```bash
|
||||
docker rm uptime_database_mongo
|
||||
```
|
||||
|
||||
#### Troubleshooting
|
||||
|
||||
**Port already in use:**
|
||||
|
||||
- Check if another service is using ports 5173, 52345, 27017, or 6379
|
||||
- Stop the conflicting service or change the port in `.env` files
|
||||
|
||||
**MongoDB connection issues:**
|
||||
|
||||
- Verify container is running: `docker ps`
|
||||
- Check container logs: `docker logs uptime_database_mongo`
|
||||
|
||||
**Module not found errors:**
|
||||
|
||||
- Ensure you ran `npm install` in both `client` and `server` directories
|
||||
|
||||
**Need more help?**
|
||||
|
||||
- Check the [full documentation](https://docs.checkmate.so)
|
||||
- Ask on [Discord](https://discord.com/invite/NAb6H3UTjK)
|
||||
|
||||
### Start contributing code?
|
||||
|
||||
1. Pick or open an issue (check `good-first-issue`s first)
|
||||
2. (optional but highly suggested) Read a detailed structure of [Checkmate](https://deepwiki.com/bluewave-labs/Checkmate) if you would like to deep dive into the architecture.
|
||||
3. Ask to be assigned. If there is alrady someone assigned and it's been more than 7 days, you can raise the flag and ask to be assigned as well.
|
||||
3. Ask to be assigned. If there is already someone assigned and it's been more than 7 days, you can raise the flag and ask to be assigned as well.
|
||||
4. Create a branch from `develop`.
|
||||
5. Write your code.
|
||||
6. Run and test locally.
|
||||
@@ -75,6 +231,7 @@ Docs live in [checkmate-documentation](https://github.com/bluewave-labs/checkmat
|
||||
### Help with translations?
|
||||
|
||||
We use [PoEditor](https://poeditor.com) for translations. You can:
|
||||
|
||||
- [Sign up and join your language team](https://poeditor.com/join/project/lRUoGZFCsJ).
|
||||
- Translate UI strings.
|
||||
- Ask questions on Discord in the relevant #translations channel.
|
||||
@@ -84,6 +241,7 @@ Make sure all new UI strings in code use `t('key')`.
|
||||
### Submit a pull request?
|
||||
|
||||
Follow the [pull request checklist](#pull-request-checklist). Your PR should:
|
||||
|
||||
- Be focused on one issue.
|
||||
- Be tested locally.
|
||||
- Use our linting and translation rules.
|
||||
@@ -123,7 +281,6 @@ If one or more of these are missing, we may ask you to update your pull request
|
||||
|
||||
## Branching model
|
||||
|
||||
|
||||
- Code contributions should go to the `develop` branch.
|
||||
- `master` is used for stable releases.
|
||||
- Use descriptive branch names, like `fix/login-error` or `feat/add-alerts`.
|
||||
@@ -137,13 +294,10 @@ If one or more of these are missing, we may ask you to update your pull request
|
||||
|
||||
## Thank you
|
||||
|
||||
Thanks for making Checkmate better. We mean it. Whether it’s your first pull request or your 50th, we’re excited to build with you.
|
||||
Thanks for making Checkmate better. We mean it. Whether it's your first pull request or your 50th, we're excited to build with you.
|
||||
|
||||
|
||||
PS: feel free to introduce yourself on [Discord](https://discord.gg/YOUR-DISCORD-LINK) and say hi.
|
||||
PS: feel free to introduce yourself on [Discord](https://discord.gg/NAb6H3UTjK) and say hi.
|
||||
|
||||
-- Checkmate team
|
||||
|
||||
Also make sure you read the [document about how to make a good pull request](/PULLREQUESTS.md).
|
||||
|
||||
|
||||
+172
@@ -0,0 +1,172 @@
|
||||
<p align=center> <a href="https://trendshift.io/repositories/12443" target="_blank"><img src="https://trendshift.io/api/badge/repositories/12443" alt="bluewave-labs%2Fcheckmate | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a></p>
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
[](https://www.bestpractices.dev/projects/9901)
|
||||
[](https://deepwiki.com/bluewave-labs/checkmate)
|
||||
|
||||
<h1 align="center"><a href="https://bluewavelabs.ca" target="_blank">Checkmate</a></h1>
|
||||
|
||||
<p align="center"><strong>Una aplicación de código abierto para monitoreo de infraestructura y tiempo de actividad</strong></p>
|
||||
|
||||
<img width="1660" alt="image" src="https://github.com/user-attachments/assets/b748f36d-a271-4965-ad0a-18bf153bbee7" />
|
||||
|
||||
Este repositorio contiene tanto el frontend como el backend de Checkmate, una herramienta de monitoreo de código abierto y autoalojada para rastrear hardware de servidores, tiempo de actividad, tiempos de respuesta e incidentes en tiempo real con visualizaciones atractivas. Checkmate revisa regularmente si un servidor o sitio web es accesible y funciona de manera óptima, proporcionando alertas e informes en tiempo real sobre la disponibilidad, el tiempo de inactividad y el tiempo de respuesta de los servicios monitoreados.
|
||||
|
||||
Checkmate también tiene un agente llamado [Capture](https://github.com/bluewave-labs/capture), para recuperar datos de servidores remotos. Aunque Capture no es obligatorio para ejecutar Checkmate, proporciona información adicional sobre el estado de la CPU, RAM, disco y temperatura de tus servidores.
|
||||
|
||||
Checkmate ha sido probado con más de 1000 monitores activos sin problemas ni cuellos de botella de rendimiento.
|
||||
|
||||
**Si deseas patrocinar una función, [visita este enlace](https://checkmate.so/sponsored-features).**
|
||||
|
||||
## 📚 Tabla de contenidos
|
||||
|
||||
- [📦 Demo](#demo)
|
||||
- [🔗 Guía del usuario](#guía-del-usuario)
|
||||
- [🛠️ Instalación](#instalación)
|
||||
- [🏁 Traducciones](#traducciones)
|
||||
- [🚀 Rendimiento](#rendimiento)
|
||||
- [💚 Preguntas e ideas](#preguntas-e-ideas)
|
||||
- [🧩 Características](#características)
|
||||
- [🏗️ Capturas de pantalla](#capturas-de-pantalla)
|
||||
- [🏗️ Tecnologías](#tecnologías)
|
||||
- [🔗 Enlaces útiles](#enlaces-útiles)
|
||||
- [🤝 Contribuciones](#contribuciones)
|
||||
- [💰 Patrocinadores](#patrocinadores)
|
||||
|
||||
...
|
||||
|
||||
**[Texto truncado para mantener la longitud del mensaje manejable]**
|
||||
|
||||
## Demo
|
||||
|
||||
Puedes ver la última versión de [Checkmate](https://checkmate-demo.bluewavelabs.ca/) en acción. El usuario es uptimedemo@demo.com y la contraseña es Demouser1! (ten en cuenta que actualizamos el servidor de demostración de vez en cuando, así que si no funciona para ti, por favor contáctanos en el canal de Discusiones).
|
||||
|
||||
## Guía del usuario
|
||||
|
||||
Las instrucciones de uso se pueden encontrar [aquí](https://docs.checkmate.so/checkmate-2.1). Todavía está en desarrollo y parte de la información puede estar desactualizada ya que continuamente añadimos funciones cada semana. ¡Ten por seguro que estamos haciendo lo mejor posible! :)
|
||||
|
||||
## Instalación
|
||||
|
||||
Consulta las instrucciones de instalación en el [portal de documentación de Checkmate](https://docs.checkmate.so/checkmate-2.1/users-guide/quickstart).
|
||||
|
||||
Alternativamente, también puedes usar [Coolify](https://coolify.io/), [Elestio](https://elest.io/open-source/checkmate), [K8s](./charts/helm/checkmate/INSTALLATION.md) o [Pikapods](https://www.pikapods.com/) para desplegar rápidamente una instancia de Checkmate. Si deseas monitorear tu infraestructura de servidores, necesitarás el agente [Capture](https://github.com/bluewave-labs/capture). El repositorio de Capture también contiene las instrucciones de instalación.
|
||||
|
||||
## Traducciones
|
||||
|
||||
Si deseas usar Checkmate en tu idioma, por favor [ve a esta página](https://poeditor.com/join/project/lRUoGZFCsJ) y regístrate para el idioma al que te gustaría traducir Checkmate.
|
||||
|
||||
## Rendimiento
|
||||
|
||||
Gracias a extensas optimizaciones, Checkmate opera con un uso de memoria excepcionalmente bajo, requiriendo recursos mínimos de memoria y CPU. Aquí está el uso de memoria de una instancia de Node.js ejecutándose en un servidor que monitorea 323 servidores cada minuto:
|
||||
|
||||

|
||||
|
||||
También puedes ver el consumo de memoria de MongoDB y Redis en el mismo servidor (398Mb y 15Mb) para la misma cantidad de servidores:
|
||||
|
||||

|
||||
|
||||
## Preguntas e Ideas
|
||||
|
||||
Si tienes alguna pregunta, sugerencia o comentario, tienes varias opciones:
|
||||
|
||||
- [Canal de Discord](https://discord.gg/NAb6H3UTjK)
|
||||
- [Discusiones en GitHub](https://github.com/bluewave-labs/bluewave-uptime/discussions)
|
||||
- [Grupo en Reddit](https://www.reddit.com/r/CheckmateMonitoring/)
|
||||
|
||||
¡No dudes en hacer preguntas o compartir tus ideas, nos encantaría saber de ti!
|
||||
|
||||
## Características
|
||||
|
||||
- Completamente de código abierto, desplegable en tus propios servidores o dispositivos personales (por ejemplo, Raspberry Pi 4 o 5)
|
||||
- Monitoreo de sitios web
|
||||
- Monitoreo de velocidad de carga
|
||||
- Monitoreo de infraestructura (memoria, uso de disco, rendimiento de CPU, etc) - requiere el agente [Capture](https://github.com/bluewave-labs/capture)
|
||||
- Monitoreo de Docker
|
||||
- Monitoreo con ping
|
||||
- Monitoreo de certificados SSL
|
||||
- Monitoreo de puertos
|
||||
- Incidentes en una sola vista
|
||||
- Páginas de estado
|
||||
- Notificaciones por correo, Webhooks, Discord, Telegram, Slack
|
||||
- Mantenimiento programado
|
||||
- Monitoreo de consultas JSON
|
||||
- Soporte para múltiples idiomas
|
||||
|
||||
**Hoja de ruta a corto plazo:** ([Milestone 2.2](https://github.com/bluewave-labs/Checkmate/milestone/8))
|
||||
|
||||
- Mejores notificaciones
|
||||
- Monitoreo de red
|
||||
- ...y algunas funciones más
|
||||
|
||||
## Capturas de pantalla
|
||||
|
||||
<p>
|
||||
<img width="1628" alt="image" src="https://github.com/user-attachments/assets/2eff6464-0738-4a32-9312-26e1e8e86275" />
|
||||
</p>
|
||||
<p>
|
||||
<img width="1656" alt="image" src="https://github.com/user-attachments/assets/616c3563-c2a7-4ee4-af6c-7e6068955d1a" />
|
||||
</p>
|
||||
<p>
|
||||
<img width="1652" alt="image" src="https://github.com/user-attachments/assets/7912d7cf-0d0e-4f26-aa5c-2ad7170b5c99" />
|
||||
</p>
|
||||
<p>
|
||||
<img width="1652" alt="image" src="https://github.com/user-attachments/assets/08c2c6ac-3a2f-44d1-a229-d1746a3f9d16" />
|
||||
</p>
|
||||
|
||||
## Tecnologías
|
||||
|
||||
- [ReactJs](https://react.dev/)
|
||||
- [MUI (framework de React)](https://mui.com/)
|
||||
- [Node.js](https://nodejs.org/en)
|
||||
- [MongoDB](https://mongodb.com)
|
||||
- [Recharts](https://recharts.org)
|
||||
- ¡Y muchos otros componentes de código abierto!
|
||||
|
||||
## Enlaces útiles
|
||||
|
||||
- Si deseas apoyarnos, por favor considera darle una ⭐ y haz clic en "watch".
|
||||
- ¿Tienes una pregunta o sugerencia para la hoja de ruta? Revisa nuestro [canal de Discord](https://discord.gg/NAb6H3UTjK) o el foro de [Discusiones](https://github.com/bluewave-labs/checkmate/discussions).
|
||||
- ¿Quieres saber cuándo hay una nueva versión? Usa [Newreleases](https://newreleases.io/), un servicio gratuito para seguir lanzamientos.
|
||||
- Mira un video de instalación y uso de Checkmate [aquí](https://www.youtube.com/watch?v=GfFOc0xHIwY)
|
||||
|
||||
## Contribuciones
|
||||
|
||||
Somos [Alex](http://github.com/ajhollid) (líder de equipo), [Vishnu](http://github.com/vishnusn77), [Mohadeseh](http://github.com/mohicody), [Gorkem](http://github.com/gorkem-bwl/), [Owaise](http://github.com/Owaiseimdad), [Aryaman](https://github.com/Br0wnHammer) y [Mert](https://github.com/mertssmnoglu), ayudando a personas y empresas a monitorear su infraestructura y servidores.
|
||||
|
||||
Nos enorgullecemos de construir conexiones fuertes con contribuyentes de todos los niveles. A pesar de ser un proyecto joven, Checkmate ya ha ganado más de 7000 estrellas y ha atraído a más de 90 contribuyentes de todo el mundo.
|
||||
|
||||
Nuestro repositorio ha sido marcado con estrella por empleados de **Google, Microsoft, Intel, Cisco, Tencent, Electronic Arts, ByteDance, JP Morgan Chase, Deloitte, Accenture, Foxconn, Broadcom, China Telecom, Barclays, Capgemini, Wipro, Cloudflare, Dassault Systèmes y NEC**, ¡así que no te detengas — participa, contribuye y aprende con nosotros!
|
||||
|
||||
Cómo contribuir:
|
||||
|
||||
0. Dale una estrella al repositorio :)
|
||||
1. Revisa la [guía para contribuidores](https://github.com/bluewave-labs/Checkmate/blob/develop/CONTRIBUTING.md). Se anima a los nuevos a revisar las etiquetas `good-first-issue`.
|
||||
2. Consulta la [estructura del proyecto](https://docs.checkmate.so/checkmate-2.1/developers-guide/general-project-structure) y la [visión general](https://bluewavelabs.gitbook.io/checkmate/developers-guide/high-level-overview).
|
||||
3. Lee una estructura detallada de [Checkmate](https://deepwiki.com/bluewave-labs/Checkmate) si deseas profundizar en la arquitectura.
|
||||
4. Abre un issue si crees que has encontrado un error.
|
||||
5. Revisa los issues con la etiqueta `good-first-issue` si eres nuevo.
|
||||
6. Haz un pull request para añadir nuevas funciones, mejoras o correcciones.
|
||||
|
||||
<a href="https://github.com/bluewave-labs/checkmate/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=bluewave-labs/checkmate" />
|
||||
</a>
|
||||
|
||||
[](https://star-history.com/#bluewave-labs/bluewave-uptime&Date)
|
||||
|
||||
## Patrocinadores
|
||||
|
||||
Gracias a [Gitbook](https://gitbook.io/) por darnos una cuenta gratuita para su plataforma de documentación, y a [Poeditor](https://poeditor.com/) por proporcionarnos una cuenta gratuita para servicios de traducción. Si deseas patrocinar Checkmate, por favor envía un correo a hello@bluewavelabs.ca
|
||||
|
||||
Si deseas patrocinar una función, [visita esta página](https://checkmate.so/sponsored-features).
|
||||
|
||||
También puedes revisar otros proyectos de BlueWave orientados a desarrolladores y contribuidores:
|
||||
|
||||
- [VerifyWise](https://github.com/bluewave-labs/verifywise), la primera plataforma de gobernanza de IA de código abierto.
|
||||
- [DataRoom](https://github.com/bluewave-labs/bluewave-dataroom), una aplicación de intercambio de archivos seguro, también conocida como dataroom.
|
||||
- [Guidefox](https://github.com/bluewave-labs/guidefox), una app que ayuda a nuevos usuarios a aprender a usar tu producto mediante pistas, tours, popups y banners.
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
This repository contains both the frontend and the backend of Checkmate, an open-source, self-hosted monitoring tool for tracking server hardware, uptime, response times, and incidents in real-time with beautiful visualizations. Checkmate regularly checks whether a server/website is accessible and performs optimally, providing real-time alerts and reports on the monitored services' availability, downtime, and response time.
|
||||
|
||||
Checkmate also has an agent, called [Capture](https://github.com/bluewave-labs/capture), to retrieve data from remote servers. While Capture is not required to run Checkmate, it provides additional insights about your servers' CPU, RAM, disk, and temperature status.
|
||||
Checkmate also has an agent, called [Capture](https://github.com/bluewave-labs/capture), to retrieve data from remote servers. While Capture is not required to run Checkmate, it provides additional insights about your servers' CPU, RAM, disk, and temperature status. Capture can run on Linux, Windows, Mac, Raspberry Pi, or any device that can run Go.
|
||||
|
||||
Checkmate has been stress-tested with 1000+ active monitors without any particular issues or performance bottlenecks.
|
||||
|
||||
@@ -26,37 +26,46 @@ Checkmate has been stress-tested with 1000+ active monitors without any particul
|
||||
|
||||
## 📚 Table of contents
|
||||
|
||||
- [📦 Demo](#-demo)
|
||||
- [🔗 User's guide](#-users-guide)
|
||||
- [🛠️ Installation](#️-installation)
|
||||
- [🏁 Translations](#-translations)
|
||||
- [🚀 Performance](#-performance)
|
||||
- [💚 Questions & Ideas](#-questions--ideas)
|
||||
- [🧩 Features](#-features)
|
||||
- [🏗️ Screenshots](#-screenshots)
|
||||
- [🏗️ Tech stack](#-tech-stack)
|
||||
- [📦 Demo](#demo)
|
||||
- [🔗 User's guide](#users-guide)
|
||||
- [🛠️ Installation](#installation)
|
||||
- [🏁 Translations](#translations)
|
||||
- [🚀 Performance](#performance)
|
||||
- [💚 Questions & Ideas](#questions--ideas)
|
||||
- [🧩 Features](#features)
|
||||
- [🏗️ Screenshots](#screenshots)
|
||||
- [🏗️ Tech stack](#tech-stack)
|
||||
- [🔗 A few links](#a-few-links)
|
||||
- [🤝 Contributing](#-contributing)
|
||||
- [💰 Our sponsors](#-our-sponsors)
|
||||
- [🤝 Contributing](#contributing)
|
||||
- [💰 Our sponsors](#our-sponsors)
|
||||
|
||||
|
||||
## 📦 Demo
|
||||
## Demo
|
||||
|
||||
You can see the latest build of [Checkmate](https://checkmate-demo.bluewavelabs.ca/) in action. The username is uptimedemo@demo.com and the password is Demouser1! (just a note that we update the demo server from time to time, so if it doesn't work for you, please ping us on the Discussions channel).
|
||||
|
||||
## 🔗 User's guide
|
||||
## User's guide
|
||||
|
||||
Usage instructions can be found [here](https://docs.checkmate.so/checkmate-2.1). It's still WIP and some of the information there might be outdated as we continuously add features weekly. Rest assured, we are doing our best! :)
|
||||
|
||||
## 🛠️ Installation
|
||||
## Installation
|
||||
|
||||
See installation instructions in [Checkmate documentation portal](https://docs.checkmate.so/checkmate-2.1/users-guide/quickstart). Alternatively, you can also use [Coolify](https://coolify.io/), [Elestio](https://elest.io/open-source/checkmate) or [Pikapods](https://www.pikapods.com/) to quickly spin off a Checkmate instance. If you would like to monitor your server infrastructure, you'll need [Capture agent](https://github.com/bluewave-labs/capture). Capture repository also contains the installation instructions.
|
||||
See installation instructions in [Checkmate documentation portal](https://docs.checkmate.so/checkmate-2.1/users-guide/quickstart).
|
||||
|
||||
## 🏁 Translations
|
||||
Alternatively, you can also use [Coolify](https://coolify.io/), [Elestio](https://elest.io/open-source/checkmate), [K8s](./charts/helm/checkmate/INSTALLATION.md), [Sive Host](https://sive.host) (South Africa) or [Pikapods](https://www.pikapods.com/) to quickly spin off a Checkmate instance. If you would like to monitor your server infrastructure, you'll need [Capture agent](https://github.com/bluewave-labs/capture). Capture repository also contains the installation instructions.
|
||||
|
||||
### Using a Custom CA
|
||||
|
||||
If you need to monitor internal HTTPS endpoints with certificates from private Certificate Authorities (like Smallstep), see our [Custom CA Trust Guide](./docs/custom-ca-trust.md) for Docker configuration options.
|
||||
|
||||
For more documentation, see the [docs directory](./docs/).
|
||||
|
||||
|
||||
## Translations
|
||||
|
||||
If you would like to use Checkmate in your language, please [go to this page](https://poeditor.com/join/project/lRUoGZFCsJ) and register for the language you would like to translate Checkmate to.
|
||||
|
||||
## 🚀 Performance
|
||||
## Performance
|
||||
|
||||
Thanks to extensive optimizations, Checkmate operates with an exceptionally small memory footprint, requiring minimal memory and CPU resources. Here’s the memory usage of a Node.js instance running on a server that monitors 323 servers every minute:
|
||||
|
||||
@@ -66,34 +75,44 @@ You can see the memory footprint of MongoDB and Redis on the same server (398Mb
|
||||
|
||||

|
||||
|
||||
## 💚 Questions & Ideas
|
||||
## Questions & Ideas
|
||||
|
||||
If you have any questions, suggestions or comments, please use our [Discord channel](https://discord.gg/NAb6H3UTjK). We've also launched our [Discussions](https://github.com/bluewave-labs/bluewave-uptime/discussions) page! Feel free to ask questions or share your ideas—we'd love to hear from you!
|
||||
If you have any questions, suggestions or comments, you have several options:
|
||||
|
||||
## 🧩 Features
|
||||
- [Discord channel](https://discord.gg/NAb6H3UTjK)
|
||||
- [GitHub Discussions](https://github.com/bluewave-labs/bluewave-uptime/discussions)
|
||||
- [Reddit group](https://www.reddit.com/r/CheckmateMonitoring/)
|
||||
|
||||
Feel free to ask questions or share your ideas - we'd love to hear from you!
|
||||
|
||||
## Features
|
||||
|
||||
- Completely open source, deployable on your servers or home devices (e.g Raspberry Pi 4 or 5)
|
||||
- Website monitoring
|
||||
- Page speed monitoring
|
||||
- Infrastructure monitoring (memory, disk usage, CPU performance etc) - requires [Capture](https://github.com/bluewave-labs/capture)
|
||||
- Infrastructure monitoring (memory, disk usage, CPU performance, network etc) - requires [Capture](https://github.com/bluewave-labs/capture) agent
|
||||
- Docker monitoring
|
||||
- Ping monitoring
|
||||
- SSL monitoring
|
||||
- Port monitoring
|
||||
- Game server monitoring (3.0)
|
||||
- Incidents at a glance
|
||||
- Status pages
|
||||
- E-mail, Webhooks, Discord, Telegram, Slack notifications
|
||||
- E-mail, Webhooks, Discord and Slack notifications
|
||||
- Scheduled maintenance
|
||||
- JSON query monitoring
|
||||
- Support for multiple languages
|
||||
- Multi-language support for English, German, Japanese, Portuguese (Brazil), Russian, Turkish, Ukrainian, Vietnamese, Chinese (Traditional, Taiwan)
|
||||
|
||||
**Short term roadmap:** ([Milestone 2.2](https://github.com/bluewave-labs/Checkmate/milestone/8))
|
||||
**Short term roadmap:**
|
||||
|
||||
- Plugins that will help Checkmate get any information from a remote service (e.g database, etc)
|
||||
- Better notifications
|
||||
- Network monitoring
|
||||
- ..and a few more features
|
||||
|
||||
## 🏗️ Screenshots
|
||||
If you would like to sponsor an additional feature, [see this page](https://checkmate.so/sponsored-features).
|
||||
|
||||
## Screenshots
|
||||
|
||||
<p>
|
||||
<img width="1628" alt="image" src="https://github.com/user-attachments/assets/2eff6464-0738-4a32-9312-26e1e8e86275" />
|
||||
@@ -110,7 +129,7 @@ If you have any questions, suggestions or comments, please use our [Discord chan
|
||||
|
||||
|
||||
|
||||
## 🏗️ Tech stack
|
||||
## Tech stack
|
||||
|
||||
- [ReactJs](https://react.dev/)
|
||||
- [MUI (React framework)](https://mui.com/)
|
||||
@@ -126,11 +145,11 @@ If you have any questions, suggestions or comments, please use our [Discord chan
|
||||
- Need a ping when there's a new release? Use [Newreleases](https://newreleases.io/), a free service to track releases.
|
||||
- Watch a Checkmate [installation and usage video](https://www.youtube.com/watch?v=GfFOc0xHIwY)
|
||||
|
||||
## 🤝 Contributing
|
||||
## Contributing
|
||||
|
||||
We are [Alex](http://github.com/ajhollid) (team lead), [Vishnu](http://github.com/vishnusn77), [Mohadeseh](http://github.com/mohicody), [Gorkem](http://github.com/gorkem-bwl/), [Owaise](http://github.com/Owaiseimdad), [Aryaman](https://github.com/Br0wnHammer) and [Mert](https://github.com/mertssmnoglu) helping individuals and businesses monitor their infra and servers.
|
||||
We are [Alex](http://github.com/ajhollid) (team lead), [Gorkem](http://github.com/gorkem-bwl/), [Owaise](http://github.com/Owaiseimdad), [Aryaman](https://github.com/Br0wnHammer), [Mert](https://github.com/mertssmnoglu) and [Karen](https://github.com/karenvicent) helping individuals and businesses monitor their infra and servers.
|
||||
|
||||
We pride ourselves on building strong connections with contributors at every level. Despite being a young project, Checkmate has already earned 6000+ stars and attracted 80+ contributors from around the globe.
|
||||
We pride ourselves on building strong connections with contributors at every level. Despite being a young project, Checkmate has already earned 7000+ stars and attracted 90+ contributors from around the globe.
|
||||
|
||||
Our repo is starred by employees from **Google, Microsoft, Intel, Cisco, Tencent, Electronic Arts, ByteDance, JP Morgan Chase, Deloitte, Accenture, Foxconn, Broadcom, China Telecom, Barclays, Capgemini, Wipro, Cloudflare, Dassault Systèmes and NEC**, so don’t hold back — jump in, contribute and learn with us!
|
||||
|
||||
@@ -150,7 +169,7 @@ Here's how you can contribute:
|
||||
|
||||
[](https://star-history.com/#bluewave-labs/bluewave-uptime&Date)
|
||||
|
||||
## 💰 Our sponsors
|
||||
## Our sponsors
|
||||
|
||||
Thanks to [Gitbook](https://gitbook.io/) for giving us a free tier for their documentation platform, and [Poeditor](https://poeditor.com/) providing us a free account to use their i18n services. If you would like to sponsor Checkmate, please send an email to hello@bluewavelabs.ca
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
.DS_Store
|
||||
.git/
|
||||
.gitignore
|
||||
.bzr/
|
||||
.bzrignore
|
||||
.hg/
|
||||
.hgignore
|
||||
.svn/
|
||||
*.swp
|
||||
*.bak
|
||||
*.tmp
|
||||
*.orig
|
||||
*~
|
||||
.project
|
||||
.idea/
|
||||
*.tmproj
|
||||
.vscode/
|
||||
@@ -0,0 +1,6 @@
|
||||
apiVersion: v2
|
||||
name: checkmate-chart
|
||||
description: A Helm chart for Checkmate App
|
||||
type: application
|
||||
version: 0.1.0
|
||||
appVersion: "2.3"
|
||||
@@ -0,0 +1,39 @@
|
||||
# Kubernetes Installation Guide for Checkmate
|
||||
|
||||
This guide walks you through deploying Checkmate on your Kubernetes cluster using Helm.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- A running Kubernetes cluster
|
||||
- Helm CLI installed and configured
|
||||
- `kubectl` configured to access your cluster
|
||||
|
||||
## Steps
|
||||
|
||||
### 1. Clone the repo and navigate to the Helm chart
|
||||
|
||||
```bash
|
||||
git clone https://github.com/bluewave-labs/checkmate.git
|
||||
cd checkmate/charts/helm/checkmate
|
||||
```
|
||||
|
||||
### 2. Customize values.yaml
|
||||
Edit `values.yaml` to update:
|
||||
- `client.ingress.host` and `server.ingress.host` with your domain names
|
||||
- `server.protocol` (usually http or https)
|
||||
- Secrets under the `secrets` section (`JWT_SECRET`, email credentials, API keys, etc.) — replace all change_me values
|
||||
|
||||
### 3. Deploy the Helm chart
|
||||
```bash
|
||||
helm install checkmate ./charts/helm/checkmate
|
||||
```
|
||||
This will deploy the client, server, MongoDB, and Redis components.
|
||||
|
||||
### 4. Verify the deployment
|
||||
Check pods and services:
|
||||
```bash
|
||||
kubectl get pods
|
||||
kubectl get svc
|
||||
```
|
||||
|
||||
Once all pods are `Running` and `Ready`, you can access Checkmate via the configured ingress hosts.
|
||||
@@ -0,0 +1,12 @@
|
||||
{{- if eq .Values.client.ingress.host "change_me" }}
|
||||
{{- fail "client.ingress.host must be overridden and not set to 'change_me'" }}
|
||||
{{- end }}
|
||||
|
||||
{{- if eq .Values.server.ingress.host "change_me" }}
|
||||
{{- fail "server.ingress.host must be overridden and not set to 'change_me'" }}
|
||||
{{- end }}
|
||||
|
||||
{{- $protocol := .Values.server.protocol }}
|
||||
{{- if not (or (eq $protocol "http") (eq $protocol "https")) }}
|
||||
{{- fail "server.protocol must be either 'http' or 'https'" }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,44 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: checkmate-client
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: checkmate-client
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: checkmate-client
|
||||
spec:
|
||||
{{- with .Values.client.affinity }}
|
||||
affinity:
|
||||
{{- tpl ( . | toYaml) $ | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.client.tolerations }}
|
||||
tolerations:
|
||||
{{- tpl ( . | toYaml) $ | nindent 8 }}
|
||||
{{- end }}
|
||||
containers:
|
||||
- name: client
|
||||
image: {{ .Values.client.image }}
|
||||
ports:
|
||||
- containerPort: {{ .Values.client.port }}
|
||||
env:
|
||||
- name: UPTIME_APP_API_BASE_URL
|
||||
value: "{{ .Values.server.protocol }}://{{ .Values.server.ingress.host }}/api/v1"
|
||||
- name: UPTIME_APP_CLIENT_HOST
|
||||
value: "{{ .Values.client.protocol }}://{{ .Values.client.ingress.host }}"
|
||||
volumeMounts:
|
||||
- name: config-volume
|
||||
mountPath: /etc/nginx/conf.d/default.conf
|
||||
subPath: default.conf
|
||||
{{- with .Values.client.resources }}
|
||||
resources:
|
||||
{{- tpl ( . | toYaml) $ | nindent 12 }}
|
||||
{{- end }}
|
||||
volumes:
|
||||
- name: config-volume
|
||||
configMap:
|
||||
name: checkmate-server-nginx-cm
|
||||
@@ -0,0 +1,25 @@
|
||||
{{- if .Values.client.ingress.enabled }}
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: checkmate-client-ingress
|
||||
{{- if .Values.client.ingress.annotations }}
|
||||
annotations:
|
||||
{{- range $key, $value := .Values.client.ingress.annotations }}
|
||||
{{ $key }}: {{ $value | quote }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
spec:
|
||||
ingressClassName: {{ .Values.client.ingress.className }}
|
||||
rules:
|
||||
- host: {{ .Values.client.ingress.host }}
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: checkmate-client
|
||||
port:
|
||||
number: {{ .Values.client.port }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,9 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: checkmate-client
|
||||
spec:
|
||||
selector:
|
||||
app: checkmate-client
|
||||
ports:
|
||||
- port: {{ .Values.client.port }}
|
||||
@@ -0,0 +1,9 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: checkmate-mongodb
|
||||
spec:
|
||||
selector:
|
||||
app: checkmate-mongodb
|
||||
ports:
|
||||
- port: {{ .Values.mongodb.port }}
|
||||
@@ -0,0 +1,44 @@
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: checkmate-mongodb
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: checkmate-mongodb
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: checkmate-mongodb
|
||||
spec:
|
||||
{{- with .Values.mongodb.affinity }}
|
||||
affinity:
|
||||
{{- tpl ( . | toYaml) $ | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.mongodb.tolerations }}
|
||||
tolerations:
|
||||
{{- tpl ( . | toYaml) $ | nindent 8 }}
|
||||
{{- end }}
|
||||
containers:
|
||||
- name: mongodb
|
||||
image: {{ .Values.mongodb.image }}
|
||||
ports:
|
||||
- containerPort: {{ .Values.mongodb.port }}
|
||||
command: ["mongod", "--quiet", "--bind_ip_all"]
|
||||
volumeMounts:
|
||||
- name: checkmate-mongo-persistent-storage
|
||||
mountPath: /data/db
|
||||
{{- with .Values.mongodb.resources }}
|
||||
resources:
|
||||
{{- tpl ( . | toYaml) $ | nindent 12 }}
|
||||
{{- end }}
|
||||
volumeClaimTemplates:
|
||||
- metadata:
|
||||
name: checkmate-mongo-persistent-storage
|
||||
spec:
|
||||
storageClassName: "gp3"
|
||||
accessModes: ["ReadWriteOnce"]
|
||||
resources:
|
||||
requests:
|
||||
storage: {{ .Values.persistence.mongodbSize }}
|
||||
@@ -0,0 +1,11 @@
|
||||
{{- if .Values.redis.enabled }}
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: checkmate-redis
|
||||
spec:
|
||||
selector:
|
||||
app: checkmate-redis
|
||||
ports:
|
||||
- port: {{ .Values.redis.port }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,33 @@
|
||||
{{- if .Values.redis.enabled }}
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: checkmate-redis
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: checkmate-redis
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: checkmate-redis
|
||||
spec:
|
||||
containers:
|
||||
- name: redis
|
||||
image: {{ .Values.redis.image }}
|
||||
ports:
|
||||
- containerPort: {{ .Values.redis.port }}
|
||||
volumeMounts:
|
||||
- name: redis-data
|
||||
mountPath: /data
|
||||
volumeClaimTemplates:
|
||||
- metadata:
|
||||
name: checkmate-redis-persistent-storage
|
||||
spec:
|
||||
storageClassName: "gp3"
|
||||
accessModes: ["ReadWriteOnce"]
|
||||
resources:
|
||||
requests:
|
||||
storage: {{ .Values.persistence.redisSize }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,15 @@
|
||||
{{- $secrets := .Values.secrets }}
|
||||
|
||||
{{- if or (not $secrets.JWT_SECRET) (eq $secrets.JWT_SECRET "change_me") }}
|
||||
{{- fail "secrets.JWT_SECRET must be overridden and cannot be 'change_me'" }}
|
||||
{{- end }}
|
||||
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: checkmate-secrets
|
||||
type: Opaque
|
||||
stringData:
|
||||
{{- range $key, $value := $secrets }}
|
||||
{{ $key }}: {{ $value | quote }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,37 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: checkmate-server
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: checkmate-server
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: checkmate-server
|
||||
spec:
|
||||
{{- with .Values.server.affinity }}
|
||||
affinity:
|
||||
{{- tpl ( . | toYaml) $ | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.server.tolerations }}
|
||||
tolerations:
|
||||
{{- tpl ( . | toYaml) $ | nindent 8 }}
|
||||
{{- end }}
|
||||
containers:
|
||||
- name: server
|
||||
image: {{ .Values.server.image }}
|
||||
ports:
|
||||
- containerPort: {{ .Values.server.port }}
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: checkmate-secrets
|
||||
{{- with .Values.server.resources }}
|
||||
resources:
|
||||
{{- tpl ( . | toYaml) $ | nindent 12 }}
|
||||
{{- end }}
|
||||
env:
|
||||
- name: CLIENT_HOST
|
||||
value: "{{ .Values.client.protocol }}://{{ .Values.client.ingress.host }}"
|
||||
@@ -0,0 +1,32 @@
|
||||
{{- if .Values.server.ingress.enabled }}
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: checkmate-server-ingress
|
||||
{{- if .Values.server.ingress.annotations }}
|
||||
annotations:
|
||||
{{- range $key, $value := .Values.server.ingress.annotations }}
|
||||
{{ $key }}: {{ $value | quote }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{/*#annotations:
|
||||
#nginx.ingress.kubernetes.io/rewrite-target: /
|
||||
#nginx.ingress.kubernetes.io/enable-cors: "true"
|
||||
#nginx.ingress.kubernetes.io/cors-allow-origin: "http://{{ .Values.client.ingress.host }},https://{{ .Values.client.ingress.host }}"
|
||||
#nginx.ingress.kubernetes.io/cors-allow-methods: "GET, PUT, POST, DELETE, PATCH, OPTIONS"
|
||||
#nginx.ingress.kubernetes.io/cors-allow-headers: "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization"
|
||||
#nginx.ingress.kubernetes.io/cors-allow-credentials: "true"*/}}
|
||||
spec:
|
||||
ingressClassName: {{ .Values.server.ingress.className }}
|
||||
rules:
|
||||
- host: {{ .Values.server.ingress.host }}
|
||||
http:
|
||||
paths:
|
||||
- path: /api/v1
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: checkmate-server
|
||||
port:
|
||||
number: {{ .Values.server.port }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,41 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: checkmate-server-nginx-cm
|
||||
data:
|
||||
default.conf: |
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
|
||||
server_name checkmate-demo.bluewavelabs.ca;
|
||||
server_tokens off;
|
||||
|
||||
location /.well-known/acme-challenge/ {
|
||||
root /var/www/certbot;
|
||||
}
|
||||
|
||||
location / {
|
||||
root /usr/share/nginx/html;
|
||||
index index.html index.htm;
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
# location /api/ {
|
||||
# proxy_pass http://{{ .Values.server.ingress.host }}:5000/api/;
|
||||
# proxy_http_version 1.1;
|
||||
# proxy_set_header Host $host;
|
||||
# proxy_set_header X-Real-IP $remote_addr;
|
||||
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
# proxy_set_header X-Forwarded-Proto $scheme;
|
||||
# }
|
||||
|
||||
location /api-docs/ {
|
||||
proxy_pass http://{{ .Values.server.ingress.host }}:5000/api-docs/;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: checkmate-server
|
||||
spec:
|
||||
selector:
|
||||
app: checkmate-server
|
||||
ports:
|
||||
- port: {{ .Values.server.port }}
|
||||
@@ -0,0 +1,48 @@
|
||||
client:
|
||||
image: ghcr.io/bluewave-labs/checkmate-client:v3.2.0
|
||||
port: 80
|
||||
protocol: http
|
||||
ingress:
|
||||
enabled: true
|
||||
host: change_me
|
||||
className: nginx
|
||||
annotations: {}
|
||||
|
||||
server:
|
||||
image: ghcr.io/bluewave-labs/checkmate-backend:v3.2.0
|
||||
port: 52345
|
||||
protocol: http
|
||||
ingress:
|
||||
enabled: true
|
||||
host: change_me
|
||||
className: nginx
|
||||
annotations: {}
|
||||
|
||||
redis:
|
||||
enabled: false
|
||||
image: redis:7.2
|
||||
port: 6379
|
||||
|
||||
mongodb:
|
||||
image: ghcr.io/bluewave-labs/checkmate-mongo:v3.2.0
|
||||
port: 27017
|
||||
|
||||
secrets:
|
||||
JWT_SECRET: change_me
|
||||
# REFRESH_TOKEN_SECRET: change_me
|
||||
# SYSTEM_EMAIL_ADDRESS: test@example.com
|
||||
# SYSTEM_EMAIL_PASSWORD: change_me
|
||||
# SYSTEM_EMAIL_HOST: smtp.example.com
|
||||
# SYSTEM_EMAIL_PORT: "587"
|
||||
# PAGESPEED_API_KEY: change_me
|
||||
DB_CONNECTION_STRING: mongodb://checkmate-mongodb.namespace.svc:27017/uptime_db
|
||||
CLIENT_HOST: change_me
|
||||
# REDIS_HOST: redis
|
||||
# REDIS_PORT: "6379"
|
||||
# DB_TYPE: MongoDB
|
||||
# TOKEN_TTL: 99d
|
||||
# REFRESH_TOKEN_TTL: 99d
|
||||
|
||||
persistence:
|
||||
mongodbSize: 5Gi
|
||||
redisSize: 1Gi
|
||||
@@ -1,3 +1,4 @@
|
||||
VITE_APP_API_BASE_URL=UPTIME_APP_API_BASE_URL
|
||||
VITE_APP_API_V2_BASE_URL=UPTIME_APP_API_V2_BASE_URL
|
||||
VITE_APP_CLIENT_HOST=UPTIME_APP_CLIENT_HOST
|
||||
VITE_APP_LOG_LEVEL=UPTIME_APP_LOG_LEVEL
|
||||
Generated
+161
-628
@@ -11,6 +11,7 @@
|
||||
"@emotion/react": "^11.13.3",
|
||||
"@emotion/styled": "^11.13.0",
|
||||
"@hello-pangea/dnd": "^18.0.0",
|
||||
"@hookform/resolvers": "5.2.2",
|
||||
"@mui/icons-material": "6.4.11",
|
||||
"@mui/lab": "6.0.0-dev.240424162023-9968b4889d",
|
||||
"@mui/material": "6.4.11",
|
||||
@@ -21,11 +22,14 @@
|
||||
"dayjs": "1.11.13",
|
||||
"flag-icons": "7.3.2",
|
||||
"html2canvas": "^1.4.1",
|
||||
"i18next": "^24.2.2",
|
||||
"human-interval": "2.0.1",
|
||||
"i18next": "25.4.2",
|
||||
"joi": "17.13.3",
|
||||
"mui-color-input": "^6.0.0",
|
||||
"pretty-ms": "9.3.0",
|
||||
"react": "18.3.1",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-hook-form": "7.63.0",
|
||||
"react-i18next": "^15.4.0",
|
||||
"react-icons": "5.5.0",
|
||||
"react-redux": "9.2.0",
|
||||
@@ -34,9 +38,12 @@
|
||||
"react-toastify": "^10.0.5",
|
||||
"recharts": "2.15.2",
|
||||
"redux-persist": "6.0.0",
|
||||
"vite-plugin-svgr": "^4.2.0"
|
||||
"swr": "2.3.6",
|
||||
"vite-plugin-svgr": "^4.2.0",
|
||||
"zod": "4.1.11"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "24.5.2",
|
||||
"@types/react": "^18.2.66",
|
||||
"@types/react-dom": "^18.2.22",
|
||||
"@vitejs/plugin-react": "^4.2.1",
|
||||
@@ -45,10 +52,8 @@
|
||||
"eslint-plugin-react-hooks": "^5.0.0",
|
||||
"eslint-plugin-react-refresh": "^0.4.6",
|
||||
"prettier": "^3.3.3",
|
||||
"vite": "6.3.5"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@rollup/rollup-linux-arm64-musl": "4.41.0"
|
||||
"typescript": "5.9.3",
|
||||
"vite": "6.3.6"
|
||||
}
|
||||
},
|
||||
"node_modules/@ampproject/remapping": {
|
||||
@@ -283,9 +288,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/runtime": {
|
||||
"version": "7.27.1",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.1.tgz",
|
||||
"integrity": "sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==",
|
||||
"version": "7.28.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.3.tgz",
|
||||
"integrity": "sha512-9uIQ10o0WGdpP6GDhXcdOJPJuDgFtIDtN/9+ArJQ2NAfAmiuhTQdzkaTGR33v43GYS2UrSA0eX2pPPHoFVvpxA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
@@ -491,262 +496,6 @@
|
||||
"integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@esbuild/aix-ppc64": {
|
||||
"version": "0.25.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.5.tgz",
|
||||
"integrity": "sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"aix"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-arm": {
|
||||
"version": "0.25.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.5.tgz",
|
||||
"integrity": "sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-arm64": {
|
||||
"version": "0.25.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.5.tgz",
|
||||
"integrity": "sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-x64": {
|
||||
"version": "0.25.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.5.tgz",
|
||||
"integrity": "sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/darwin-arm64": {
|
||||
"version": "0.25.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.5.tgz",
|
||||
"integrity": "sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/darwin-x64": {
|
||||
"version": "0.25.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.5.tgz",
|
||||
"integrity": "sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/freebsd-arm64": {
|
||||
"version": "0.25.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.5.tgz",
|
||||
"integrity": "sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/freebsd-x64": {
|
||||
"version": "0.25.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.5.tgz",
|
||||
"integrity": "sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-arm": {
|
||||
"version": "0.25.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.5.tgz",
|
||||
"integrity": "sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-arm64": {
|
||||
"version": "0.25.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.5.tgz",
|
||||
"integrity": "sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-ia32": {
|
||||
"version": "0.25.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.5.tgz",
|
||||
"integrity": "sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-loong64": {
|
||||
"version": "0.25.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.5.tgz",
|
||||
"integrity": "sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==",
|
||||
"cpu": [
|
||||
"loong64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-mips64el": {
|
||||
"version": "0.25.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.5.tgz",
|
||||
"integrity": "sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==",
|
||||
"cpu": [
|
||||
"mips64el"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-ppc64": {
|
||||
"version": "0.25.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.5.tgz",
|
||||
"integrity": "sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-riscv64": {
|
||||
"version": "0.25.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.5.tgz",
|
||||
"integrity": "sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-s390x": {
|
||||
"version": "0.25.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.5.tgz",
|
||||
"integrity": "sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-x64": {
|
||||
"version": "0.25.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.5.tgz",
|
||||
@@ -763,134 +512,6 @@
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/netbsd-arm64": {
|
||||
"version": "0.25.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.5.tgz",
|
||||
"integrity": "sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"netbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/netbsd-x64": {
|
||||
"version": "0.25.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.5.tgz",
|
||||
"integrity": "sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"netbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/openbsd-arm64": {
|
||||
"version": "0.25.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.5.tgz",
|
||||
"integrity": "sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/openbsd-x64": {
|
||||
"version": "0.25.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.5.tgz",
|
||||
"integrity": "sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/sunos-x64": {
|
||||
"version": "0.25.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.5.tgz",
|
||||
"integrity": "sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"sunos"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-arm64": {
|
||||
"version": "0.25.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.5.tgz",
|
||||
"integrity": "sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-ia32": {
|
||||
"version": "0.25.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.5.tgz",
|
||||
"integrity": "sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-x64": {
|
||||
"version": "0.25.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.5.tgz",
|
||||
"integrity": "sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint-community/eslint-utils": {
|
||||
"version": "4.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz",
|
||||
@@ -1040,6 +661,18 @@
|
||||
"react-dom": "^18.0.0 || ^19.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@hookform/resolvers": {
|
||||
"version": "5.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-5.2.2.tgz",
|
||||
"integrity": "sha512-A/IxlMLShx3KjV/HeTcTfaMxdwy690+L/ZADoeaTltLx+CVuzkeVIPuybK3jrRfw7YZnmdKsVVHAlEPIAEUNlA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@standard-schema/utils": "^0.3.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react-hook-form": "^7.55.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@humanwhocodes/config-array": {
|
||||
"version": "0.13.0",
|
||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz",
|
||||
@@ -2063,123 +1696,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@rollup/rollup-android-arm-eabi": {
|
||||
"version": "4.41.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.41.0.tgz",
|
||||
"integrity": "sha512-KxN+zCjOYHGwCl4UCtSfZ6jrq/qi88JDUtiEFk8LELEHq2Egfc/FgW+jItZiOLRuQfb/3xJSgFuNPC9jzggX+A==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-android-arm64": {
|
||||
"version": "4.41.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.41.0.tgz",
|
||||
"integrity": "sha512-yDvqx3lWlcugozax3DItKJI5j05B0d4Kvnjx+5mwiUpWramVvmAByYigMplaoAQ3pvdprGCTCE03eduqE/8mPQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-darwin-arm64": {
|
||||
"version": "4.41.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.41.0.tgz",
|
||||
"integrity": "sha512-2KOU574vD3gzcPSjxO0eyR5iWlnxxtmW1F5CkNOHmMlueKNCQkxR6+ekgWyVnz6zaZihpUNkGxjsYrkTJKhkaw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-darwin-x64": {
|
||||
"version": "4.41.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.41.0.tgz",
|
||||
"integrity": "sha512-gE5ACNSxHcEZyP2BA9TuTakfZvULEW4YAOtxl/A/YDbIir/wPKukde0BNPlnBiP88ecaN4BJI2TtAd+HKuZPQQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-freebsd-arm64": {
|
||||
"version": "4.41.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.41.0.tgz",
|
||||
"integrity": "sha512-GSxU6r5HnWij7FoSo7cZg3l5GPg4HFLkzsFFh0N/b16q5buW1NAWuCJ+HMtIdUEi6XF0qH+hN0TEd78laRp7Dg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-freebsd-x64": {
|
||||
"version": "4.41.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.41.0.tgz",
|
||||
"integrity": "sha512-KGiGKGDg8qLRyOWmk6IeiHJzsN/OYxO6nSbT0Vj4MwjS2XQy/5emsmtoqLAabqrohbgLWJ5GV3s/ljdrIr8Qjg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
|
||||
"version": "4.41.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.41.0.tgz",
|
||||
"integrity": "sha512-46OzWeqEVQyX3N2/QdiU/CMXYDH/lSHpgfBkuhl3igpZiaB3ZIfSjKuOnybFVBQzjsLwkus2mjaESy8H41SzvA==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
|
||||
"version": "4.41.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.41.0.tgz",
|
||||
"integrity": "sha512-lfgW3KtQP4YauqdPpcUZHPcqQXmTmH4nYU0cplNeW583CMkAGjtImw4PKli09NFi2iQgChk4e9erkwlfYem6Lg==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm64-gnu": {
|
||||
"version": "4.41.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.41.0.tgz",
|
||||
"integrity": "sha512-nn8mEyzMbdEJzT7cwxgObuwviMx6kPRxzYiOl6o/o+ChQq23gfdlZcUNnt89lPhhz3BYsZ72rp0rxNqBSfqlqw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm64-musl": {
|
||||
"version": "4.41.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.41.0.tgz",
|
||||
@@ -2193,71 +1709,6 @@
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-loongarch64-gnu": {
|
||||
"version": "4.41.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.41.0.tgz",
|
||||
"integrity": "sha512-WbnJaxPv1gPIm6S8O/Wg+wfE/OzGSXlBMbOe4ie+zMyykMOeqmgD1BhPxZQuDqwUN+0T/xOFtL2RUWBspnZj3w==",
|
||||
"cpu": [
|
||||
"loong64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
|
||||
"version": "4.41.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.41.0.tgz",
|
||||
"integrity": "sha512-eRDWR5t67/b2g8Q/S8XPi0YdbKcCs4WQ8vklNnUYLaSWF+Cbv2axZsp4jni6/j7eKvMLYCYdcsv8dcU+a6QNFg==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
|
||||
"version": "4.41.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.41.0.tgz",
|
||||
"integrity": "sha512-TWrZb6GF5jsEKG7T1IHwlLMDRy2f3DPqYldmIhnA2DVqvvhY2Ai184vZGgahRrg8k9UBWoSlHv+suRfTN7Ua4A==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-riscv64-musl": {
|
||||
"version": "4.41.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.41.0.tgz",
|
||||
"integrity": "sha512-ieQljaZKuJpmWvd8gW87ZmSFwid6AxMDk5bhONJ57U8zT77zpZ/TPKkU9HpnnFrM4zsgr4kiGuzbIbZTGi7u9A==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-s390x-gnu": {
|
||||
"version": "4.41.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.41.0.tgz",
|
||||
"integrity": "sha512-/L3pW48SxrWAlVsKCN0dGLB2bi8Nv8pr5S5ocSM+S0XCn5RCVCXqi8GVtHFsOBBCSeR+u9brV2zno5+mg3S4Aw==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-x64-gnu": {
|
||||
"version": "4.41.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.41.0.tgz",
|
||||
@@ -2284,45 +1735,6 @@
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-arm64-msvc": {
|
||||
"version": "4.41.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.41.0.tgz",
|
||||
"integrity": "sha512-4yodtcOrFHpbomJGVEqZ8fzD4kfBeCbpsUy5Pqk4RluXOdsWdjLnjhiKy2w3qzcASWd04fp52Xz7JKarVJ5BTg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-ia32-msvc": {
|
||||
"version": "4.41.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.41.0.tgz",
|
||||
"integrity": "sha512-tmazCrAsKzdkXssEc65zIE1oC6xPHwfy9d5Ta25SRCDOZS+I6RypVVShWALNuU9bxIfGA0aqrmzlzoM5wO5SPQ==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-x64-msvc": {
|
||||
"version": "4.41.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.41.0.tgz",
|
||||
"integrity": "sha512-h1J+Yzjo/X+0EAvR2kIXJDuTuyT7drc+t2ALY0nIcGPbTatNOf0VWdhEA2Z4AAjv6X1NJV7SYo5oCTYRJhSlVA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@sideway/address": {
|
||||
"version": "4.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz",
|
||||
@@ -2715,6 +2127,16 @@
|
||||
"integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "24.5.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.5.2.tgz",
|
||||
"integrity": "sha512-FYxk1I7wPv3K2XBaoyH2cTnocQEu8AOZ60hPbsyukMPLv5/5qr7V1i8PLHdl6Zf87I+xZXFvPCXYjiTFq+YSDQ==",
|
||||
"devOptional": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~7.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/parse-json": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz",
|
||||
@@ -3030,13 +2452,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/axios": {
|
||||
"version": "1.9.0",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.9.0.tgz",
|
||||
"integrity": "sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==",
|
||||
"version": "1.12.2",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.12.2.tgz",
|
||||
"integrity": "sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.15.6",
|
||||
"form-data": "^4.0.0",
|
||||
"form-data": "^4.0.4",
|
||||
"proxy-from-env": "^1.1.0"
|
||||
}
|
||||
},
|
||||
@@ -3599,6 +3021,15 @@
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/dequal": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
|
||||
"integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/doctrine": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
|
||||
@@ -4342,14 +3773,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/form-data": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz",
|
||||
"integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==",
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz",
|
||||
"integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
"es-set-tostringtag": "^2.1.0",
|
||||
"hasown": "^2.0.2",
|
||||
"mime-types": "^2.1.12"
|
||||
},
|
||||
"engines": {
|
||||
@@ -4689,10 +4121,19 @@
|
||||
"node": ">=8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/human-interval": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/human-interval/-/human-interval-2.0.1.tgz",
|
||||
"integrity": "sha512-r4Aotzf+OtKIGQCB3odUowy4GfUDTy3aTWTfLd7ZF2gBCy3XW3v/dJLRefZnOFFnjqs5B1TypvS8WarpBkYUNQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"numbered": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/i18next": {
|
||||
"version": "24.2.3",
|
||||
"resolved": "https://registry.npmjs.org/i18next/-/i18next-24.2.3.tgz",
|
||||
"integrity": "sha512-lfbf80OzkocvX7nmZtu7nSTNbrTYR52sLWxPtlXX1zAhVw8WEnFk4puUkCR4B1dNQwbSpEHHHemcZu//7EcB7A==",
|
||||
"version": "25.4.2",
|
||||
"resolved": "https://registry.npmjs.org/i18next/-/i18next-25.4.2.tgz",
|
||||
"integrity": "sha512-gD4T25a6ovNXsfXY1TwHXXXLnD/K2t99jyYMCSimSCBnBRJVQr5j+VAaU83RJCPzrTGhVQ6dqIga66xO2rtd5g==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
@@ -4709,7 +4150,7 @@
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.26.10"
|
||||
"@babel/runtime": "^7.27.6"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": "^5"
|
||||
@@ -5523,6 +4964,12 @@
|
||||
"integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/numbered": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/numbered/-/numbered-1.1.0.tgz",
|
||||
"integrity": "sha512-pv/ue2Odr7IfYOO0byC1KgBI10wo5YDauLhxY6/saNzAdAs0r1SotGCPzzCLNPL0xtrAwWRialLu23AAu9xO1g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/object-assign": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||
@@ -5738,6 +5185,18 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/parse-ms": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-4.0.0.tgz",
|
||||
"integrity": "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/path-exists": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
|
||||
@@ -5865,6 +5324,21 @@
|
||||
"url": "https://github.com/prettier/prettier?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/pretty-ms": {
|
||||
"version": "9.3.0",
|
||||
"resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.3.0.tgz",
|
||||
"integrity": "sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"parse-ms": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/prop-types": {
|
||||
"version": "15.8.1",
|
||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
||||
@@ -5950,6 +5424,22 @@
|
||||
"react": "^18.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/react-hook-form": {
|
||||
"version": "7.63.0",
|
||||
"resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.63.0.tgz",
|
||||
"integrity": "sha512-ZwueDMvUeucovM2VjkCf7zIHcs1aAlDimZu2Hvel5C5907gUzMpm4xCrQXtRzCvsBqFjonB4m3x4LzCFI1ZKWA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/react-hook-form"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17 || ^18 || ^19"
|
||||
}
|
||||
},
|
||||
"node_modules/react-i18next": {
|
||||
"version": "15.5.1",
|
||||
"resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-15.5.1.tgz",
|
||||
@@ -6748,6 +6238,19 @@
|
||||
"integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/swr": {
|
||||
"version": "2.3.6",
|
||||
"resolved": "https://registry.npmjs.org/swr/-/swr-2.3.6.tgz",
|
||||
"integrity": "sha512-wfHRmHWk/isGNMwlLGlZX5Gzz/uTgo0o2IRuTMcf4CPuPFJZlq0rDaKUx+ozB5nBOReNV1kiOyzMfj+MBMikLw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"dequal": "^2.0.3",
|
||||
"use-sync-external-store": "^1.4.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/text-segmentation": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz",
|
||||
@@ -6896,6 +6399,20 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "5.9.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
|
||||
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
|
||||
"devOptional": true,
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/unbox-primitive": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz",
|
||||
@@ -6915,6 +6432,13 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "7.12.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.12.0.tgz",
|
||||
"integrity": "sha512-goOacqME2GYyOZZfb5Lgtu+1IDmAlAEu5xnD3+xTzS10hT0vzpf0SPjkXwAw9Jm+4n/mQGDP3LO8CPbYROeBfQ==",
|
||||
"devOptional": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/update-browserslist-db": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz",
|
||||
@@ -6996,9 +6520,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/vite": {
|
||||
"version": "6.3.5",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz",
|
||||
"integrity": "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==",
|
||||
"version": "6.3.6",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-6.3.6.tgz",
|
||||
"integrity": "sha512-0msEVHJEScQbhkbVTb/4iHZdJ6SXp/AvxL2sjwYQFfBqleHtnCqv1J3sa9zbWz/6kW1m9Tfzn92vW+kZ1WV6QA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"esbuild": "^0.25.0",
|
||||
@@ -7246,6 +6770,15 @@
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/zod": {
|
||||
"version": "4.1.11",
|
||||
"resolved": "https://registry.npmjs.org/zod/-/zod-4.1.11.tgz",
|
||||
"integrity": "sha512-WPsqwxITS2tzx1bzhIKsEs19ABD5vmCVa4xBo2tq/SrV4RNZtfws1EnCWQXM6yh8bD08a1idvkB5MZSBiZsjwg==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/colinhacks"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+13
-16
@@ -5,8 +5,8 @@
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"build-dev": "vite build --mode development",
|
||||
"build": "tsc -b && vite build",
|
||||
"build-dev": "tsc -b && vite build --mode development",
|
||||
"lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0",
|
||||
"preview": "vite preview",
|
||||
"format": "prettier --write .",
|
||||
@@ -16,6 +16,7 @@
|
||||
"@emotion/react": "^11.13.3",
|
||||
"@emotion/styled": "^11.13.0",
|
||||
"@hello-pangea/dnd": "^18.0.0",
|
||||
"@hookform/resolvers": "5.2.2",
|
||||
"@mui/icons-material": "6.4.11",
|
||||
"@mui/lab": "6.0.0-dev.240424162023-9968b4889d",
|
||||
"@mui/material": "6.4.11",
|
||||
@@ -26,11 +27,14 @@
|
||||
"dayjs": "1.11.13",
|
||||
"flag-icons": "7.3.2",
|
||||
"html2canvas": "^1.4.1",
|
||||
"i18next": "^24.2.2",
|
||||
"human-interval": "2.0.1",
|
||||
"i18next": "25.4.2",
|
||||
"joi": "17.13.3",
|
||||
"mui-color-input": "^6.0.0",
|
||||
"pretty-ms": "9.3.0",
|
||||
"react": "18.3.1",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-hook-form": "7.63.0",
|
||||
"react-i18next": "^15.4.0",
|
||||
"react-icons": "5.5.0",
|
||||
"react-redux": "9.2.0",
|
||||
@@ -39,17 +43,12 @@
|
||||
"react-toastify": "^10.0.5",
|
||||
"recharts": "2.15.2",
|
||||
"redux-persist": "6.0.0",
|
||||
"vite-plugin-svgr": "^4.2.0"
|
||||
},
|
||||
"unusedDepencies": {
|
||||
"@solana/wallet-adapter-base": "0.9.25",
|
||||
"@solana/wallet-adapter-material-ui": "0.16.35",
|
||||
"@solana/wallet-adapter-react": "0.15.37",
|
||||
"@solana/wallet-adapter-react-ui": "0.9.37",
|
||||
"@solana/wallet-adapter-wallets": "0.19.34",
|
||||
"@solana/web3.js": "1.98.0"
|
||||
"swr": "2.3.6",
|
||||
"vite-plugin-svgr": "^4.2.0",
|
||||
"zod": "4.1.11"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "24.5.2",
|
||||
"@types/react": "^18.2.66",
|
||||
"@types/react-dom": "^18.2.22",
|
||||
"@vitejs/plugin-react": "^4.2.1",
|
||||
@@ -58,9 +57,7 @@
|
||||
"eslint-plugin-react-hooks": "^5.0.0",
|
||||
"eslint-plugin-react-refresh": "^0.4.6",
|
||||
"prettier": "^3.3.3",
|
||||
"vite": "6.3.5"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@rollup/rollup-linux-arm64-musl": "4.41.0"
|
||||
"typescript": "5.9.3",
|
||||
"vite": "6.3.6"
|
||||
}
|
||||
}
|
||||
+6
-11
@@ -9,8 +9,7 @@ import { CssBaseline, GlobalStyles } from "@mui/material";
|
||||
import { logger } from "./Utils/Logger"; // Import the logger
|
||||
import { networkService } from "./main";
|
||||
import { Routes } from "./Routes";
|
||||
import WalletProvider from "./Components/WalletProvider";
|
||||
import AppLayout from "./Components/Layouts/AppLayout";
|
||||
import AppLayout from "@/Components/v1/Layouts/AppLayout";
|
||||
|
||||
function App() {
|
||||
const mode = useSelector((state) => state.ui.mode);
|
||||
@@ -24,16 +23,12 @@ function App() {
|
||||
}, []);
|
||||
|
||||
return (
|
||||
/* Extract Themeprovider, baseline and global styles to Styles */
|
||||
<ThemeProvider theme={mode === "light" ? lightTheme : darkTheme}>
|
||||
<WalletProvider>
|
||||
<CssBaseline />
|
||||
|
||||
<AppLayout>
|
||||
<Routes />
|
||||
</AppLayout>
|
||||
<ToastContainer />
|
||||
</WalletProvider>
|
||||
<CssBaseline />
|
||||
<AppLayout>
|
||||
<Routes />
|
||||
</AppLayout>
|
||||
<ToastContainer />
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,212 +0,0 @@
|
||||
import PropTypes from "prop-types";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { Box, Button, Stack, Typography, Link } from "@mui/material";
|
||||
import { Link as RouterLink } from "react-router-dom";
|
||||
import Skeleton from "../../assets/Images/create-placeholder.svg?react";
|
||||
import SkeletonDark from "../../assets/Images/create-placeholder-dark.svg?react";
|
||||
import Background from "../../assets/Images/background-grid.svg?react";
|
||||
import Check from "../Check/Check";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useSelector } from "react-redux";
|
||||
import Alert from "../Alert";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import "./index.css";
|
||||
import { useFetchSettings } from "../../Hooks/settingsHooks";
|
||||
import { useState } from "react";
|
||||
/**
|
||||
* Fallback component to display a fallback UI with a title, a list of checks, and a navigation button.
|
||||
*
|
||||
* @param {Object} props - The component props.
|
||||
* @param {string} props.title - The title to be displayed in the fallback UI.
|
||||
* @param {Array<string>} props.checks - An array of strings representing the checks to display.
|
||||
* @param {string} [props.link="/"] - The link to navigate to.
|
||||
* @param {boolean} [props.vowelStart=false] - Whether the title starts with a vowel.
|
||||
* @param {boolean} [props.showPageSpeedWarning=false] - Whether to show the PageSpeed API warning.
|
||||
* @returns {JSX.Element} The rendered fallback UI.
|
||||
*/
|
||||
|
||||
const Fallback = ({
|
||||
title,
|
||||
checks,
|
||||
link = "/",
|
||||
isAdmin,
|
||||
vowelStart = false,
|
||||
showPageSpeedWarning = false,
|
||||
}) => {
|
||||
const theme = useTheme();
|
||||
const navigate = useNavigate();
|
||||
const mode = useSelector((state) => state.ui.mode);
|
||||
const { t } = useTranslation();
|
||||
const [settingsData, setSettingsData] = useState(undefined);
|
||||
|
||||
const [isLoading, error] = useFetchSettings({
|
||||
setSettingsData,
|
||||
setIsApiKeySet: () => {},
|
||||
setIsEmailPasswordSet: () => {},
|
||||
});
|
||||
// Custom warning message with clickable link
|
||||
const renderWarningMessage = () => {
|
||||
return (
|
||||
<>
|
||||
{t("pageSpeedWarning")}{" "}
|
||||
<Link
|
||||
component={RouterLink}
|
||||
to="/settings"
|
||||
sx={{
|
||||
textDecoration: "underline",
|
||||
color: "inherit",
|
||||
fontWeight: "inherit",
|
||||
"&:hover": {
|
||||
textDecoration: "underline",
|
||||
},
|
||||
}}
|
||||
>
|
||||
{t("pageSpeedLearnMoreLink")}
|
||||
</Link>{" "}
|
||||
{t("pageSpeedAddApiKey")}
|
||||
</>
|
||||
);
|
||||
};
|
||||
return (
|
||||
<Box
|
||||
position="relative"
|
||||
sx={{
|
||||
height: "100%",
|
||||
width: "100%",
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
border={1}
|
||||
borderColor={theme.palette.primary.lowContrast}
|
||||
borderRadius={theme.shape.borderRadius}
|
||||
backgroundColor={theme.palette.primary.main}
|
||||
overflow="hidden"
|
||||
sx={{
|
||||
display: "flex",
|
||||
borderStyle: "dashed",
|
||||
height: {
|
||||
sm: "50vh",
|
||||
md: "70vh",
|
||||
lg: "60vh",
|
||||
xl: "55vh",
|
||||
},
|
||||
width: {
|
||||
sm: "90%",
|
||||
md: "50%",
|
||||
lg: "40%",
|
||||
},
|
||||
padding: theme.spacing(10),
|
||||
}}
|
||||
>
|
||||
<Stack
|
||||
className={`fallback__${title?.trim().split(" ")[0]}`}
|
||||
alignItems="center"
|
||||
gap={theme.spacing(20)}
|
||||
>
|
||||
{mode === "light" ? (
|
||||
<Skeleton style={{ zIndex: 1 }} />
|
||||
) : (
|
||||
<SkeletonDark style={{ zIndex: 1 }} />
|
||||
)}
|
||||
<Box
|
||||
className="background-pattern-svg"
|
||||
sx={{
|
||||
"& svg g g:last-of-type path": {
|
||||
stroke: theme.palette.primary.lowContrast,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Background style={{ width: "100%" }} />
|
||||
</Box>
|
||||
<Stack
|
||||
gap={theme.spacing(4)}
|
||||
maxWidth={theme.spacing(180)}
|
||||
zIndex={1}
|
||||
>
|
||||
<Typography
|
||||
alignSelf="center"
|
||||
component="h1"
|
||||
marginY={theme.spacing(4)}
|
||||
color={theme.palette.primary.contrastTextTertiary}
|
||||
>
|
||||
{vowelStart ? "An" : "A"} {title} is used to:
|
||||
</Typography>
|
||||
{checks?.map((check, index) => (
|
||||
<Check
|
||||
text={check}
|
||||
key={`${title.trim().split(" ")[0]}-${index}`}
|
||||
outlined={true}
|
||||
/>
|
||||
))}
|
||||
</Stack>
|
||||
{/* TODO - display a different fallback if user is not an admin*/}
|
||||
{isAdmin && (
|
||||
<>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="accent"
|
||||
sx={{ alignSelf: "center" }}
|
||||
onClick={() => navigate(link)}
|
||||
>
|
||||
Let's create your first {title}
|
||||
</Button>
|
||||
{/* Bulk create of uptime monitors */}
|
||||
{title === "uptime monitor" && (
|
||||
<Button
|
||||
variant="contained"
|
||||
color="accent"
|
||||
sx={{ alignSelf: "center" }}
|
||||
onClick={() => navigate("/uptime/bulk-import")}
|
||||
>
|
||||
{t("bulkImport.fallbackPage")}
|
||||
</Button>
|
||||
)}
|
||||
|
||||
{/* Warning box for PageSpeed monitor */}
|
||||
{title === "pagespeed monitor" && showPageSpeedWarning && (
|
||||
<Box sx={{ width: "80%", maxWidth: "600px", zIndex: 1 }}>
|
||||
<Box
|
||||
sx={{
|
||||
"& .alert.row-stack": {
|
||||
backgroundColor: theme.palette.warningSecondary.main,
|
||||
borderColor: theme.palette.warningSecondary.lowContrast,
|
||||
"& .MuiTypography-root": {
|
||||
color: theme.palette.warningSecondary.contrastText,
|
||||
},
|
||||
"& .MuiBox-root > svg": {
|
||||
color: theme.palette.warningSecondary.contrastText,
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
{settingsData?.pagespeedKeySet === false && (
|
||||
<Alert
|
||||
variant="warning"
|
||||
hasIcon={true}
|
||||
body={renderWarningMessage()}
|
||||
/>
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</Stack>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
Fallback.propTypes = {
|
||||
title: PropTypes.string.isRequired,
|
||||
checks: PropTypes.arrayOf(PropTypes.string).isRequired,
|
||||
link: PropTypes.string,
|
||||
isAdmin: PropTypes.bool,
|
||||
vowelStart: PropTypes.bool,
|
||||
showPageSpeedWarning: PropTypes.bool,
|
||||
};
|
||||
|
||||
export default Fallback;
|
||||
@@ -6,6 +6,13 @@ import { useSelector } from "react-redux";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { setLanguage } from "../Features/UI/uiSlice";
|
||||
|
||||
const langMap = {
|
||||
cs: "cz",
|
||||
ja: "jp",
|
||||
uk: "ua",
|
||||
vi: "vn",
|
||||
};
|
||||
|
||||
const LanguageSelector = () => {
|
||||
const { i18n } = useTranslation();
|
||||
const theme = useTheme();
|
||||
@@ -23,30 +30,44 @@ const LanguageSelector = () => {
|
||||
value={language}
|
||||
onChange={handleChange}
|
||||
size="small"
|
||||
sx={{ minWidth: 80 }}
|
||||
sx={{
|
||||
minWidth: 80,
|
||||
"& .MuiSelect-select": {
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
},
|
||||
"& .MuiSelect-icon": {
|
||||
alignSelf: "center",
|
||||
},
|
||||
}}
|
||||
>
|
||||
{languages.map((lang) => {
|
||||
let parsedLang = lang === "en" ? "gb" : lang;
|
||||
|
||||
// Fix for Czech
|
||||
if (parsedLang === "cs") {
|
||||
parsedLang = "cz";
|
||||
}
|
||||
if (parsedLang.includes("-")) {
|
||||
parsedLang = parsedLang.split("-")[1].toLowerCase();
|
||||
}
|
||||
|
||||
parsedLang = langMap[parsedLang] || parsedLang;
|
||||
|
||||
const flag = parsedLang ? `fi fi-${parsedLang}` : null;
|
||||
|
||||
return (
|
||||
<MenuItem
|
||||
key={lang}
|
||||
value={lang}
|
||||
sx={{
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<Stack
|
||||
direction="row"
|
||||
spacing={theme.spacing(2)}
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
>
|
||||
<Box
|
||||
component="span"
|
||||
|
||||
@@ -1,106 +0,0 @@
|
||||
/* TODO */
|
||||
aside .MuiList-root svg {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
opacity: 0.9;
|
||||
}
|
||||
aside span.MuiTypography-root {
|
||||
font-size: var(--env-var-font-size-medium);
|
||||
line-height: 1;
|
||||
}
|
||||
aside .MuiStack-root + span.MuiTypography-root {
|
||||
font-size: var(--env-var-font-size-medium-plus);
|
||||
}
|
||||
aside .MuiListSubheader-root {
|
||||
font-size: var(--env-var-font-size-small);
|
||||
font-weight: 500;
|
||||
line-height: 1.5;
|
||||
text-transform: uppercase;
|
||||
margin-bottom: 2px;
|
||||
opacity: 0.6;
|
||||
}
|
||||
aside p.MuiTypography-root {
|
||||
font-size: var(--env-var-font-size-small);
|
||||
opacity: 0.8;
|
||||
}
|
||||
aside .MuiListItemButton-root:not(.selected-path) > * {
|
||||
opacity: 0.9;
|
||||
}
|
||||
aside .selected-path > * {
|
||||
opacity: 1;
|
||||
}
|
||||
aside .selected-path span.MuiTypography-root {
|
||||
font-weight: 600;
|
||||
}
|
||||
aside .MuiCollapse-wrapperInner .MuiList-root > .MuiListItemButton-root {
|
||||
position: relative;
|
||||
}
|
||||
aside .MuiCollapse-wrapperInner .MuiList-root svg,
|
||||
aside .MuiList-root .MuiListItemText-root + svg {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
}
|
||||
|
||||
.sidebar-popup li.MuiButtonBase-root:has(.MuiBox-root) {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
.sidebar-popup svg {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
/* TRANSITIONS */
|
||||
aside {
|
||||
flex: 1;
|
||||
transition: max-width 650ms cubic-bezier(0.36, -0.01, 0, 0.77);
|
||||
}
|
||||
.home-layout aside.collapsed {
|
||||
max-width: 64px;
|
||||
}
|
||||
|
||||
aside.expanded .MuiTypography-root,
|
||||
aside.expanded p.MuiTypography-root,
|
||||
aside.expanded .MuiListItemText-root + svg,
|
||||
aside.expanded .MuiAvatar-root + .MuiBox-root + .MuiIconButton-root {
|
||||
visibility: visible;
|
||||
animation: fadeIn 1s ease;
|
||||
}
|
||||
|
||||
aside.collapsed .MuiTypography-root,
|
||||
aside.collapsed p.MuiTypography-root,
|
||||
aside.collapsed .MuiListItemText-root + svg,
|
||||
aside.collapsed .MuiAvatar-root + .MuiBox-root + .MuiIconButton-root {
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
aside .MuiListSubheader-root {
|
||||
transition: padding 200ms ease;
|
||||
}
|
||||
|
||||
.sidebar-delay-fade {
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transition: opacity 0.3s ease;
|
||||
}
|
||||
|
||||
aside.expanded.sidebar-ready .sidebar-delay-fade {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
0% {
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
}
|
||||
30% {
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
}
|
||||
100% {
|
||||
opacity: 0.9;
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
@@ -1,873 +0,0 @@
|
||||
import React, { useEffect, useState, useRef } from "react";
|
||||
import {
|
||||
Box,
|
||||
Collapse,
|
||||
Divider,
|
||||
IconButton,
|
||||
List,
|
||||
ListItemButton,
|
||||
ListItemIcon,
|
||||
ListItemText,
|
||||
Menu,
|
||||
MenuItem,
|
||||
Stack,
|
||||
Tooltip,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import ThemeSwitch from "../ThemeSwitch";
|
||||
import Avatar from "../Avatar";
|
||||
import StarPrompt from "../StarPrompt";
|
||||
import LockSvg from "../../assets/icons/lock.svg?react";
|
||||
import UserSvg from "../../assets/icons/user.svg?react";
|
||||
import TeamSvg from "../../assets/icons/user-two.svg?react";
|
||||
import LogoutSvg from "../../assets/icons/logout.svg?react";
|
||||
import Support from "../../assets/icons/support.svg?react";
|
||||
import Maintenance from "../../assets/icons/maintenance.svg?react";
|
||||
import Monitors from "../../assets/icons/monitors.svg?react";
|
||||
import Incidents from "../../assets/icons/incidents.svg?react";
|
||||
import Integrations from "../../assets/icons/integrations.svg?react";
|
||||
import PageSpeed from "../../assets/icons/page-speed.svg?react";
|
||||
import Settings from "../../assets/icons/settings.svg?react";
|
||||
import ArrowDown from "../../assets/icons/down-arrow.svg?react";
|
||||
import ArrowUp from "../../assets/icons/up-arrow.svg?react";
|
||||
import ArrowRight from "../../assets/icons/right-arrow.svg?react";
|
||||
import ArrowLeft from "../../assets/icons/left-arrow.svg?react";
|
||||
import DotsVertical from "../../assets/icons/dots-vertical.svg?react";
|
||||
import ChangeLog from "../../assets/icons/changeLog.svg?react";
|
||||
import Docs from "../../assets/icons/docs.svg?react";
|
||||
import StatusPages from "../../assets/icons/status-pages.svg?react";
|
||||
import Discussions from "../../assets/icons/discussions.svg?react";
|
||||
import Notifications from "../../assets/icons/notifications.svg?react";
|
||||
import Logs from "../../assets/icons/logs.svg?react";
|
||||
|
||||
import "./index.css";
|
||||
|
||||
// Utils
|
||||
import { useLocation, useNavigate } from "react-router";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { clearAuthState } from "../../Features/Auth/authSlice";
|
||||
import { toggleSidebar } from "../../Features/UI/uiSlice";
|
||||
import { TurnedIn } from "@mui/icons-material";
|
||||
import { rules } from "eslint-plugin-react-refresh";
|
||||
|
||||
const getMenu = (t) => [
|
||||
{ name: t("menu.uptime"), path: "uptime", icon: <Monitors /> },
|
||||
{ name: t("menu.pagespeed"), path: "pagespeed", icon: <PageSpeed /> },
|
||||
|
||||
{ name: t("menu.infrastructure"), path: "infrastructure", icon: <Integrations /> },
|
||||
{
|
||||
name: t("menu.notifications"),
|
||||
path: "notifications",
|
||||
icon: <Notifications />,
|
||||
},
|
||||
{ name: t("menu.incidents"), path: "incidents", icon: <Incidents /> },
|
||||
|
||||
{ name: t("menu.statusPages"), path: "status", icon: <StatusPages /> },
|
||||
{ name: t("menu.maintenance"), path: "maintenance", icon: <Maintenance /> },
|
||||
{ name: t("menu.logs"), path: "logs", icon: <Logs /> },
|
||||
|
||||
{
|
||||
name: t("menu.settings"),
|
||||
icon: <Settings />,
|
||||
path: "settings",
|
||||
},
|
||||
];
|
||||
|
||||
const getOtherMenuItems = (t) => [
|
||||
{ name: t("menu.support"), path: "support", icon: <Support /> },
|
||||
{
|
||||
name: t("menu.discussions"),
|
||||
path: "discussions",
|
||||
icon: <Discussions />,
|
||||
},
|
||||
{ name: t("menu.docs"), path: "docs", icon: <Docs /> },
|
||||
{ name: t("menu.changelog"), path: "changelog", icon: <ChangeLog /> },
|
||||
];
|
||||
|
||||
const getAccountMenuItems = (t) => [
|
||||
{ name: t("menu.profile"), path: "account/profile", icon: <UserSvg /> },
|
||||
{ name: t("menu.password"), path: "account/password", icon: <LockSvg /> },
|
||||
{ name: t("menu.team"), path: "account/team", icon: <TeamSvg /> },
|
||||
];
|
||||
|
||||
/* TODO this could be a key in nested Path would be the link */
|
||||
const URL_MAP = {
|
||||
support: "https://discord.com/invite/NAb6H3UTjK",
|
||||
discussions: "https://github.com/bluewave-labs/checkmate/discussions",
|
||||
docs: "https://bluewavelabs.gitbook.io/checkmate",
|
||||
changelog: "https://github.com/bluewave-labs/checkmate/releases",
|
||||
};
|
||||
|
||||
const PATH_MAP = {
|
||||
monitors: "Dashboard",
|
||||
pagespeed: "Dashboard",
|
||||
infrastructure: "Dashboard",
|
||||
account: "Account",
|
||||
settings: "Settings",
|
||||
};
|
||||
|
||||
/**
|
||||
* @component
|
||||
* Sidebar component serves as a sidebar containing a menu.
|
||||
*
|
||||
* @returns {JSX.Element} The JSX element representing the Sidebar component.
|
||||
*/
|
||||
|
||||
function Sidebar() {
|
||||
const theme = useTheme();
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
const dispatch = useDispatch();
|
||||
const { t } = useTranslation();
|
||||
const authState = useSelector((state) => state.auth);
|
||||
|
||||
const otherMenuItems = getOtherMenuItems(t);
|
||||
const accountMenuItems = getAccountMenuItems(t);
|
||||
const collapsed = useSelector((state) => state.ui.sidebar.collapsed);
|
||||
const [open, setOpen] = useState({ Dashboard: false, Account: false, Other: false });
|
||||
const [anchorEl, setAnchorEl] = useState(null);
|
||||
const [popup, setPopup] = useState();
|
||||
const { user } = useSelector((state) => state.auth);
|
||||
|
||||
const sidebarRef = useRef(null);
|
||||
const [sidebarReady, setSidebarReady] = useState(false);
|
||||
const TRANSITION_DURATION = 200;
|
||||
let menu = getMenu(t);
|
||||
menu = menu.filter((item) => {
|
||||
if (item.path === "logs") {
|
||||
return user.role?.includes("admin") || user.role?.includes("superadmin");
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (!collapsed) {
|
||||
setSidebarReady(false);
|
||||
const timeout = setTimeout(() => {
|
||||
setSidebarReady(true);
|
||||
}, TRANSITION_DURATION);
|
||||
return () => clearTimeout(timeout);
|
||||
} else {
|
||||
setSidebarReady(false);
|
||||
}
|
||||
}, [collapsed]);
|
||||
|
||||
const renderAccountMenuItems = () => {
|
||||
let filteredAccountMenuItems = [...accountMenuItems];
|
||||
|
||||
// If the user is in demo mode, remove the "Password" option
|
||||
if (user.role?.includes("demo")) {
|
||||
filteredAccountMenuItems = filteredAccountMenuItems.filter(
|
||||
(item) => item.name !== "Password"
|
||||
);
|
||||
}
|
||||
|
||||
// If the user is NOT a superadmin, remove the "Team" option
|
||||
if (user.role && !user.role.includes("superadmin")) {
|
||||
filteredAccountMenuItems = filteredAccountMenuItems.filter(
|
||||
(item) => item.name !== "Team"
|
||||
);
|
||||
}
|
||||
|
||||
return filteredAccountMenuItems.map((item) => (
|
||||
<MenuItem
|
||||
key={item.name}
|
||||
onClick={() => {
|
||||
closePopup();
|
||||
navigate(item.path);
|
||||
}}
|
||||
sx={{
|
||||
gap: theme.spacing(2),
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
pl: theme.spacing(4),
|
||||
}}
|
||||
>
|
||||
{item.icon}
|
||||
{item.name}
|
||||
</MenuItem>
|
||||
));
|
||||
};
|
||||
|
||||
const openPopup = (event, id) => {
|
||||
setAnchorEl(event.currentTarget);
|
||||
setPopup(id);
|
||||
};
|
||||
const closePopup = () => {
|
||||
setAnchorEl(null);
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles logging out the user
|
||||
*
|
||||
*/
|
||||
const logout = async () => {
|
||||
// Clear auth state
|
||||
dispatch(clearAuthState());
|
||||
navigate("/login");
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const matchedKey = Object.keys(PATH_MAP).find((key) =>
|
||||
location.pathname.includes(key)
|
||||
);
|
||||
|
||||
if (matchedKey) {
|
||||
setOpen((prev) => ({ ...prev, [PATH_MAP[matchedKey]]: true }));
|
||||
}
|
||||
}, [location]);
|
||||
|
||||
const iconColor = theme.palette.primary.contrastTextTertiary;
|
||||
const sidebarClassName = `${collapsed ? "collapsed" : "expanded"} ${sidebarReady ? "sidebar-ready" : ""}`;
|
||||
|
||||
/* TODO refactor this, there are a some ternaries and comments in the return */
|
||||
return (
|
||||
<Stack
|
||||
component="aside"
|
||||
ref={sidebarRef}
|
||||
className={sidebarClassName}
|
||||
/* TODO general padding should be here */
|
||||
py={theme.spacing(6)}
|
||||
gap={theme.spacing(6)}
|
||||
/* TODO set all style in this sx if possible (when general)
|
||||
This is the top lever for styles
|
||||
*/
|
||||
sx={{
|
||||
position: "relative",
|
||||
borderRight: `1px solid ${theme.palette.primary.lowContrast}`,
|
||||
borderColor: theme.palette.primary.lowContrast,
|
||||
borderRadius: 0,
|
||||
"& :is(p, span, .MuiListSubheader-root)": {
|
||||
/*
|
||||
Text color for unselected menu items and menu headings
|
||||
Secondary contrast text against main background
|
||||
*/
|
||||
color: theme.palette.primary.contrastTextSecondary,
|
||||
},
|
||||
"& .MuiList-root svg path": {
|
||||
/* Menu Icons */
|
||||
stroke: iconColor,
|
||||
},
|
||||
"& .selected-path": {
|
||||
/* Selected menu item */
|
||||
backgroundColor: theme.palette.secondary.main,
|
||||
"&:hover": {
|
||||
backgroundColor: theme.palette.secondary.main,
|
||||
},
|
||||
"& .MuiListItemIcon-root svg path": {
|
||||
/* Selected menu item icon */
|
||||
stroke: theme.palette.secondary.contrastText,
|
||||
},
|
||||
"& .MuiListItemText-root :is(p, span)": {
|
||||
/* Selected menu item text */
|
||||
color: theme.palette.secondary.contrastText,
|
||||
},
|
||||
},
|
||||
"& .MuiListItemButton-root:not(.selected-path)": {
|
||||
transition: "background-color .3s",
|
||||
" &:hover": {
|
||||
/* Hovered menu item bg color */
|
||||
backgroundColor: theme.palette.tertiary.main,
|
||||
"& :is(p, span)": {
|
||||
/* Hovered menu item text color */
|
||||
color: theme.palette.tertiary.contrastText,
|
||||
},
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
<IconButton
|
||||
sx={{
|
||||
position: "absolute",
|
||||
/* TODO 60 is a magic number. if logo chnges size this might break */
|
||||
top: 60,
|
||||
right: 0,
|
||||
transform: `translate(50%, 0)`,
|
||||
backgroundColor: theme.palette.tertiary.main,
|
||||
border: 1,
|
||||
borderColor: theme.palette.primary.lowContrast,
|
||||
p: theme.spacing(2.5),
|
||||
"& svg": {
|
||||
width: theme.spacing(8),
|
||||
height: theme.spacing(8),
|
||||
"& path": {
|
||||
/* TODO this should be set at the top level if possible */
|
||||
stroke: theme.palette.primary.contrastTextSecondary,
|
||||
},
|
||||
},
|
||||
"&:focus": { outline: "none" },
|
||||
"&:hover": {
|
||||
backgroundColor: theme.palette.primary.lowContrast,
|
||||
borderColor: theme.palette.primary.lowContrast,
|
||||
},
|
||||
}}
|
||||
onClick={() => {
|
||||
setOpen((prev) =>
|
||||
Object.fromEntries(Object.keys(prev).map((key) => [key, false]))
|
||||
);
|
||||
dispatch(toggleSidebar());
|
||||
}}
|
||||
>
|
||||
{collapsed ? <ArrowRight /> : <ArrowLeft />}
|
||||
</IconButton>
|
||||
{/* TODO Alignment done using padding. Use single source of truth to that*/}
|
||||
<Stack
|
||||
pt={theme.spacing(6)}
|
||||
pb={theme.spacing(12)}
|
||||
pl={theme.spacing(8)}
|
||||
>
|
||||
{/* TODO Abstract logo into component */}
|
||||
{/* TODO Turn logo into a link */}
|
||||
<Stack
|
||||
direction="row"
|
||||
alignItems="center"
|
||||
gap={theme.spacing(4)}
|
||||
onClick={() => navigate("/")}
|
||||
sx={{ cursor: "pointer" }}
|
||||
>
|
||||
<Stack
|
||||
justifyContent="center"
|
||||
alignItems="center"
|
||||
minWidth={theme.spacing(16)}
|
||||
minHeight={theme.spacing(16)}
|
||||
pl="1px"
|
||||
fontSize={18}
|
||||
color={theme.palette.accent.contrastText}
|
||||
sx={{
|
||||
position: "relative",
|
||||
backgroundColor: theme.palette.accent.main,
|
||||
color: theme.palette.accent.contrastText,
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
userSelect: "none",
|
||||
}}
|
||||
>
|
||||
C
|
||||
</Stack>
|
||||
<Typography
|
||||
component="span"
|
||||
mt={theme.spacing(2)}
|
||||
sx={{ opacity: 0.8, fontWeight: 500 }}
|
||||
>
|
||||
{t("common.appName")}
|
||||
</Typography>
|
||||
</Stack>
|
||||
</Stack>
|
||||
<Box
|
||||
sx={{
|
||||
flexGrow: 1,
|
||||
overflow: "auto",
|
||||
overflowX: "hidden",
|
||||
"&::-webkit-scrollbar": {
|
||||
width: theme.spacing(2),
|
||||
},
|
||||
"&::-webkit-scrollbar-thumb": {
|
||||
backgroundColor: theme.palette.primary.lowContrast,
|
||||
borderRadius: theme.spacing(4),
|
||||
},
|
||||
}}
|
||||
>
|
||||
<List
|
||||
component="nav"
|
||||
aria-labelledby="nested-menu-subheader"
|
||||
disablePadding
|
||||
sx={{
|
||||
px: theme.spacing(6),
|
||||
height: "100%",
|
||||
/* overflow: "hidden", */
|
||||
}}
|
||||
>
|
||||
{menu.map((item) => {
|
||||
return item.path ? (
|
||||
/* If item has a path */
|
||||
<Tooltip
|
||||
key={item.path}
|
||||
placement="right"
|
||||
title={collapsed ? item.name : ""}
|
||||
slotProps={{
|
||||
popper: {
|
||||
modifiers: [
|
||||
{
|
||||
name: "offset",
|
||||
options: {
|
||||
offset: [0, -16],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
}}
|
||||
disableInteractive
|
||||
>
|
||||
<ListItemButton
|
||||
className={
|
||||
location.pathname.startsWith(`/${item.path}`) ? "selected-path" : ""
|
||||
}
|
||||
onClick={() => navigate(`/${item.path}`)}
|
||||
sx={{
|
||||
height: "37px",
|
||||
gap: theme.spacing(4),
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
px: theme.spacing(4),
|
||||
pl: theme.spacing(5),
|
||||
}}
|
||||
>
|
||||
<ListItemIcon sx={{ minWidth: 0 }}>{item.icon}</ListItemIcon>
|
||||
<ListItemText>{item.name}</ListItemText>
|
||||
</ListItemButton>
|
||||
</Tooltip>
|
||||
) : collapsed ? (
|
||||
/* TODO Do we ever get here? If item does not have a path and collapsed state is true */
|
||||
<React.Fragment key={item.name}>
|
||||
<Tooltip
|
||||
placement="right"
|
||||
title={collapsed ? item.name : ""}
|
||||
slotProps={{
|
||||
popper: {
|
||||
modifiers: [
|
||||
{
|
||||
name: "offset",
|
||||
options: {
|
||||
offset: [0, -16],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
}}
|
||||
disableInteractive
|
||||
>
|
||||
<ListItemButton
|
||||
className={
|
||||
Boolean(anchorEl) && popup === item.name ? "selected-path" : ""
|
||||
}
|
||||
onClick={(event) => openPopup(event, item.name)}
|
||||
sx={{
|
||||
position: "relative",
|
||||
gap: theme.spacing(4),
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
px: theme.spacing(4),
|
||||
}}
|
||||
>
|
||||
<ListItemIcon sx={{ minWidth: 0 }}>{item.icon}</ListItemIcon>
|
||||
<ListItemText>{item.name}</ListItemText>
|
||||
</ListItemButton>
|
||||
</Tooltip>
|
||||
<Menu
|
||||
className="sidebar-popup"
|
||||
anchorEl={anchorEl}
|
||||
open={Boolean(anchorEl) && popup === item.name}
|
||||
onClose={closePopup}
|
||||
disableScrollLock
|
||||
anchorOrigin={{
|
||||
vertical: "top",
|
||||
horizontal: "right",
|
||||
}}
|
||||
slotProps={{
|
||||
paper: {
|
||||
sx: {
|
||||
mt: theme.spacing(-2),
|
||||
ml: theme.spacing(1),
|
||||
},
|
||||
},
|
||||
}}
|
||||
MenuListProps={{ sx: { px: 1, py: 2 } }}
|
||||
sx={{
|
||||
ml: theme.spacing(8),
|
||||
/* TODO what is this selection? */
|
||||
"& .selected-path": {
|
||||
backgroundColor: theme.palette.tertiary.main,
|
||||
},
|
||||
}}
|
||||
>
|
||||
{item.nested.map((child) => {
|
||||
if (
|
||||
child.name === "Team" &&
|
||||
authState.user?.role &&
|
||||
!authState.user.role.includes("superadmin")
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<MenuItem
|
||||
className={
|
||||
location.pathname.includes(child.path) ? "selected-path" : ""
|
||||
}
|
||||
key={child.path}
|
||||
onClick={() => {
|
||||
const url = URL_MAP[child.path];
|
||||
if (url) {
|
||||
window.open(url, "_blank", "noreferrer");
|
||||
} else {
|
||||
navigate(`/${child.path}`);
|
||||
}
|
||||
closePopup();
|
||||
}}
|
||||
sx={{
|
||||
gap: theme.spacing(4),
|
||||
opacity: 0.9,
|
||||
/* TODO this has no effect? */
|
||||
"& svg": {
|
||||
"& path": {
|
||||
stroke: theme.palette.primary.contrastTextTertiary,
|
||||
strokeWidth: 1.1,
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
{child.icon}
|
||||
{child.name}
|
||||
</MenuItem>
|
||||
);
|
||||
})}
|
||||
</Menu>
|
||||
</React.Fragment>
|
||||
) : (
|
||||
/* TODO Do we ever get here? If item does not have a path and collapsed state is false */
|
||||
<React.Fragment key={item.name}>
|
||||
<ListItemButton
|
||||
onClick={() =>
|
||||
setOpen((prev) => ({
|
||||
...Object.fromEntries(Object.keys(prev).map((key) => [key, false])),
|
||||
[item.name]: !prev[item.name],
|
||||
}))
|
||||
}
|
||||
sx={{
|
||||
gap: theme.spacing(4),
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
px: theme.spacing(4),
|
||||
}}
|
||||
>
|
||||
<ListItemIcon sx={{ minWidth: 0 }}>{item.icon}</ListItemIcon>
|
||||
<ListItemText>{item.name}</ListItemText>
|
||||
{open[`${item.name}`] ? <ArrowUp /> : <ArrowDown />}
|
||||
</ListItemButton>
|
||||
<Collapse
|
||||
in={open[`${item.name}`]}
|
||||
timeout="auto"
|
||||
>
|
||||
<List
|
||||
component="div"
|
||||
disablePadding
|
||||
sx={{ pl: theme.spacing(12) }}
|
||||
>
|
||||
{item.nested.map((child) => {
|
||||
if (
|
||||
child.name === "Team" &&
|
||||
authState.user?.role &&
|
||||
!authState.user.role.includes("superadmin")
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<ListItemButton
|
||||
className={
|
||||
location.pathname.includes(child.path) ? "selected-path" : ""
|
||||
}
|
||||
key={child.path}
|
||||
onClick={() => {
|
||||
const url = URL_MAP[child.path];
|
||||
if (url) {
|
||||
window.open(url, "_blank", "noreferrer");
|
||||
} else {
|
||||
navigate(`/${child.path}`);
|
||||
}
|
||||
}}
|
||||
sx={{
|
||||
gap: theme.spacing(4),
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
pl: theme.spacing(4),
|
||||
"&::before": {
|
||||
content: `""`,
|
||||
position: "absolute",
|
||||
top: 0,
|
||||
left: "-7px",
|
||||
height: "100%",
|
||||
borderLeft: 1,
|
||||
borderLeftColor: theme.palette.primary.lowContrast,
|
||||
},
|
||||
"&:last-child::before": {
|
||||
height: "50%",
|
||||
},
|
||||
"&::after": {
|
||||
content: `""`,
|
||||
position: "absolute",
|
||||
top: "45%",
|
||||
left: "-8px",
|
||||
height: "3px",
|
||||
width: "3px",
|
||||
borderRadius: "50%",
|
||||
backgroundColor: theme.palette.primary.lowContrast,
|
||||
},
|
||||
"&.selected-path::after": {
|
||||
/* TODO what is this selector doing? */
|
||||
backgroundColor: theme.palette.primary.contrastTextTertiary,
|
||||
transform: "scale(1.2)",
|
||||
},
|
||||
}}
|
||||
>
|
||||
<ListItemIcon sx={{ minWidth: 0 }}>{child.icon}</ListItemIcon>
|
||||
<ListItemText>{child.name}</ListItemText>
|
||||
</ListItemButton>
|
||||
);
|
||||
})}
|
||||
</List>
|
||||
</Collapse>
|
||||
</React.Fragment>
|
||||
);
|
||||
})}
|
||||
</List>
|
||||
</Box>
|
||||
|
||||
{!collapsed && <StarPrompt />}
|
||||
|
||||
<List
|
||||
component="nav"
|
||||
disablePadding
|
||||
sx={{ px: theme.spacing(6) }}
|
||||
>
|
||||
{otherMenuItems.map((item) => {
|
||||
return item.path ? (
|
||||
<Tooltip
|
||||
key={item.path}
|
||||
placement="right"
|
||||
title={collapsed ? item.name : ""}
|
||||
slotProps={{
|
||||
popper: {
|
||||
modifiers: [
|
||||
{
|
||||
name: "offset",
|
||||
options: {
|
||||
offset: [0, -16],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
}}
|
||||
disableInteractive
|
||||
>
|
||||
<ListItemButton
|
||||
className={
|
||||
location.pathname.startsWith(`/${item.path}`) ? "selected-path" : ""
|
||||
}
|
||||
onClick={() => {
|
||||
const url = URL_MAP[item.path];
|
||||
if (url) {
|
||||
window.open(url, "_blank", "noreferrer");
|
||||
} else {
|
||||
navigate(`/${item.path}`);
|
||||
}
|
||||
}}
|
||||
sx={{
|
||||
height: "37px",
|
||||
gap: theme.spacing(4),
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
px: theme.spacing(4),
|
||||
pl: theme.spacing(5),
|
||||
}}
|
||||
>
|
||||
<ListItemIcon sx={{ minWidth: 0 }}>{item.icon} </ListItemIcon>
|
||||
<ListItemText>{item.name} </ListItemText>{" "}
|
||||
</ListItemButton>
|
||||
</Tooltip>
|
||||
) : null;
|
||||
})}
|
||||
</List>
|
||||
<Divider sx={{ mt: "auto", borderColor: theme.palette.primary.lowContrast }} />
|
||||
<Stack
|
||||
direction="row"
|
||||
height="50px"
|
||||
alignItems="center"
|
||||
py={theme.spacing(4)}
|
||||
px={theme.spacing(8)}
|
||||
gap={theme.spacing(2)}
|
||||
borderRadius={theme.shape.borderRadius}
|
||||
>
|
||||
{collapsed ? (
|
||||
<>
|
||||
<Tooltip
|
||||
title="Options"
|
||||
slotProps={{
|
||||
popper: {
|
||||
modifiers: [
|
||||
{
|
||||
name: "offset",
|
||||
options: {
|
||||
offset: [0, -10],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
}}
|
||||
disableInteractive
|
||||
>
|
||||
<IconButton
|
||||
onClick={(event) => openPopup(event, "logout")}
|
||||
sx={{ p: 0, "&:focus": { outline: "none" } }}
|
||||
>
|
||||
<Avatar small={true} />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Avatar small={true} />
|
||||
<Box
|
||||
ml={theme.spacing(2)}
|
||||
sx={{ maxWidth: "50%", overflow: "hidden" }}
|
||||
>
|
||||
<Typography
|
||||
component="span"
|
||||
fontWeight={500}
|
||||
sx={{
|
||||
display: "block",
|
||||
whiteSpace: "nowrap",
|
||||
overflow: "hidden",
|
||||
textOverflow: "ellipsis",
|
||||
}}
|
||||
>
|
||||
{authState.user?.firstName} {authState.user?.lastName}
|
||||
</Typography>
|
||||
<Typography sx={{ textTransform: "capitalize" }}>
|
||||
{authState.user?.role?.includes("superadmin")
|
||||
? t("roles.superAdmin")
|
||||
: authState.user?.role?.includes("admin")
|
||||
? t("roles.admin")
|
||||
: authState.user?.role?.includes("user")
|
||||
? t("roles.teamMember")
|
||||
: authState.user?.role?.includes("demo")
|
||||
? t("roles.demoUser")
|
||||
: authState.user?.role}
|
||||
</Typography>
|
||||
</Box>
|
||||
<Stack
|
||||
className="sidebar-delay-fade"
|
||||
flexDirection={"row"}
|
||||
marginLeft={"auto"}
|
||||
columnGap={theme.spacing(2)}
|
||||
>
|
||||
<ThemeSwitch color={iconColor} />
|
||||
<Tooltip
|
||||
title={t("navControls")}
|
||||
disableInteractive
|
||||
>
|
||||
<IconButton
|
||||
sx={{
|
||||
ml: "auto",
|
||||
mr: "-8px",
|
||||
"&:focus": { outline: "none" },
|
||||
alignSelf: "center",
|
||||
padding: "10px",
|
||||
|
||||
"& svg": {
|
||||
width: "22px",
|
||||
height: "22px",
|
||||
},
|
||||
"& svg path": {
|
||||
/* Vertical three dots */
|
||||
stroke: iconColor,
|
||||
},
|
||||
}}
|
||||
onClick={(event) => openPopup(event, "logout")}
|
||||
>
|
||||
<DotsVertical />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
</Stack>
|
||||
</>
|
||||
)}
|
||||
<Menu
|
||||
className="sidebar-popup"
|
||||
anchorEl={anchorEl}
|
||||
open={Boolean(anchorEl) && popup === "logout"}
|
||||
onClose={closePopup}
|
||||
disableScrollLock
|
||||
anchorOrigin={{
|
||||
vertical: "top",
|
||||
horizontal: "right",
|
||||
}}
|
||||
slotProps={{
|
||||
paper: {
|
||||
sx: {
|
||||
marginTop: theme.spacing(-4),
|
||||
marginLeft: collapsed ? theme.spacing(2) : 0,
|
||||
},
|
||||
},
|
||||
}}
|
||||
MenuListProps={{
|
||||
sx: {
|
||||
p: 2,
|
||||
"& li": { m: 0 },
|
||||
"& li:has(.MuiBox-root):hover": {
|
||||
backgroundColor: "transparent",
|
||||
},
|
||||
},
|
||||
}}
|
||||
sx={{
|
||||
ml: theme.spacing(4),
|
||||
}}
|
||||
>
|
||||
{collapsed && (
|
||||
<MenuItem sx={{ cursor: "default", minWidth: "50%" }}>
|
||||
<Box
|
||||
mb={theme.spacing(2)}
|
||||
sx={{
|
||||
minWidth: "50%",
|
||||
maxWidth: "max-content",
|
||||
overflow: "visible",
|
||||
whiteSpace: "nowrap",
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
component="span"
|
||||
fontWeight={500}
|
||||
fontSize={13}
|
||||
sx={{
|
||||
display: "block",
|
||||
whiteSpace: "nowrap",
|
||||
overflow: "visible",
|
||||
// wordBreak: "break-word",
|
||||
textOverflow: "clip",
|
||||
}}
|
||||
>
|
||||
{authState.user?.firstName} {authState.user?.lastName}
|
||||
</Typography>
|
||||
<Typography
|
||||
sx={{
|
||||
textTransform: "capitalize",
|
||||
fontSize: 12,
|
||||
whiteSpace: "nowrap",
|
||||
overflow: "visible",
|
||||
// wordBreak: "break-word",
|
||||
}}
|
||||
>
|
||||
{authState.user?.role}
|
||||
</Typography>
|
||||
</Box>
|
||||
</MenuItem>
|
||||
)}
|
||||
{/* TODO Do we need two dividers? */}
|
||||
{collapsed && <Divider />}
|
||||
{/* <Divider /> */}
|
||||
{renderAccountMenuItems()}
|
||||
<MenuItem
|
||||
onClick={logout}
|
||||
sx={{
|
||||
gap: theme.spacing(4),
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
pl: theme.spacing(4),
|
||||
"& svg path": {
|
||||
stroke: iconColor,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<LogoutSvg />
|
||||
{t("menu.logOut", "Log out")}
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
</Stack>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
export default Sidebar;
|
||||
+4
-4
@@ -2,17 +2,17 @@
|
||||
import IconButton from "@mui/material/IconButton";
|
||||
import Menu from "@mui/material/Menu";
|
||||
import MenuItem from "@mui/material/MenuItem";
|
||||
import Settings from "../../assets/icons/settings-bold.svg?react";
|
||||
import Dialog from "../../Components/Dialog";
|
||||
import Settings from "../../../assets/icons/settings-bold.svg?react";
|
||||
import Dialog from "../Dialog/index.jsx";
|
||||
|
||||
// Utils
|
||||
import { useState } from "react";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { createToast } from "../../Utils/toastUtils";
|
||||
import { createToast } from "../../../Utils/toastUtils.jsx";
|
||||
|
||||
import PropTypes from "prop-types";
|
||||
import { usePauseMonitor, useDeleteMonitor } from "../../Hooks/monitorHooks";
|
||||
import { usePauseMonitor, useDeleteMonitor } from "../../../Hooks/v1/monitorHooks.js";
|
||||
|
||||
const ActionsMenu = ({
|
||||
monitor,
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,35 @@
|
||||
import LeftArrow from "../../../assets/icons/left-arrow.svg?react";
|
||||
import LeftArrowDouble from "../../../assets/icons/left-arrow-double.svg?react";
|
||||
import LeftArrowLong from "../../../assets/icons/left-arrow-long.svg?react";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
const ArrowLeft = ({ type, color = "#667085", ...props }) => {
|
||||
if (type === "double") {
|
||||
return (
|
||||
<LeftArrowDouble
|
||||
style={{ color }}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
} else if (type === "long") {
|
||||
return (
|
||||
<LeftArrowLong
|
||||
style={{ color }}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<LeftArrow
|
||||
style={{ color }}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
ArrowLeft.propTypes = {
|
||||
color: PropTypes.string,
|
||||
type: PropTypes.oneOf(["double", "long", "default"]),
|
||||
};
|
||||
export default ArrowLeft;
|
||||
@@ -0,0 +1,28 @@
|
||||
import RightArrow from "../../../assets/icons/right-arrow.svg?react";
|
||||
import RightArrowDouble from "../../../assets/icons/right-arrow-double.svg?react";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
const ArrowRight = ({ type, color = "#667085", ...props }) => {
|
||||
if (type === "double") {
|
||||
return (
|
||||
<RightArrowDouble
|
||||
style={{ color }}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<RightArrow
|
||||
style={{ color }}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
ArrowRight.propTypes = {
|
||||
type: PropTypes.oneOf(["double", "default"]),
|
||||
color: PropTypes.string,
|
||||
};
|
||||
|
||||
export default ArrowRight;
|
||||
File renamed without changes.
@@ -15,7 +15,7 @@ import { useTheme } from "@emotion/react";
|
||||
* <Avatar src="assets/img" first="Alex" last="Holliday" small />
|
||||
*/
|
||||
|
||||
const Avatar = ({ src, small, sx }) => {
|
||||
const Avatar = ({ src, small, sx, onClick = () => {} }) => {
|
||||
const { user } = useSelector((state) => state.auth);
|
||||
const theme = useTheme();
|
||||
|
||||
@@ -31,6 +31,7 @@ const Avatar = ({ src, small, sx }) => {
|
||||
|
||||
return (
|
||||
<MuiAvatar
|
||||
onClick={onClick}
|
||||
alt={`${user?.firstName} ${user?.lastName}`}
|
||||
/* TODO What is the /static/images/avatar/2.jpg ?*/
|
||||
src={src ? src : user?.avatarImage ? image : "/static/images/avatar/2.jpg"}
|
||||
@@ -66,6 +67,7 @@ Avatar.propTypes = {
|
||||
src: PropTypes.string,
|
||||
small: PropTypes.bool,
|
||||
sx: PropTypes.object,
|
||||
onClick: PropTypes.func,
|
||||
};
|
||||
|
||||
export default Avatar;
|
||||
File renamed without changes.
+1
-2
@@ -2,8 +2,7 @@ import PropTypes from "prop-types";
|
||||
import { Box, Breadcrumbs as MUIBreadcrumbs } from "@mui/material";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import ArrowRight from "../../assets/icons/right-arrow.svg?react";
|
||||
|
||||
import ArrowRight from "../ArrowRight/index.jsx";
|
||||
import "./index.css";
|
||||
|
||||
/**
|
||||
File renamed without changes.
+1
-1
@@ -61,7 +61,7 @@ import {
|
||||
Tooltip,
|
||||
ResponsiveContainer,
|
||||
} from "recharts";
|
||||
import { createGradient } from "../Utils/gradientUtils";
|
||||
import { createGradient } from "../Utils/gradientUtils.jsx";
|
||||
import PropTypes from "prop-types";
|
||||
import { useTheme } from "@mui/material";
|
||||
import { useId } from "react";
|
||||
File renamed without changes.
+1
-1
@@ -1,6 +1,6 @@
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { Box, Stack, Tooltip, Typography } from "@mui/material";
|
||||
import { formatDateWithTz } from "../../../Utils/timeUtils";
|
||||
import { formatDateWithTz } from "../../../../Utils/timeUtils.js";
|
||||
import { useEffect, useState } from "react";
|
||||
import "./index.css";
|
||||
import { useSelector } from "react-redux";
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
import { Typography, Stack } from "@mui/material";
|
||||
import PropTypes from "prop-types";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import IconBox from "../../IconBox";
|
||||
import IconBox from "../../IconBox/index.jsx";
|
||||
|
||||
/**
|
||||
* `EmptyView` is a functional React component that displays an empty state view with an optional icon, header, and message.
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
import { Stack, Typography } from "@mui/material";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import IconBox from "../../IconBox";
|
||||
import EmptyView from "./EmptyView";
|
||||
import IconBox from "../../IconBox/index.jsx";
|
||||
import EmptyView from "./EmptyView.jsx";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
const ChartBox = ({
|
||||
File renamed without changes.
+39
-10
@@ -1,8 +1,10 @@
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { useEffect, useState, useMemo } from "react";
|
||||
import Stack from "@mui/material/Stack";
|
||||
import { Box, Typography } from "@mui/material";
|
||||
import PropTypes from "prop-types";
|
||||
import "./index.css";
|
||||
import CircularProgress from "@mui/material/CircularProgress";
|
||||
|
||||
const MINIMUM_VALUE = 0;
|
||||
const MAXIMUM_VALUE = 100;
|
||||
@@ -15,19 +17,26 @@ const MAXIMUM_VALUE = 100;
|
||||
* @param {number} [props.progress=0] - Progress percentage (0-100)
|
||||
* @param {number} [props.radius=60] - Radius of the gauge circle
|
||||
* @param {number} [props.strokeWidth=15] - Width of the gauge stroke
|
||||
* @param {number} [props.threshold=50] - Threshold for color change
|
||||
* @param {number} [props.precision=1] - Precision of the progress percentage
|
||||
* @param {string} [props.unit="%"] - Unit of progress
|
||||
*
|
||||
* @example
|
||||
* <CustomGauge
|
||||
* progress={75}
|
||||
* radius={50}
|
||||
* strokeWidth={10}
|
||||
* threshold={50}
|
||||
* />
|
||||
*
|
||||
* @returns {React.ReactElement} Rendered CustomGauge component
|
||||
*/
|
||||
const CustomGauge = ({ progress = 0, radius = 70, strokeWidth = 15, threshold = 50 }) => {
|
||||
const CustomGauge = ({
|
||||
isLoading = false,
|
||||
progress = 0,
|
||||
radius = 70,
|
||||
strokeWidth = 15,
|
||||
precision = 1,
|
||||
unit = "%",
|
||||
}) => {
|
||||
const theme = useTheme();
|
||||
// Calculate the length of the stroke for the circle
|
||||
const { circumference, totalSize, strokeLength } = useMemo(
|
||||
@@ -52,10 +61,28 @@ const CustomGauge = ({ progress = 0, radius = 70, strokeWidth = 15, threshold =
|
||||
|
||||
const progressWithinRange = Math.max(MINIMUM_VALUE, Math.min(progress, MAXIMUM_VALUE));
|
||||
|
||||
const fillColor =
|
||||
progressWithinRange > threshold
|
||||
? theme.palette.error.lowContrast // CAIO_REVIEW
|
||||
: theme.palette.accent.main; // CAIO_REVIEW
|
||||
let fillColor;
|
||||
if (progressWithinRange < 50) {
|
||||
fillColor = theme.palette.success.main;
|
||||
} else if (progressWithinRange < 80) {
|
||||
fillColor = theme.palette.warning.lowContrast;
|
||||
} else {
|
||||
fillColor = theme.palette.error.lowContrast;
|
||||
}
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<Stack
|
||||
className="radial-chart"
|
||||
width={radius}
|
||||
height={radius}
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
>
|
||||
<CircularProgress color="accent" />
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Box
|
||||
@@ -71,7 +98,7 @@ const CustomGauge = ({ progress = 0, radius = 70, strokeWidth = 15, threshold =
|
||||
>
|
||||
<circle
|
||||
className="radial-chart-base"
|
||||
stroke={theme.palette.secondary.light} // CAIO_REVIEW
|
||||
stroke={theme.palette.secondary.light}
|
||||
strokeWidth={strokeWidth}
|
||||
fill="none"
|
||||
cx={totalSize / 2} // Center the circle
|
||||
@@ -103,7 +130,7 @@ const CustomGauge = ({ progress = 0, radius = 70, strokeWidth = 15, threshold =
|
||||
fill: theme.typography.h2.color,
|
||||
}}
|
||||
>
|
||||
{`${progressWithinRange.toFixed(1)}%`}
|
||||
{`${progressWithinRange.toFixed(precision)}${unit}`}
|
||||
</Typography>
|
||||
</Box>
|
||||
);
|
||||
@@ -112,8 +139,10 @@ const CustomGauge = ({ progress = 0, radius = 70, strokeWidth = 15, threshold =
|
||||
export default CustomGauge;
|
||||
|
||||
CustomGauge.propTypes = {
|
||||
isLoading: PropTypes.bool,
|
||||
progress: PropTypes.number,
|
||||
radius: PropTypes.number,
|
||||
strokeWidth: PropTypes.number,
|
||||
threshold: PropTypes.number,
|
||||
precision: PropTypes.number,
|
||||
unit: PropTypes.string,
|
||||
};
|
||||
+1
-1
@@ -5,7 +5,7 @@ import { Stack, Box, Tooltip, Typography } from "@mui/material";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { useState, useEffect } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import { formatDateWithTz } from "../../../Utils/timeUtils";
|
||||
import { formatDateWithTz } from "../../../../Utils/timeUtils.js";
|
||||
import { useSelector } from "react-redux";
|
||||
|
||||
const PlaceholderCheck = ({ daysToShow }) => {
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
import { Stack, Typography } from "@mui/material";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import IconBox from "../../IconBox";
|
||||
import IconBox from "../../IconBox/index.jsx";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
const LegendBox = ({ children, icon, header, sx }) => {
|
||||
File renamed without changes.
+2
-2
@@ -12,11 +12,11 @@ import { Box, Stack, Typography } from "@mui/material";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { useMemo, useState } from "react";
|
||||
import { useSelector } from "react-redux";
|
||||
import { formatDateWithTz } from "../../../Utils/timeUtils";
|
||||
import { formatDateWithTz } from "../../../../Utils/timeUtils.js";
|
||||
import {
|
||||
tooltipDateFormatLookup,
|
||||
tickDateFormatLookup,
|
||||
} from "../Utils/chartUtilFunctions";
|
||||
} from "../Utils/chartUtilFunctions.js";
|
||||
|
||||
import "./index.css";
|
||||
const CustomToolTip = ({ active, payload, label, dateRange }) => {
|
||||
+25
-19
@@ -1,7 +1,7 @@
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { Box, Stack, Tooltip, Typography } from "@mui/material";
|
||||
import { formatDateWithTz } from "../../../Utils/timeUtils";
|
||||
import { useEffect, useState } from "react";
|
||||
import { formatDateWithTz } from "../../../../Utils/timeUtils.js";
|
||||
import { useEffect, useState, forwardRef } from "react";
|
||||
import { useSelector } from "react-redux";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
@@ -17,26 +17,32 @@ import PropTypes from "prop-types";
|
||||
* @returns {JSX.Element} The Bar component.
|
||||
*/
|
||||
|
||||
const Bar = ({ width, height, backgroundColor, borderRadius, children }) => {
|
||||
const theme = useTheme();
|
||||
const Bar = forwardRef(
|
||||
({ width, height, backgroundColor, borderRadius, children, ...otherProps }, ref) => {
|
||||
const theme = useTheme();
|
||||
|
||||
return (
|
||||
<Box
|
||||
position="relative"
|
||||
width={width}
|
||||
height={height}
|
||||
backgroundColor={backgroundColor}
|
||||
sx={{
|
||||
borderRadius: borderRadius || theme.spacing(1.5),
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
return (
|
||||
<Box
|
||||
ref={ref}
|
||||
position="relative"
|
||||
width={width}
|
||||
height={height}
|
||||
backgroundColor={backgroundColor}
|
||||
sx={{
|
||||
borderRadius: borderRadius || theme.spacing(1.5),
|
||||
}}
|
||||
{...otherProps}
|
||||
>
|
||||
{children}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
Bar.displayName = "Bar";
|
||||
|
||||
Bar.propTypes = {
|
||||
width: PropTypes.string.isRequired,
|
||||
width: PropTypes.oneOfType([PropTypes.string, PropTypes.object]).isRequired,
|
||||
height: PropTypes.string.isRequired,
|
||||
backgroundColor: PropTypes.string.isRequired,
|
||||
borderRadius: PropTypes.string,
|
||||
+1
@@ -1,5 +1,6 @@
|
||||
export const tooltipDateFormatLookup = (dateRange) => {
|
||||
const dateFormatLookup = {
|
||||
recent: "ddd. MMMM D, YYYY, hh:mm A",
|
||||
day: "ddd. MMMM D, YYYY, hh:mm A",
|
||||
week: "ddd. MMMM D, YYYY, hh:mm A",
|
||||
month: "ddd. MMMM D, YYYY",
|
||||
+50
-5
@@ -2,9 +2,9 @@ import PropTypes from "prop-types";
|
||||
import { useSelector } from "react-redux";
|
||||
import { useTheme } from "@mui/material";
|
||||
import { Text } from "recharts";
|
||||
import { formatDateWithTz } from "../../../Utils/timeUtils";
|
||||
import { formatDateWithTz } from "../../../../Utils/timeUtils.js";
|
||||
import { Box, Stack, Typography } from "@mui/material";
|
||||
import { tickDateFormatLookup, tooltipDateFormatLookup } from "./chartUtilFunctions";
|
||||
import { tickDateFormatLookup, tooltipDateFormatLookup } from "./chartUtilFunctions.js";
|
||||
/**
|
||||
* Custom tick component for rendering time with timezone.
|
||||
*
|
||||
@@ -88,7 +88,51 @@ PercentTick.propTypes = {
|
||||
*/
|
||||
const getFormattedPercentage = (value) => {
|
||||
if (typeof value !== "number") return value;
|
||||
return `${(value * 100).toFixed(2)}.%`;
|
||||
return `${(value * 100).toFixed(2)}%`;
|
||||
};
|
||||
|
||||
/**
|
||||
* Custom tick component for rendering network bytes per second.
|
||||
*
|
||||
* @param {Object} props - The properties object.
|
||||
* @param {number} props.x - The x-coordinate for the tick.
|
||||
* @param {number} props.y - The y-coordinate for the tick.
|
||||
* @param {Object} props.payload - The payload object containing tick data.
|
||||
* @param {number} props.index - The index of the tick.
|
||||
* @returns {JSX.Element|null} The rendered tick component or null for the first tick.
|
||||
*/
|
||||
export const NetworkTick = ({ x, y, payload, index, formatter }) => {
|
||||
const theme = useTheme();
|
||||
if (index === 0) return null;
|
||||
|
||||
if (formatter === undefined) {
|
||||
formatter = (value, space = false) => {
|
||||
if (typeof value !== "number") return value;
|
||||
// need to add space between value and unit
|
||||
return `${(value / 1024).toFixed(1)}${space ? " " : ""}Kbps`;
|
||||
};
|
||||
}
|
||||
|
||||
return (
|
||||
<Text
|
||||
x={x - 20}
|
||||
y={y}
|
||||
textAnchor="middle"
|
||||
fill={theme.palette.primary.contrastTextTertiary}
|
||||
fontSize={11}
|
||||
fontWeight={400}
|
||||
>
|
||||
{formatter(payload?.value, true)}
|
||||
</Text>
|
||||
);
|
||||
};
|
||||
|
||||
NetworkTick.propTypes = {
|
||||
x: PropTypes.number,
|
||||
y: PropTypes.number,
|
||||
payload: PropTypes.object,
|
||||
index: PropTypes.number,
|
||||
formatter: PropTypes.func,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -112,6 +156,7 @@ export const InfrastructureTooltip = ({
|
||||
yLabel,
|
||||
dotColor,
|
||||
dateRange,
|
||||
formatter = getFormattedPercentage,
|
||||
}) => {
|
||||
const uiTimezone = useSelector((state) => state.ui.timezone);
|
||||
const theme = useTheme();
|
||||
@@ -166,8 +211,8 @@ export const InfrastructureTooltip = ({
|
||||
sx={{ opacity: 0.8 }}
|
||||
>
|
||||
{yIdx >= 0
|
||||
? `${yLabel} ${getFormattedPercentage(payload[0].payload[hardwareType][yIdx][metric])}`
|
||||
: `${yLabel} ${getFormattedPercentage(payload[0].payload[yKey])}`}
|
||||
? `${yLabel} ${formatter(payload[0].payload[hardwareType][yIdx][metric])}`
|
||||
: `${yLabel} ${formatter(payload[0].payload[yKey])}`}
|
||||
</Typography>
|
||||
</Stack>
|
||||
</Box>
|
||||
File renamed without changes.
@@ -1,7 +1,7 @@
|
||||
import "./check.css";
|
||||
import PropTypes from "prop-types";
|
||||
import CheckGrey from "../../assets/icons/check.svg?react";
|
||||
import CheckOutlined from "../../assets/icons/check-outlined.svg?react";
|
||||
import CheckGrey from "../../../assets/icons/check.svg?react";
|
||||
import CheckOutlined from "../../../assets/icons/check-outlined.svg?react";
|
||||
import { Box, Stack, Typography } from "@mui/material";
|
||||
import { useTheme } from "@emotion/react";
|
||||
|
||||
@@ -51,9 +51,10 @@ const Check = ({ text, noHighlightText, variant = "info", outlined = false }) =>
|
||||
sx={{
|
||||
color:
|
||||
variant === "info"
|
||||
? theme.palette.primary.contrastTextTertiary
|
||||
? theme.palette.primary.contrastTextSecondary
|
||||
: colors[variant],
|
||||
opacity: 0.8,
|
||||
opacity: 0.9,
|
||||
fontWeight: 450,
|
||||
}}
|
||||
>
|
||||
{noHighlightText && <Typography component="span">{noHighlightText}</Typography>}{" "}
|
||||
@@ -64,7 +65,7 @@ const Check = ({ text, noHighlightText, variant = "info", outlined = false }) =>
|
||||
};
|
||||
|
||||
Check.propTypes = {
|
||||
text: PropTypes.oneOfType([PropTypes.string, PropTypes.element]).isRequired,
|
||||
text: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),
|
||||
noHighlightText: PropTypes.string,
|
||||
variant: PropTypes.oneOf(["info", "error", "success"]),
|
||||
outlined: PropTypes.bool,
|
||||
File renamed without changes.
File renamed without changes.
+1
-1
@@ -10,7 +10,7 @@ import MenuItem from "@mui/material/MenuItem";
|
||||
import Drawer from "@mui/material/Drawer";
|
||||
import MenuIcon from "@mui/icons-material/Menu";
|
||||
import CloseRoundedIcon from "@mui/icons-material/CloseRounded";
|
||||
import ThemeSwitch from "../ThemeSwitch";
|
||||
import ThemeSwitch from "../ThemeSwitch/index.jsx";
|
||||
import { useTheme } from "@mui/material/styles";
|
||||
import { useSelector } from "react-redux";
|
||||
import { useLocation, useNavigate } from "react-router-dom";
|
||||
File renamed without changes.
+8
-4
@@ -4,15 +4,14 @@ const ConfigBox = styled(Stack)(({ theme }) => ({
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
justifyContent: "space-between",
|
||||
gap: theme.spacing(20),
|
||||
backgroundColor: theme.palette.primary.main,
|
||||
border: 1,
|
||||
borderStyle: "solid",
|
||||
borderColor: theme.palette.primary.lowContrast,
|
||||
borderRadius: theme.spacing(2),
|
||||
"& > *": {
|
||||
paddingTop: theme.spacing(12),
|
||||
paddingBottom: theme.spacing(18),
|
||||
paddingTop: theme.spacing(15),
|
||||
paddingBottom: theme.spacing(15),
|
||||
},
|
||||
"& > div:first-of-type": {
|
||||
flex: 0.7,
|
||||
@@ -21,11 +20,16 @@ const ConfigBox = styled(Stack)(({ theme }) => ({
|
||||
borderRightColor: theme.palette.primary.lowContrast,
|
||||
paddingRight: theme.spacing(15),
|
||||
paddingLeft: theme.spacing(15),
|
||||
backgroundColor: theme.palette.tertiary.background,
|
||||
"& :is(h1, h2):first-of-type": {
|
||||
fontWeight: 600,
|
||||
marginBottom: theme.spacing(4),
|
||||
},
|
||||
},
|
||||
"& > div:last-of-type": {
|
||||
flex: 1,
|
||||
paddingRight: theme.spacing(20),
|
||||
paddingLeft: theme.spacing(18),
|
||||
paddingLeft: theme.spacing(20),
|
||||
},
|
||||
"& h1, & h2": {
|
||||
color: theme.palette.primary.contrastTextSecondary,
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
import { Box, Stack, Typography } from "@mui/material";
|
||||
import PropTypes from "prop-types";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import ConfigBox from "../ConfigBox";
|
||||
import ConfigBox from "../ConfigBox/index.jsx";
|
||||
|
||||
/**
|
||||
* ConfigRow is a styled container used to layout content in a row format with specific padding, border, and spacing.
|
||||
+5
-1
@@ -2,7 +2,7 @@ import { useId } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import { Modal, Stack, Typography } from "@mui/material";
|
||||
|
||||
const GenericDialog = ({ title, description, open, onClose, theme, children }) => {
|
||||
const GenericDialog = ({ title, description, open, onClose, theme, children, width }) => {
|
||||
const titleId = useId();
|
||||
const descriptionId = useId();
|
||||
const ariaDescribedBy = description?.length > 0 ? descriptionId : "";
|
||||
@@ -16,6 +16,7 @@ const GenericDialog = ({ title, description, open, onClose, theme, children }) =
|
||||
>
|
||||
<Stack
|
||||
gap={theme.spacing(2)}
|
||||
width={width}
|
||||
sx={{
|
||||
position: "absolute",
|
||||
top: "50%",
|
||||
@@ -39,6 +40,7 @@ const GenericDialog = ({ title, description, open, onClose, theme, children }) =
|
||||
fontSize={16}
|
||||
color={theme.palette.primary.contrastText}
|
||||
fontWeight={600}
|
||||
marginBottom={theme.spacing(4)}
|
||||
>
|
||||
{title}
|
||||
</Typography>
|
||||
@@ -46,6 +48,7 @@ const GenericDialog = ({ title, description, open, onClose, theme, children }) =
|
||||
<Typography
|
||||
id={descriptionId}
|
||||
color={theme.palette.primary.contrastTextTertiary}
|
||||
marginBottom={theme.spacing(4)}
|
||||
>
|
||||
{description}
|
||||
</Typography>
|
||||
@@ -64,6 +67,7 @@ GenericDialog.propTypes = {
|
||||
theme: PropTypes.object.isRequired,
|
||||
children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node])
|
||||
.isRequired,
|
||||
width: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.object]),
|
||||
};
|
||||
|
||||
export { GenericDialog };
|
||||
@@ -1,6 +1,6 @@
|
||||
import PropTypes from "prop-types";
|
||||
import { Button, Stack } from "@mui/material";
|
||||
import { GenericDialog } from "./genericDialog";
|
||||
import { GenericDialog } from "./genericDialog.jsx";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
File renamed without changes.
@@ -0,0 +1,44 @@
|
||||
import { Button, Stack } from "@mui/material";
|
||||
import { useTheme } from "@mui/material/styles";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
const FallbackActionButtons = ({ link, type }) => {
|
||||
const theme = useTheme();
|
||||
const navigate = useNavigate();
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Stack
|
||||
gap={theme.spacing(10)}
|
||||
alignItems="center"
|
||||
>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="accent"
|
||||
sx={{ fontWeight: 700 }}
|
||||
onClick={() => navigate(link)}
|
||||
>
|
||||
{t(`${type}.fallback.actionButton`)}
|
||||
</Button>
|
||||
{type === "uptimeMonitor" && (
|
||||
<Button
|
||||
variant="contained"
|
||||
color="accent"
|
||||
sx={{ alignSelf: "center" }}
|
||||
onClick={() => navigate("/uptime/bulk-import")}
|
||||
>
|
||||
{t("bulkImport.fallbackPage")}
|
||||
</Button>
|
||||
)}
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
FallbackActionButtons.propTypes = {
|
||||
title: PropTypes.string.isRequired,
|
||||
link: PropTypes.string.isRequired,
|
||||
type: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
export default FallbackActionButtons;
|
||||
@@ -0,0 +1,39 @@
|
||||
import { useTheme } from "@emotion/react";
|
||||
import Box from "@mui/material/Box";
|
||||
import Background from "../../../assets/Images/background-grid.svg?react";
|
||||
import OutputAnimation from "../../../assets/Animations/output.gif";
|
||||
import DarkmodeOutput from "../../../assets/Animations/darkmodeOutput.gif";
|
||||
import { useSelector } from "react-redux";
|
||||
const FallbackBackground = () => {
|
||||
const theme = useTheme();
|
||||
const mode = useSelector((state) => state.ui.mode);
|
||||
return (
|
||||
<>
|
||||
<Box
|
||||
component="img"
|
||||
src={mode === "light" ? OutputAnimation : DarkmodeOutput}
|
||||
background="transparent"
|
||||
alt="Loading animation"
|
||||
sx={{
|
||||
zIndex: 1,
|
||||
border: "none",
|
||||
borderRadius: theme.spacing(8),
|
||||
width: "100%",
|
||||
transform: "scale(0.6667)",
|
||||
}}
|
||||
/>
|
||||
<Box
|
||||
className="background-pattern-svg"
|
||||
sx={{
|
||||
"& svg g g:last-of-type path": {
|
||||
stroke: theme.palette.primary.lowContrast,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Background style={{ width: "100%" }} />
|
||||
</Box>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default FallbackBackground;
|
||||
@@ -0,0 +1,35 @@
|
||||
import PropTypes from "prop-types";
|
||||
import { useTheme } from "@mui/material/styles";
|
||||
import Box from "@mui/material/Box";
|
||||
import Stack from "@mui/material/Stack";
|
||||
import Check from "../Check/Check.jsx";
|
||||
const FallbackCheckList = ({ checks, type }) => {
|
||||
const theme = useTheme();
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexWrap: "wrap",
|
||||
gap: theme.spacing(2),
|
||||
alignItems: "flex-start",
|
||||
maxWidth: { xs: "90%", md: "80%", lg: "75%" },
|
||||
}}
|
||||
>
|
||||
{checks?.map((check, index) => (
|
||||
<Check
|
||||
text={check}
|
||||
key={`${type.trim().split(" ")[0]}-${index}`}
|
||||
outlined={true}
|
||||
/>
|
||||
))}
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
FallbackCheckList.propTypes = {
|
||||
checks: PropTypes.arrayOf(PropTypes.string).isRequired,
|
||||
title: PropTypes.string.isRequired,
|
||||
type: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
export default FallbackCheckList;
|
||||
@@ -0,0 +1,44 @@
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { Box, Stack } from "@mui/material";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
const FallbackContainer = ({ children, type }) => {
|
||||
const theme = useTheme();
|
||||
return (
|
||||
<Box
|
||||
border={1}
|
||||
borderColor={theme.palette.tertiary.border}
|
||||
borderRadius={theme.shape.borderRadius}
|
||||
backgroundColor={theme.palette.tertiary.background}
|
||||
overflow="hidden"
|
||||
sx={{
|
||||
display: "flex",
|
||||
borderStyle: "dashed",
|
||||
height: "fit-content",
|
||||
minHeight: "60vh",
|
||||
width: {
|
||||
sm: "90%",
|
||||
md: "70%",
|
||||
lg: "50%",
|
||||
xl: "40%",
|
||||
},
|
||||
padding: `${theme.spacing(20)} ${theme.spacing(10)}`,
|
||||
}}
|
||||
>
|
||||
<Stack
|
||||
className={`fallback__${type?.trim().split(" ")[0]}`}
|
||||
alignItems="center"
|
||||
gap={theme.spacing(20)}
|
||||
>
|
||||
{children}
|
||||
</Stack>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
FallbackContainer.propTypes = {
|
||||
children: PropTypes.node,
|
||||
type: PropTypes.string,
|
||||
};
|
||||
|
||||
export default FallbackContainer;
|
||||
@@ -0,0 +1,69 @@
|
||||
import Box from "@mui/material/Box";
|
||||
import { useTheme } from "@mui/material/styles";
|
||||
import Link from "@mui/material/Link";
|
||||
import { Link as RouterLink } from "react-router-dom";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import Alert from "../Alert/index.jsx";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
const renderWarningMessage = (t) => {
|
||||
return (
|
||||
<>
|
||||
{t("pageSpeedWarning")}{" "}
|
||||
<Link
|
||||
component={RouterLink}
|
||||
to="/settings"
|
||||
sx={{
|
||||
textDecoration: "underline",
|
||||
color: "inherit",
|
||||
fontWeight: "inherit",
|
||||
"&:hover": {
|
||||
textDecoration: "underline",
|
||||
},
|
||||
}}
|
||||
>
|
||||
{t("pageSpeedLearnMoreLink")}
|
||||
</Link>{" "}
|
||||
{t("pageSpeedAddApiKey")}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const FallbackPageSpeedWarning = ({ settingsData }) => {
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<Box sx={{ width: "80%", maxWidth: "600px", zIndex: 1 }}>
|
||||
<Box
|
||||
sx={{
|
||||
"& .alert.row-stack": {
|
||||
backgroundColor: theme.palette.warningSecondary.main,
|
||||
borderColor: theme.palette.warningSecondary.lowContrast,
|
||||
"& .MuiTypography-root": {
|
||||
color: theme.palette.warningSecondary.contrastText,
|
||||
},
|
||||
"& .MuiBox-root > svg": {
|
||||
color: theme.palette.warningSecondary.contrastText,
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
{settingsData?.pagespeedKeySet === false && (
|
||||
<Alert
|
||||
variant="warning"
|
||||
hasIcon={true}
|
||||
body={renderWarningMessage(t)}
|
||||
/>
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
FallbackPageSpeedWarning.propTypes = {
|
||||
settingsData: PropTypes.shape({
|
||||
pagespeedKeySet: PropTypes.bool,
|
||||
}),
|
||||
};
|
||||
|
||||
export default FallbackPageSpeedWarning;
|
||||
@@ -0,0 +1,21 @@
|
||||
import { useTheme } from "@mui/material/styles";
|
||||
import { Typography } from "@mui/material";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
const FallbackTitle = ({ title }) => {
|
||||
const theme = useTheme();
|
||||
return (
|
||||
<Typography
|
||||
alignSelf="center"
|
||||
component="h1"
|
||||
marginY={theme.spacing(4)}
|
||||
color={theme.palette.primary.contrastText}
|
||||
>
|
||||
{title}
|
||||
</Typography>
|
||||
);
|
||||
};
|
||||
FallbackTitle.propTypes = {
|
||||
title: PropTypes.string.isRequired,
|
||||
};
|
||||
export default FallbackTitle;
|
||||
@@ -38,7 +38,3 @@
|
||||
background-size: cover;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.fallback__status > .MuiStack-root {
|
||||
margin-left: var(--env-var-spacing-2);
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
import PropTypes from "prop-types";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { Box, Stack } from "@mui/material";
|
||||
import "./index.css";
|
||||
import FallbackTitle from "./FallbackTitle.jsx";
|
||||
import FallbackCheckList from "./FallbackCheckList.jsx";
|
||||
import FallbackActionButtons from "./FallBackActionButtons.jsx";
|
||||
import FallbackBackground from "./FallbackBackground.jsx";
|
||||
import FallbackContainer from "./FallbackContainer.jsx";
|
||||
/**
|
||||
* Fallback component to display a fallback UI with a title, a list of checks, and a navigation button.
|
||||
*
|
||||
* @param {Object} props - The component props.
|
||||
* @param {string} props.title - The title to be displayed in the fallback UI.
|
||||
* @param {string} props.type - The type of the fallback (e.g., "pageSpeed", "notifications").
|
||||
* @param {Array<string>} props.checks - An array of strings representing the checks to display.
|
||||
* @param {string} [props.link="/"] - The link to navigate to.
|
||||
* @param {boolean} [props.showPageSpeedWarning=false] - Whether to show the PageSpeed API warning.
|
||||
* @returns {JSX.Element} The rendered fallback UI.
|
||||
*/
|
||||
|
||||
const Fallback = ({ title, checks, link = "/", isAdmin, type, children }) => {
|
||||
const theme = useTheme();
|
||||
return (
|
||||
<Box
|
||||
position="relative"
|
||||
sx={{
|
||||
height: "100%",
|
||||
width: "100%",
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<FallbackContainer type={type}>
|
||||
<FallbackBackground />
|
||||
<Stack
|
||||
gap={theme.spacing(5)}
|
||||
zIndex={1}
|
||||
alignItems="center"
|
||||
>
|
||||
<FallbackTitle title={title} />
|
||||
<FallbackCheckList
|
||||
checks={checks}
|
||||
title={title}
|
||||
type={type}
|
||||
/>
|
||||
</Stack>
|
||||
{isAdmin && (
|
||||
<Stack
|
||||
gap={theme.spacing(10)}
|
||||
alignItems="center"
|
||||
>
|
||||
<FallbackActionButtons
|
||||
title={title}
|
||||
link={link}
|
||||
type={type}
|
||||
/>
|
||||
{children}
|
||||
</Stack>
|
||||
)}
|
||||
</FallbackContainer>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
Fallback.propTypes = {
|
||||
title: PropTypes.string.isRequired,
|
||||
checks: PropTypes.arrayOf(PropTypes.string).isRequired,
|
||||
link: PropTypes.string,
|
||||
isAdmin: PropTypes.bool,
|
||||
showPageSpeedWarning: PropTypes.bool,
|
||||
type: PropTypes.string.isRequired,
|
||||
children: PropTypes.node,
|
||||
};
|
||||
export default Fallback;
|
||||
File renamed without changes.
File renamed without changes.
+15
-8
@@ -1,8 +1,8 @@
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { Box, Stack } from "@mui/material";
|
||||
import Skeleton from "../../assets/Images/create-placeholder.svg?react";
|
||||
import SkeletonDark from "../../assets/Images/create-placeholder-dark.svg?react";
|
||||
import Background from "../../assets/Images/background-grid.svg?react";
|
||||
import OutputAnimation from "../../../assets/Animations/output.gif";
|
||||
import DarkmodeOutput from "../../../assets/Animations/darkmodeOutput.gif";
|
||||
import Background from "../../../assets/Images/background-grid.svg?react";
|
||||
import { useSelector } from "react-redux";
|
||||
|
||||
/**
|
||||
@@ -37,11 +37,18 @@ const GenericFallback = ({ children }) => {
|
||||
marginTop: "100px",
|
||||
}}
|
||||
>
|
||||
{mode === "light" ? (
|
||||
<Skeleton style={{ zIndex: 1 }} />
|
||||
) : (
|
||||
<SkeletonDark style={{ zIndex: 1 }} />
|
||||
)}
|
||||
<Box
|
||||
component="img"
|
||||
src={mode === "light" ? OutputAnimation : DarkmodeOutput}
|
||||
Background="transparent"
|
||||
alt="Loading animation"
|
||||
sx={{
|
||||
zIndex: 1,
|
||||
border: "none",
|
||||
borderRadius: theme.spacing(8),
|
||||
width: "100%",
|
||||
}}
|
||||
/>
|
||||
<Box
|
||||
sx={{
|
||||
"& svg g g:last-of-type path": {
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
import { logger } from "../../Utils/Logger";
|
||||
import { networkService } from "../../main";
|
||||
import { logger } from "../../../Utils/Logger.js";
|
||||
import { networkService } from "../../../main.jsx";
|
||||
|
||||
const withAdminCheck = (WrappedComponent) => {
|
||||
const WithAdminCheck = (props) => {
|
||||
File renamed without changes.
@@ -1,7 +1,7 @@
|
||||
import { Stack, Typography } from "@mui/material";
|
||||
import PropTypes from "prop-types";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import Dot from "../Dot";
|
||||
import Dot from "../Dot/index.jsx";
|
||||
/**
|
||||
* Host component.
|
||||
* This subcomponent receives a params object and displays the host details.
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
import PropTypes from "prop-types";
|
||||
import { useTheme } from "@mui/material";
|
||||
import { BaseLabel } from "../Label";
|
||||
import { BaseLabel } from "../Label/index.jsx";
|
||||
|
||||
/**
|
||||
* @component
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import i18n from "../../Utils/i18n";
|
||||
import i18n from "../../../Utils/i18n.js";
|
||||
import { useSelector } from "react-redux";
|
||||
import { useEffect } from "react";
|
||||
const I18nLoader = () => {
|
||||
File renamed without changes.
File renamed without changes.
+2
-2
@@ -1,6 +1,6 @@
|
||||
import { RowContainer } from "../StandardContainer";
|
||||
import { RowContainer } from "../StandardContainer/index.jsx";
|
||||
import { Stack, Typography } from "@mui/material";
|
||||
import Image from "../Image";
|
||||
import Image from "../Image/index.jsx";
|
||||
|
||||
import { useTheme } from "@mui/material/styles";
|
||||
|
||||
+2
-3
@@ -1,9 +1,8 @@
|
||||
import PropTypes from "prop-types";
|
||||
import { FormControlLabel, Checkbox as MuiCheckbox } from "@mui/material";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import CheckboxOutline from "../../../assets/icons/checkbox-outline.svg?react";
|
||||
import CheckboxFilled from "../../../assets/icons/checkbox-filled.svg?react";
|
||||
import "./index.css";
|
||||
import CheckboxOutline from "../../../../assets/icons/checkbox-outline.svg?react";
|
||||
import CheckboxFilled from "../../../../assets/icons/checkbox-filled.svg?react";
|
||||
|
||||
/**
|
||||
* Checkbox Component
|
||||
File renamed without changes.
@@ -0,0 +1,51 @@
|
||||
import { Stack, Typography } from "@mui/material";
|
||||
import PropTypes from "prop-types";
|
||||
import { useTheme } from "@emotion/react";
|
||||
|
||||
const DEFAULT_GAP = 6;
|
||||
const FieldWrapper = ({
|
||||
label,
|
||||
children,
|
||||
gap,
|
||||
labelMb,
|
||||
labelFontWeight = 500,
|
||||
labelVariant = "h3",
|
||||
labelSx = {},
|
||||
sx = {},
|
||||
}) => {
|
||||
const theme = useTheme();
|
||||
return (
|
||||
<Stack
|
||||
gap={gap ?? theme.spacing(DEFAULT_GAP)}
|
||||
sx={sx}
|
||||
>
|
||||
{label && (
|
||||
<Typography
|
||||
component={labelVariant}
|
||||
color={theme.palette.primary.contrastTextSecondary}
|
||||
fontWeight={labelFontWeight}
|
||||
sx={{
|
||||
...(labelMb !== undefined && { mb: theme.spacing(labelMb) }),
|
||||
...labelSx,
|
||||
}}
|
||||
>
|
||||
{label}
|
||||
</Typography>
|
||||
)}
|
||||
{children}
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
FieldWrapper.propTypes = {
|
||||
label: PropTypes.node,
|
||||
children: PropTypes.node.isRequired,
|
||||
gap: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.object]),
|
||||
labelMb: PropTypes.number,
|
||||
labelFontWeight: PropTypes.number,
|
||||
labelVariant: PropTypes.string,
|
||||
labelSx: PropTypes.object,
|
||||
sx: PropTypes.object,
|
||||
};
|
||||
|
||||
export default FieldWrapper;
|
||||
+2
-2
@@ -1,10 +1,10 @@
|
||||
// Components
|
||||
import { Box, Stack, Typography } from "@mui/material";
|
||||
import CloudUploadIcon from "@mui/icons-material/CloudUpload";
|
||||
import Image from "../../../Components/Image";
|
||||
import Image from "../../Image/index.jsx";
|
||||
import TextField from "@mui/material/TextField";
|
||||
import IconButton from "@mui/material/IconButton";
|
||||
import ProgressUpload from "../../ProgressBars";
|
||||
import ProgressUpload from "../../ProgressBars/index.jsx";
|
||||
import ImageIcon from "@mui/icons-material/Image";
|
||||
|
||||
// Utils
|
||||
File renamed without changes.
+20
-3
@@ -1,7 +1,7 @@
|
||||
import PropTypes from "prop-types";
|
||||
import { FormControlLabel, Radio as MUIRadio, Typography } from "@mui/material";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import RadioChecked from "../../../assets/icons/radio-checked.svg?react";
|
||||
import RadioChecked from "../../../../assets/icons/radio-checked.svg?react";
|
||||
import "./index.css";
|
||||
|
||||
/**
|
||||
@@ -24,7 +24,17 @@ import "./index.css";
|
||||
* @returns {JSX.Element} - The rendered Radio component.
|
||||
*/
|
||||
|
||||
const Radio = ({ name, checked, value, id, size, title, desc, onChange }) => {
|
||||
const Radio = ({
|
||||
name,
|
||||
checked,
|
||||
value,
|
||||
id,
|
||||
size,
|
||||
title,
|
||||
desc,
|
||||
onChange,
|
||||
labelSpacing,
|
||||
}) => {
|
||||
const theme = useTheme();
|
||||
|
||||
return (
|
||||
@@ -53,7 +63,14 @@ const Radio = ({ name, checked, value, id, size, title, desc, onChange }) => {
|
||||
onChange={onChange}
|
||||
label={
|
||||
<>
|
||||
<Typography component="p">{title}</Typography>
|
||||
<Typography
|
||||
component="p"
|
||||
mb={
|
||||
labelSpacing !== undefined ? theme.spacing(labelSpacing) : theme.spacing(2)
|
||||
}
|
||||
>
|
||||
{title}
|
||||
</Typography>
|
||||
<Typography
|
||||
component="h6"
|
||||
mt={theme.spacing(1)}
|
||||
Loaded 100 of 745 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user