Compare commits
1245 Commits
ae_mod_spo
...
feature/re
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a4ae1db497 | ||
|
|
90ee6bb156 | ||
|
|
83cd8d851d | ||
|
|
50936f56d7 | ||
|
|
fd73ad2e0f | ||
|
|
d447de4073 | ||
|
|
9d95b5eac9 | ||
|
|
3a544a2086 | ||
|
|
1fc58eb18f | ||
|
|
b3bad26d8f | ||
|
|
3f0ff46f51 | ||
|
|
2403b41529 | ||
|
|
484ea8c36c | ||
|
|
c1a440df6c | ||
|
|
0fcd4e4cdf | ||
|
|
b91d79c175 | ||
|
|
a68d5439bd | ||
|
|
266363b85f | ||
|
|
359d5d47f9 | ||
|
|
a1a33f794d | ||
|
|
f164caf65f | ||
|
|
0da470e7dc | ||
|
|
ce5a3535cc | ||
|
|
ee9d9a0aca | ||
|
|
8223b964e1 | ||
|
|
064942c647 | ||
|
|
65b793f663 | ||
|
|
d24e6c0400 | ||
|
|
4b1db3afff | ||
|
|
d1021e2822 | ||
|
|
bd4bd360f7 | ||
|
|
10cc435146 | ||
|
|
b3c0446440 | ||
|
|
79da9acd2f | ||
|
|
8029034e37 | ||
|
|
8f49edc1b3 | ||
|
|
b16413c3c0 | ||
|
|
f25b9ccd8f | ||
|
|
d99e9ee1b0 | ||
|
|
2e70ce312b | ||
|
|
9691ceca43 | ||
|
|
c06f50c21e | ||
|
|
1d0620085f | ||
|
|
74140f41db | ||
|
|
f7d1f304fe | ||
|
|
0be878c8c1 | ||
|
|
0987cd6ad9 | ||
|
|
6d1f9989d0 | ||
|
|
6aa97a9f6b | ||
|
|
9ea6b17617 | ||
|
|
c8c19a35a6 | ||
|
|
97d41adb12 | ||
|
|
69c34fa4bc | ||
|
|
d678f97324 | ||
|
|
691b20fd54 | ||
|
|
95412dd0ad | ||
|
|
e521bea448 | ||
|
|
d627e59bf6 | ||
|
|
390bbcb6e8 | ||
|
|
4f262149cd | ||
|
|
5c67421d7e | ||
|
|
3a0d901a05 | ||
|
|
7e1eaba3bc | ||
|
|
b99e85f1db | ||
|
|
a3b37a5df4 | ||
|
|
c4fa35e86e | ||
|
|
02169f1cb9 | ||
|
|
92ef08ce1f | ||
|
|
d554696c8e | ||
|
|
66c42a52f9 | ||
|
|
97e9f35ea1 | ||
|
|
b03376e136 | ||
|
|
7ded0fd9a6 | ||
|
|
e19b448238 | ||
|
|
3104304fdb | ||
|
|
88d36d512d | ||
|
|
7cd59bfaac | ||
|
|
13869b40bd | ||
|
|
a87fa02bc6 | ||
|
|
aef34dc79b | ||
|
|
0e960ba955 | ||
|
|
e9a8f7df00 | ||
|
|
a84d06a28d | ||
|
|
6e00502d3d | ||
|
|
de7e02b9ef | ||
|
|
94832c2471 | ||
|
|
6d8089bdbd | ||
|
|
14a69ca433 | ||
|
|
2f83aefd22 | ||
|
|
81e4d83c2d | ||
|
|
03a6661360 | ||
|
|
882b9b5bc7 | ||
|
|
cfed92e8a5 | ||
|
|
853219ce16 | ||
|
|
514dfe913c | ||
|
|
fd083faac5 | ||
|
|
4093afe4fc | ||
|
|
fb634268c1 | ||
|
|
d4ead978f9 | ||
|
|
4b4c3c5552 | ||
|
|
4d6c10cbad | ||
|
|
a995711335 | ||
|
|
bc10075314 | ||
|
|
389f0c855f | ||
|
|
db8c0e0d05 | ||
|
|
dfaa27384b | ||
|
|
848a3e9a4b | ||
|
|
e793db8d3b | ||
|
|
35031d3193 | ||
|
|
616d6a4404 | ||
|
|
d9887aba93 | ||
|
|
fab1a4916d | ||
|
|
bb993a1028 | ||
|
|
d1c0148c75 | ||
|
|
e912c4a48a | ||
|
|
8b22c0fc34 | ||
|
|
8d15a5ba0b | ||
|
|
3d6b7c412c | ||
|
|
77b250b4f3 | ||
|
|
c2ccf0c06d | ||
|
|
c170358681 | ||
|
|
9678c5620d | ||
|
|
a6058efaf0 | ||
|
|
b2154273e0 | ||
|
|
1f79ae4e19 | ||
|
|
6b8f4d54ed | ||
|
|
f459c09fbc | ||
|
|
0bc04bf899 | ||
|
|
8f7c1bf428 | ||
|
|
de071dae49 | ||
|
|
5b9dacd291 | ||
|
|
8c2241e610 | ||
|
|
74cc5c5d0d | ||
|
|
0f05fd708f | ||
|
|
41d20a3bcf | ||
|
|
bad5da3ddc | ||
|
|
28cb8e2bf2 | ||
|
|
11334a17b1 | ||
|
|
b24262b4ab | ||
|
|
e1a04d5eda | ||
|
|
00ff9554d8 | ||
|
|
d8b7ad61b3 | ||
|
|
88e4ab119d | ||
|
|
c3992d8711 | ||
|
|
cd03d9e488 | ||
|
|
9fa7247204 | ||
|
|
c4115adfd6 | ||
|
|
af9c4a82f0 | ||
|
|
c949581429 | ||
|
|
a2f2742f30 | ||
|
|
bcee6c5281 | ||
|
|
75f7ed54a5 | ||
|
|
c70abc46f3 | ||
|
|
b85d2ee98c | ||
|
|
03f831de8a | ||
|
|
b5a6c15059 | ||
|
|
4aeded3a12 | ||
|
|
f96a14107a | ||
|
|
99fe486842 | ||
|
|
53a03f971f | ||
|
|
0c01eed5c8 | ||
|
|
22d7c4728d | ||
|
|
24ba3940f8 | ||
|
|
f5e035318a | ||
|
|
c42ab0bfa0 | ||
|
|
abed17f5da | ||
|
|
1ba9cd1c03 | ||
|
|
4220a354be | ||
|
|
6f4f54a0c9 | ||
|
|
08bc3142e6 | ||
|
|
2f4800f995 | ||
|
|
5bf231c468 | ||
|
|
7490545ba7 | ||
|
|
43d64696d5 | ||
|
|
231c2eea17 | ||
|
|
79c0c90eae | ||
|
|
5b7aa320e2 | ||
|
|
f06358439f | ||
|
|
86fbbfdfb5 | ||
|
|
59b6577d68 | ||
|
|
fc4e59dd8c | ||
|
|
5527bce327 | ||
|
|
7a0ba7d571 | ||
|
|
811876e36a | ||
|
|
7fd3ef4f63 | ||
|
|
8ff9f2439f | ||
|
|
d6204d983a | ||
|
|
623b62f716 | ||
|
|
4f36d3eab3 | ||
|
|
64f6b290ad | ||
|
|
46a89c36fe | ||
|
|
6b6418b753 | ||
|
|
60fbfc434e | ||
|
|
c9e9fbec79 | ||
|
|
186923671d | ||
|
|
b1aae55900 | ||
|
|
f1b3820fde | ||
|
|
c670778ff3 | ||
|
|
15e0e423f2 | ||
|
|
c7b8d49730 | ||
|
|
32b6f59245 | ||
|
|
c530ff8683 | ||
|
|
fd3105b4e1 | ||
|
|
0931b960b6 | ||
|
|
662e19b091 | ||
|
|
01273c3c4d | ||
|
|
b78cb8eac2 | ||
|
|
bbf9411213 | ||
|
|
db95ed88a3 | ||
|
|
084e52be15 | ||
|
|
cc6186467a | ||
|
|
efa7833fb3 | ||
|
|
f842392aac | ||
|
|
438d366b98 | ||
|
|
88c4f4e891 | ||
|
|
92a00ddee9 | ||
|
|
9e78ba970b | ||
|
|
5a0b13700f | ||
|
|
bd964cac80 | ||
|
|
f72a77ba60 | ||
|
|
390bcf05a4 | ||
|
|
4fcf28f303 | ||
|
|
84b18a33ed | ||
|
|
9869c695f7 | ||
|
|
66510c8ff1 | ||
|
|
7364ce5527 | ||
|
|
a6ae701e0f | ||
|
|
711e24a7d0 | ||
|
|
acb96729d1 | ||
|
|
7136eb04d8 | ||
|
|
7bb4e20ce7 | ||
|
|
8a9864771b | ||
|
|
f3ee4ee987 | ||
|
|
6d2c3cb056 | ||
|
|
33c6cb862e | ||
|
|
edfe9dee7a | ||
|
|
ebaba77fe3 | ||
|
|
6dec20d932 | ||
|
|
35b6662b5b | ||
|
|
6f5b40d5ab | ||
|
|
565712b818 | ||
|
|
0446822779 | ||
|
|
231462e3ad | ||
|
|
496eea48ee | ||
|
|
05d7e78444 | ||
|
|
1e20539b1a | ||
|
|
0ecb9d15b0 | ||
|
|
2f19422c72 | ||
|
|
d3f71be94e | ||
|
|
a4b3d3887f | ||
|
|
6622fc4169 | ||
|
|
7ef18ce105 | ||
|
|
b95111503d | ||
|
|
5187f6455a | ||
|
|
bfe9823902 | ||
|
|
e286357c8d | ||
|
|
a789866642 | ||
|
|
d993ca5938 | ||
|
|
0a4940161d | ||
|
|
9ed4bd85e1 | ||
|
|
93804c23d7 | ||
|
|
dfd39ae8c9 | ||
|
|
4568d63620 | ||
|
|
9d72337d43 | ||
|
|
4861ae0499 | ||
|
|
8504f4b79a | ||
|
|
1f024d70f3 | ||
|
|
ced62cfd99 | ||
|
|
5410717dcd | ||
|
|
47eb745f3b | ||
|
|
1e94043e19 | ||
|
|
7d07879e21 | ||
|
|
1d840052c7 | ||
|
|
2e39c5f67b | ||
|
|
e962d629a3 | ||
|
|
a3999e5617 | ||
|
|
b54f43be35 | ||
|
|
ee0e108322 | ||
|
|
0ac7bea046 | ||
|
|
fd69610a3a | ||
|
|
eb396b0a55 | ||
|
|
047f6d7048 | ||
|
|
eaffc44772 | ||
|
|
32c3be9983 | ||
|
|
03c0dd6d13 | ||
|
|
a378f92c58 | ||
|
|
fa5de6e7df | ||
|
|
a52cc3808b | ||
|
|
7b853ede8c | ||
|
|
8692771efb | ||
|
|
6c79be7179 | ||
|
|
de2b5db21a | ||
|
|
37bcb7940d | ||
|
|
3e36100b9b | ||
|
|
84138943a6 | ||
|
|
bd10d98ada | ||
|
|
20ad1370e2 | ||
|
|
bcd42412f4 | ||
|
|
299d5b71c3 | ||
|
|
e23999d728 | ||
|
|
b133aa1285 | ||
|
|
6e4649882c | ||
|
|
1e35681116 | ||
|
|
ea30697ffb | ||
|
|
8bf9d488cd | ||
|
|
770e48842b | ||
|
|
b030c0eec4 | ||
|
|
06cf665b06 | ||
|
|
8a80bb1a2f | ||
|
|
4f6684e2bd | ||
|
|
8bd42d1896 | ||
|
|
d97e6e74aa | ||
|
|
628659f348 | ||
|
|
6bdedecfd8 | ||
|
|
8672796bac | ||
|
|
ef291f4be0 | ||
|
|
3c404acdfd | ||
|
|
fcefcc510b | ||
|
|
32c1899cb6 | ||
|
|
b028bd7b32 | ||
|
|
2eb4ddf1eb | ||
|
|
1d08f960b0 | ||
|
|
b675cad43d | ||
|
|
f0fae620ea | ||
|
|
cc8bbffdbf | ||
|
|
07979cb529 | ||
|
|
429403ced6 | ||
|
|
dba6ac9e3b | ||
|
|
d3a2485970 | ||
|
|
40061b92ca | ||
|
|
25de3407fd | ||
|
|
f8461f367e | ||
|
|
50deb79f6b | ||
|
|
a691e7d22d | ||
|
|
238416d903 | ||
|
|
ec7ec7b566 | ||
|
|
2d66984581 | ||
|
|
088b32e4f1 | ||
|
|
a6edc461f3 | ||
|
|
4c0b1d4c50 | ||
|
|
e87fae34f8 | ||
|
|
74a098fbde | ||
|
|
fbcebcf816 | ||
|
|
9914fd1700 | ||
|
|
bd0d96cb83 | ||
|
|
4ef2e7cd6b | ||
|
|
71b2de27ce | ||
|
|
1f46b51c9a | ||
|
|
ce59a848d6 | ||
|
|
b34f4bb3ce | ||
|
|
55dc2ab48c | ||
|
|
c947e9e77a | ||
|
|
370396a633 | ||
|
|
7cb8639230 | ||
|
|
dde9801fe6 | ||
|
|
7b4ec1fe7e | ||
|
|
c47019ddba | ||
|
|
d86558caa0 | ||
|
|
db4c061f19 | ||
|
|
357e135451 | ||
|
|
2816c09003 | ||
|
|
626f0f2351 | ||
|
|
0b345e325e | ||
|
|
1ad1251931 | ||
|
|
e93c70e0e4 | ||
|
|
b59dcf20d5 | ||
|
|
40cba6d841 | ||
|
|
574eb8c635 | ||
|
|
4e63c8418e | ||
|
|
0bccaa226f | ||
|
|
eebcd7c731 | ||
|
|
e5d41a7467 | ||
|
|
b8a8653e0a | ||
|
|
93ffb8c3ad | ||
|
|
94ccbd5f96 | ||
|
|
00322aee89 | ||
|
|
e18400d597 | ||
|
|
09dc471842 | ||
|
|
f68a64b1f8 | ||
|
|
38e88d7b27 | ||
|
|
1e0c6ec91b | ||
|
|
9617071361 | ||
|
|
0d4885b778 | ||
|
|
376837950e | ||
|
|
13912fd145 | ||
|
|
db6e9dd019 | ||
|
|
e6394549bf | ||
|
|
2b65c0ff16 | ||
|
|
f126abf39d | ||
|
|
61c78fc641 | ||
|
|
487af455d0 | ||
|
|
1d31d9d671 | ||
|
|
88d856ab2c | ||
|
|
e0f0b774ef | ||
|
|
8c51380fb5 | ||
|
|
c10abd596e | ||
|
|
39a878ac38 | ||
|
|
4c1449bb8f | ||
|
|
ac81aadd6f | ||
|
|
8c9f0afc02 | ||
|
|
bed4b9f70e | ||
|
|
dbbd8209cc | ||
|
|
f38d9b58ab | ||
|
|
83ff5681d6 | ||
|
|
695a520eb3 | ||
|
|
8279fab244 | ||
|
|
b97e4002bc | ||
|
|
a2e4c710a0 | ||
|
|
eb32ae1eaa | ||
|
|
72522ceef4 | ||
|
|
454ec2ea5d | ||
|
|
e8acce6c43 | ||
|
|
6c496992aa | ||
|
|
f6426eb574 | ||
|
|
23f182b964 | ||
|
|
240855f649 | ||
|
|
82af7a00e5 | ||
|
|
5cf076fbe3 | ||
|
|
7c70d93a68 | ||
|
|
589320a850 | ||
|
|
c4d95e1c6a | ||
|
|
14f4adeafa | ||
|
|
a75f40bf8d | ||
|
|
6b585090d0 | ||
|
|
15d417ba52 | ||
|
|
83a8377155 | ||
|
|
2976d618f8 | ||
|
|
9af5c960f7 | ||
|
|
f2059da9d1 | ||
|
|
f88e6cef89 | ||
|
|
8b68b0d2bb | ||
|
|
83d52b4e79 | ||
|
|
3041246638 | ||
|
|
ec404ab428 | ||
|
|
616cf2890c | ||
|
|
170eeef877 | ||
|
|
10fba7fef6 | ||
|
|
40ce368e59 | ||
|
|
bae46782d6 | ||
|
|
cc354100ae | ||
|
|
49139b3a1f | ||
|
|
698459c207 | ||
|
|
e794a4c23a | ||
|
|
53856a913b | ||
|
|
72fb34e3f1 | ||
|
|
dae482906d | ||
|
|
ffa33b5fa0 | ||
|
|
211945828d | ||
|
|
2be4da1172 | ||
|
|
c46c670e87 | ||
|
|
372cafeb01 | ||
|
|
42a813dc52 | ||
|
|
238757782b | ||
|
|
e96675174f | ||
|
|
24e1190874 | ||
|
|
5232c88a45 | ||
|
|
b5642583c7 | ||
|
|
3b38c31ba0 | ||
|
|
52be5ac1f7 | ||
|
|
247773235e | ||
|
|
b2b006249b | ||
|
|
e008950411 | ||
|
|
5ef6d7dc0c | ||
|
|
dc7da8c930 | ||
|
|
8f1f7bfa7e | ||
|
|
8c81f6f65e | ||
|
|
0e249b2e6d | ||
|
|
74cf6b7ca8 | ||
|
|
df3b455c18 | ||
|
|
7af1d41ff3 | ||
|
|
2ff7b4fd70 | ||
|
|
86221e6aec | ||
|
|
cdc4ee1af9 | ||
|
|
7ea65ee495 | ||
|
|
4b939d0ca0 | ||
|
|
5bfb3892e6 | ||
|
|
de740e1e37 | ||
|
|
89822ef540 | ||
|
|
13b8255055 | ||
|
|
a27fdd5fc4 | ||
|
|
66b122dca5 | ||
|
|
0b61596833 | ||
|
|
8f515e034b | ||
|
|
77c53065bc | ||
|
|
f2751cbaf9 | ||
|
|
c6d21fadc2 | ||
|
|
9687fe0c90 | ||
|
|
63cb0f2969 | ||
|
|
81e322b98b | ||
|
|
70cf91b9ee | ||
|
|
122669aabf | ||
|
|
9e4a67941e | ||
|
|
4906e45b61 | ||
|
|
15cb0aa0c5 | ||
|
|
d7a1c03beb | ||
|
|
a76cc93acf | ||
|
|
58bf335502 | ||
|
|
d256abc9b3 | ||
|
|
007eb4ec9f | ||
|
|
f2384f2714 | ||
|
|
be9c67e667 | ||
|
|
6094d5a79d | ||
|
|
cbb73ed3fd | ||
|
|
12167a3bc6 | ||
|
|
8c3f05a2ed | ||
|
|
b5a4a38514 | ||
|
|
6314d8f6e6 | ||
|
|
9bfb6580f2 | ||
|
|
f1dc6bd3dc | ||
|
|
15ee3da76d | ||
|
|
7c30b163b1 | ||
|
|
3ad1fa429a | ||
|
|
d29d325af5 | ||
|
|
1828b0f141 | ||
|
|
6d235d9159 | ||
|
|
ccba530223 | ||
|
|
1e099a275b | ||
|
|
622e0db3d7 | ||
|
|
fb937290eb | ||
|
|
35b4079b90 | ||
|
|
204f2ed988 | ||
|
|
3d2ff02f8c | ||
|
|
1f10b64d13 | ||
|
|
f55931d0e3 | ||
|
|
a851c5fe64 | ||
|
|
d274e37e37 | ||
|
|
3a47b77641 | ||
|
|
2133fa520e | ||
|
|
c4c657081f | ||
|
|
c29cee4511 | ||
|
|
3df0739e96 | ||
|
|
bb84b4bbb4 | ||
|
|
deef453580 | ||
|
|
9adcc6d54c | ||
|
|
bd1ceee1ad | ||
|
|
2515ba5577 | ||
|
|
3587258ec7 | ||
|
|
b505424c9d | ||
|
|
adda3e79c5 | ||
|
|
e1848dddb5 | ||
|
|
10c3e34b38 | ||
|
|
0d8b47af10 | ||
|
|
73eee7b8ff | ||
|
|
b967eed0a5 | ||
|
|
6e41833f82 | ||
|
|
e022645f64 | ||
|
|
2ab026611f | ||
|
|
32553ca429 | ||
|
|
98676dffd9 | ||
|
|
ca2c5c7baf | ||
|
|
f59a159712 | ||
|
|
ee5bd83673 | ||
|
|
14d68e2a5d | ||
|
|
bd4de70ac8 | ||
|
|
2575a57ba7 | ||
|
|
304c1e4123 | ||
|
|
56502981d3 | ||
|
|
376f77ad8f | ||
|
|
e653d4d92a | ||
|
|
7fa0d5cc5b | ||
|
|
b9f4189a95 | ||
|
|
b4f2be0f13 | ||
|
|
0e72d27dbd | ||
|
|
7f1759ed4b | ||
|
|
f6449b48e6 | ||
|
|
a41ecb45a9 | ||
|
|
d393ed2c7a | ||
|
|
f423345e42 | ||
|
|
aaaa0da1f9 | ||
|
|
8539ccc2f4 | ||
|
|
1059cf5683 | ||
|
|
b37db30368 | ||
|
|
d424ec24c1 | ||
|
|
b393427651 | ||
|
|
a19f6fe97e | ||
|
|
d8d6728659 | ||
|
|
a9351b4143 | ||
|
|
00f3d6087f | ||
|
|
4715d13dda | ||
|
|
f45540a31f | ||
|
|
db762a3c91 | ||
|
|
8826ebf92f | ||
|
|
35354a9d0f | ||
|
|
596986afb7 | ||
|
|
7fde0abb16 | ||
|
|
0f22ad0584 | ||
|
|
253a1c59d6 | ||
|
|
42ac7911f2 | ||
|
|
6749ecc4c3 | ||
|
|
c96e59c660 | ||
|
|
39d0a210f3 | ||
|
|
ab055beaff | ||
|
|
b62a267ee8 | ||
|
|
d8020b3d77 | ||
|
|
183d431e1d | ||
|
|
f4bd387ed9 | ||
|
|
8acb4a8c7b | ||
|
|
87b1859b0b | ||
|
|
643edbd50a | ||
|
|
3719739b57 | ||
|
|
75c7a29ae4 | ||
|
|
33bc99c2bd | ||
|
|
7e92613536 | ||
|
|
6e330a639e | ||
|
|
89b14c877e | ||
|
|
3078e33b97 | ||
|
|
ed89776a60 | ||
|
|
75d7a502f0 | ||
|
|
fc517540dc | ||
|
|
cb19031989 | ||
|
|
bdea373c7f | ||
|
|
acff856e25 | ||
|
|
a9c96c905a | ||
|
|
c62507d484 | ||
|
|
db6b481983 | ||
|
|
8b309d7b04 | ||
|
|
6f11820857 | ||
|
|
9dc4540329 | ||
|
|
7414cba165 | ||
|
|
5d6df59ee1 | ||
|
|
321c48513f | ||
|
|
8d4c770f19 | ||
|
|
106e655574 | ||
|
|
e921f3a785 | ||
|
|
aa893b5ea6 | ||
|
|
b64f4b01ad | ||
|
|
f8e88b0355 | ||
|
|
641c6b28c3 | ||
|
|
ff6e240a37 | ||
|
|
ea115b6ac1 | ||
|
|
92af1a5962 | ||
|
|
b64e7a6b8a | ||
|
|
69abe2e906 | ||
|
|
91e6556933 | ||
|
|
f89183685a | ||
|
|
47394d67ca | ||
|
|
5977df38a7 | ||
|
|
f024ccbe0c | ||
|
|
066bd66178 | ||
|
|
24931de306 | ||
|
|
3fef19488c | ||
|
|
eee8a67235 | ||
|
|
c96fb7bf00 | ||
|
|
3946e17300 | ||
|
|
c63ef94b77 | ||
|
|
0f29682874 | ||
|
|
9813d0544f | ||
|
|
af743f6e73 | ||
|
|
90c5b9414f | ||
|
|
aaa6eaa433 | ||
|
|
1bdd2aec65 | ||
|
|
747e9fdb26 | ||
|
|
b3dfb5deec | ||
|
|
c34e62a0c5 | ||
|
|
6d94583885 | ||
|
|
971ffbad02 | ||
|
|
0032d52ff9 | ||
|
|
e4797e178d | ||
|
|
c6631e221c | ||
|
|
44907bc01f | ||
|
|
940a7e9a21 | ||
|
|
1f6793927b | ||
|
|
aeeb08ab36 | ||
|
|
a0473cb50b | ||
|
|
b7515f0680 | ||
|
|
058c88c766 | ||
|
|
c0fe69ea73 | ||
|
|
12b761e127 | ||
|
|
5796ff09a1 | ||
|
|
4c09edaceb | ||
|
|
dd8181ba0e | ||
|
|
7ba11a104d | ||
|
|
1868adad99 | ||
|
|
6a79cb165d | ||
|
|
42aa9d356f | ||
|
|
2f4e707e58 | ||
|
|
fbb45d50a7 | ||
|
|
24a75d509f | ||
|
|
5ff63aa267 | ||
|
|
7e3420ec4d | ||
|
|
600bf7caa4 | ||
|
|
d1f04e4dc3 | ||
|
|
2ef3c8bab5 | ||
|
|
cffde76c88 | ||
|
|
fcec4ed96f | ||
|
|
e4485f2bda | ||
|
|
1d713db712 | ||
|
|
ec837c415a | ||
|
|
b8b86a5561 | ||
|
|
125ce32ddd | ||
|
|
f6378c1a23 | ||
|
|
6b60c14159 | ||
|
|
fd602a46ac | ||
|
|
e220653f45 | ||
|
|
acf0a169ab | ||
|
|
90a74e5ce7 | ||
|
|
9ded8f7c7e | ||
|
|
185709e67a | ||
|
|
bf29856f6b | ||
|
|
e2d67087ce | ||
|
|
9a681455ca | ||
|
|
fea392eff7 | ||
|
|
fc8ee53724 | ||
|
|
89885f9571 | ||
|
|
b0ae649824 | ||
|
|
9a1d022d5a | ||
|
|
31272a8985 | ||
|
|
28880f3160 | ||
|
|
77cc152837 | ||
|
|
d1f37af192 | ||
|
|
01e320e172 | ||
|
|
6b34b806b2 | ||
|
|
53deb5edcc | ||
|
|
a3a8f107d3 | ||
|
|
547845ed62 | ||
|
|
0fd06ef216 | ||
|
|
bd5c8a0867 | ||
|
|
6a390762d3 | ||
|
|
40081c2804 | ||
|
|
26faf50058 | ||
|
|
804fddcb5a | ||
|
|
789c0d651e | ||
|
|
dfd43963bb | ||
|
|
8df0bdf0cc | ||
|
|
53f2f5dbc5 | ||
|
|
4fe6194450 | ||
|
|
7040578ac5 | ||
|
|
26e1c89f1b | ||
|
|
34bcd9dd2d | ||
|
|
fedbbe9ae2 | ||
|
|
1e1a4f1016 | ||
|
|
5d8a3a782e | ||
|
|
791454b8fa | ||
|
|
f4538720b2 | ||
|
|
e6a9a5ceab | ||
|
|
13d906428b | ||
|
|
4fe04d9c3f | ||
|
|
abcd5c54c2 | ||
|
|
b93cacdfcc | ||
|
|
079ec80fbd | ||
|
|
d3609764e3 | ||
|
|
b381cbbc9e | ||
|
|
7e6b00c0eb | ||
|
|
594074a1dd | ||
|
|
6a609646cc | ||
|
|
94babed805 | ||
|
|
14d4be848a | ||
|
|
d0c4ef2179 | ||
|
|
80965167a5 | ||
|
|
b9698615be | ||
|
|
4d667d57a4 | ||
|
|
cf997601f4 | ||
|
|
ac7016bb3e | ||
|
|
4d2a78f80f | ||
|
|
23b82291a0 | ||
|
|
63f5168015 | ||
|
|
ee7f981e2e | ||
|
|
deac79b861 | ||
|
|
2d047f5a10 | ||
|
|
8ec01a1d64 | ||
|
|
26b3c53847 | ||
|
|
4f65374d7e | ||
|
|
19ce353a26 | ||
|
|
79e83c26a7 | ||
|
|
80e7cecbf1 | ||
|
|
a211570af9 | ||
|
|
2ebb411905 | ||
|
|
9c3fe62724 | ||
|
|
07c0b569ca | ||
|
|
cc084a32cf | ||
|
|
cfd78145f6 | ||
|
|
b9d4f47f3a | ||
|
|
2d644aafe8 | ||
|
|
295fa1b49a | ||
|
|
789d4f96e0 | ||
|
|
5da209ee1c | ||
|
|
488031f90c | ||
|
|
de24f0dc80 | ||
|
|
172763bc26 | ||
|
|
67b01c5884 | ||
|
|
a0d5a97d48 | ||
|
|
7d9950fd70 | ||
|
|
a2b7dd9450 | ||
|
|
63fea17472 | ||
|
|
590d274910 | ||
|
|
deac7bd574 | ||
|
|
3c957692c3 | ||
|
|
67a4fbe17e | ||
|
|
9160591fc4 | ||
|
|
2ae3fb07eb | ||
|
|
1c7518ad3f | ||
|
|
9a951ee365 | ||
|
|
1189e2e877 | ||
|
|
79a74db4ae | ||
|
|
7450edfdcf | ||
|
|
4ec440146e | ||
|
|
e2a510ceaa | ||
|
|
115751bcd7 | ||
|
|
ca2658a324 | ||
|
|
338c9b9b23 | ||
|
|
5037579abe | ||
|
|
980e8850be | ||
|
|
ec2c37b715 | ||
|
|
9093cc9957 | ||
|
|
79bc148e85 | ||
|
|
6694ec92c7 | ||
|
|
c130e82fd0 | ||
|
|
bd48596176 | ||
|
|
816db5281d | ||
|
|
d5ac26f0ef | ||
|
|
f9b3b3a0eb | ||
|
|
a6b9115865 | ||
|
|
0799f9a1ab | ||
|
|
c3f4832f48 | ||
|
|
03e6117024 | ||
|
|
ccb36ca953 | ||
|
|
2ac495af8e | ||
|
|
820c151750 | ||
|
|
aef469ad9d | ||
|
|
b6cd3f59e5 | ||
|
|
7b84e1c1fc | ||
|
|
0f49afec12 | ||
|
|
d6d4c88728 | ||
|
|
bb27942b52 | ||
|
|
89dd410aeb | ||
|
|
1004104de0 | ||
|
|
0e7df79bab | ||
|
|
581749ff41 | ||
|
|
a189a1c336 | ||
|
|
1c1845280b | ||
|
|
fad58bf26f | ||
|
|
47e9f9f5a1 | ||
|
|
cca43b957a | ||
|
|
d7284d5010 | ||
|
|
35c901f144 | ||
|
|
58928d07eb | ||
|
|
6a8148228f | ||
|
|
d6c26e7511 | ||
|
|
495dd0e6d9 | ||
|
|
25a28d4ff6 | ||
|
|
894c84b857 | ||
|
|
8b6f171506 | ||
|
|
5311e4704f | ||
|
|
0f40629bfe | ||
|
|
702da83ce5 | ||
|
|
32ca117b11 | ||
|
|
283850e917 | ||
|
|
514f36d998 | ||
|
|
cc4446b549 | ||
|
|
8005189bc4 | ||
|
|
41706fbcd7 | ||
|
|
6dc89083ec | ||
|
|
267b5052c9 | ||
|
|
9e6a7f0db0 | ||
|
|
476b303da4 | ||
|
|
bd2583fde3 | ||
|
|
80b394f16b | ||
|
|
36283a215b | ||
|
|
a92f8a486e | ||
|
|
f9e156e862 | ||
|
|
37c40ff4fc | ||
|
|
2cf1ea39a8 | ||
|
|
63f17e111b | ||
|
|
e46fa59a40 | ||
|
|
ce476f9a65 | ||
|
|
04b549b874 | ||
|
|
fd152cc27e | ||
|
|
86b309f048 | ||
|
|
04fd046c53 | ||
|
|
e95191d43a | ||
|
|
3b56223be3 | ||
|
|
77b14a387e | ||
|
|
527d1f82b7 | ||
|
|
1e3086560d | ||
|
|
9fd84183d7 | ||
|
|
f9c3fe4b21 | ||
|
|
d122d1fb93 | ||
|
|
c7b48ca97a | ||
|
|
1faf7fb18f | ||
|
|
3a6c462155 | ||
|
|
2a3e386f6f | ||
|
|
c711b29bea | ||
|
|
be58d87faf | ||
|
|
59eed57dec | ||
|
|
3d34e30c63 | ||
|
|
896fb76cc6 | ||
|
|
7e610ead67 | ||
|
|
e7e532f61a | ||
|
|
9fd9f61ddb | ||
|
|
e3b808a0e0 | ||
|
|
225dd678a5 | ||
|
|
0ae86593cd | ||
|
|
792c496d46 | ||
|
|
faf37f8159 | ||
|
|
5b8121bfc7 | ||
|
|
32f24f8ffa | ||
|
|
eacd40ac21 | ||
|
|
bf5bdd4a3e | ||
|
|
5fcae3b047 | ||
|
|
8b913b73f8 | ||
|
|
86dc7797e0 | ||
|
|
d5d28149ad | ||
|
|
917cca09ce | ||
|
|
3919347383 | ||
|
|
5aaaaa164d | ||
|
|
e6694718e7 | ||
|
|
9a0112e884 | ||
|
|
acf89f3fa5 | ||
|
|
4881fcf7f2 | ||
|
|
4fa8d0368f | ||
|
|
014d244019 | ||
|
|
4dbdd16bd0 | ||
|
|
45d7cba562 | ||
|
|
fed37a77b8 | ||
|
|
d8edd658b0 | ||
|
|
5139a706d0 | ||
|
|
608bef7f21 | ||
|
|
c61d3a4dca | ||
|
|
4871464adf | ||
|
|
722acdaa59 | ||
|
|
1d496eb769 | ||
|
|
75b0e53114 | ||
|
|
6aa499c79b | ||
|
|
fefd7c8027 | ||
|
|
85138e7b44 | ||
|
|
68727d24cf | ||
|
|
fa55e96be2 | ||
|
|
b0e15700b5 | ||
|
|
37801ca769 | ||
|
|
ca563fdf1f | ||
|
|
fed5d2de65 | ||
|
|
f58cd9611b | ||
|
|
7d167444c4 | ||
|
|
5208480614 | ||
|
|
f674503b21 | ||
|
|
002c283c68 | ||
|
|
46cc89ad92 | ||
|
|
f209f3ce37 | ||
|
|
ef62b30dc9 | ||
|
|
fdca94b625 | ||
|
|
f526e9094c | ||
|
|
35052898b4 | ||
|
|
146bea0a67 | ||
|
|
cc4588c8a6 | ||
|
|
0ec9cbbd08 | ||
|
|
be81122e4e | ||
|
|
56c16bef10 | ||
|
|
380a8d2ad3 | ||
|
|
0d48362529 | ||
|
|
efedc88ade | ||
|
|
ca2dc11206 | ||
|
|
bdfb276199 | ||
|
|
06a1d7a771 | ||
|
|
53fea0d25d | ||
|
|
37b2145f81 | ||
|
|
e83623526c | ||
|
|
3639342356 | ||
|
|
00fcd8e747 | ||
|
|
d5dbeeabf7 | ||
|
|
df36727540 | ||
|
|
074cf154f2 | ||
|
|
d7dfef4fe0 | ||
|
|
9a1995dd9f | ||
|
|
30e6384772 | ||
|
|
14fc1ee146 | ||
|
|
4ddc775aaa | ||
|
|
4141524d83 | ||
|
|
f407565fc7 | ||
|
|
cb1f4343db | ||
|
|
ccd91571ce | ||
|
|
75ee8e1b5c | ||
|
|
7aebf24996 | ||
|
|
0d34f81fa7 | ||
|
|
352639e702 | ||
|
|
8d7627fd36 | ||
|
|
40293e25b4 | ||
|
|
bf31a3f596 | ||
|
|
ff498ed49e | ||
|
|
2177f6c379 | ||
|
|
98d09bac76 | ||
|
|
e0e380e450 | ||
|
|
e7b7948b06 | ||
|
|
cf9f914412 | ||
|
|
2fca5b2c3b | ||
|
|
f8b53baee8 | ||
|
|
86c8aa6c83 | ||
|
|
4a70869896 | ||
|
|
0ca8da1a6e | ||
|
|
d756059ad4 | ||
|
|
6b9284951e | ||
|
|
8b53cd2b7f | ||
|
|
fdb435cd1e | ||
|
|
37c51cee29 | ||
|
|
274b599ff1 | ||
|
|
98849427d9 | ||
|
|
027d7a781d | ||
|
|
c41be23995 | ||
|
|
b0633a5c24 | ||
|
|
b2293784e0 | ||
|
|
af17a05022 | ||
|
|
a6f8f00e9e | ||
|
|
070e714aff | ||
|
|
43488b8f76 | ||
|
|
d16c47fedf | ||
|
|
064bba3d62 | ||
|
|
625169a321 | ||
|
|
ad1e42010a | ||
|
|
997f470ebe | ||
|
|
47c742d004 | ||
|
|
945c943c61 | ||
|
|
7eb3080f46 | ||
|
|
1bf90f128f | ||
|
|
8f2eb2c27e | ||
|
|
4aae2bead4 | ||
|
|
270a1429f8 | ||
|
|
a2d3d5b1f7 | ||
|
|
26a0a1dbd6 | ||
|
|
889500e80d | ||
|
|
d8e062b8c7 | ||
|
|
a1515ba6b6 | ||
|
|
27bed2f532 | ||
|
|
f4006e7226 | ||
|
|
afbe396caf | ||
|
|
aae19249d4 | ||
|
|
d410953ce4 | ||
|
|
40aba339f8 | ||
|
|
ed89c61aed | ||
|
|
6d06347e0a | ||
|
|
acc39ecb50 | ||
|
|
861107c2fd | ||
|
|
245757b501 | ||
|
|
88b0042919 | ||
|
|
9de9d31101 | ||
|
|
acaff7634d | ||
|
|
9f7a19c4b9 | ||
|
|
e6aec67247 | ||
|
|
4183c9022c | ||
|
|
298f87960a | ||
|
|
a0085723c9 | ||
|
|
d01ab2479f | ||
|
|
2d490d8058 | ||
|
|
a34d2af18e | ||
|
|
12c778c7e2 | ||
|
|
37ac30c56c | ||
|
|
8c8748b571 | ||
|
|
20e1c46461 | ||
|
|
4d7e48a170 | ||
|
|
dd9c48e801 | ||
|
|
7faa9d0459 | ||
|
|
6a22f84f23 | ||
|
|
b604eaee56 | ||
|
|
68d376b88d | ||
|
|
0090058238 | ||
|
|
a62ea7dc8d | ||
|
|
21ad9d900c | ||
|
|
4ad51b8e0b | ||
|
|
384f91bbe7 | ||
|
|
58a975bfe9 | ||
|
|
c6b7c7e803 | ||
|
|
0c4185f74c | ||
|
|
31ba1c9200 | ||
|
|
5211f83f23 | ||
|
|
ecf2b3eca8 | ||
|
|
e5cff89acb | ||
|
|
87b4f22bb1 | ||
|
|
2552e1a839 | ||
|
|
fd114bce22 | ||
|
|
991cb1e9da | ||
|
|
d49f73583c | ||
|
|
8c52722408 | ||
|
|
06add80718 | ||
|
|
5ef2d05e9c | ||
|
|
baf354fd46 | ||
|
|
8044cd0723 | ||
|
|
519525540c | ||
|
|
97f15f41f7 | ||
|
|
06df9a6230 | ||
|
|
65daf86cc7 | ||
|
|
37547a96d8 | ||
|
|
0156426f4b | ||
|
|
58d25e922c | ||
|
|
6bcc554737 | ||
|
|
84f6f1eda8 | ||
|
|
b368abc91a | ||
|
|
987e411956 | ||
|
|
bbd403b96d | ||
|
|
98cd149d2c | ||
|
|
7cd71299b3 | ||
|
|
87ef4cc6b9 | ||
|
|
8b201a68ed | ||
|
|
359c147167 | ||
|
|
d9ff625db6 | ||
|
|
0005ba7dc9 | ||
|
|
42fef3feb8 | ||
|
|
fa58d1accb | ||
|
|
f72d7be5b2 | ||
|
|
a3a32e188d | ||
|
|
94d0cfeb4d | ||
|
|
69c1250961 | ||
|
|
2aff1aadbe | ||
|
|
ca04e9739f | ||
|
|
38e73cb40c | ||
| a87b4d53a0 | |||
| f8e81bf7e4 | |||
| d242948d7e | |||
| 21ee101007 | |||
| 2b61b8f4a5 | |||
| ab268532da | |||
| 920dd176fe | |||
| 5411df5893 | |||
| ab906e4af1 | |||
| 46dcd389a4 | |||
| f405d1b3b7 | |||
| 0aae7f9361 | |||
| a51e96ea6e | |||
| f68bccddb9 | |||
| 4460b38098 | |||
| 8e6ab2c223 | |||
| d64a20e5b3 | |||
| f5ab1cecc1 | |||
| ef583e1328 | |||
| 9eee2a928b | |||
| 1ae1a3d989 | |||
| bde3229270 | |||
| 02af46a48f | |||
|
|
562479313d | ||
|
|
a5b0720933 | ||
|
|
847fad3151 | ||
|
|
16f65cf85f | ||
|
|
5671423467 | ||
|
|
8d2f4e30f4 | ||
|
|
9c85914b9f | ||
|
|
ae1764579e | ||
|
|
b5588fd9a1 | ||
|
|
1555f0f8d0 | ||
|
|
3abe92a2dc | ||
|
|
78b5fc1068 | ||
|
|
841367afeb | ||
|
|
0e26765312 | ||
|
|
c0e1d666f4 | ||
|
|
7a4a4cab5e | ||
|
|
741878172c | ||
|
|
2b1b2b7d07 | ||
|
|
9851c69c30 | ||
|
|
86972f5a02 | ||
|
|
b7bf152366 | ||
|
|
7cc23077f3 | ||
|
|
b336f18512 | ||
|
|
378ae11224 | ||
|
|
8d8fb0b638 | ||
|
|
3082c07e3e | ||
|
|
a8a2131361 | ||
|
|
a30690ea2a | ||
|
|
f20c6ef706 | ||
|
|
4d486a580c | ||
|
|
040e1e71e3 | ||
|
|
54fb837581 | ||
|
|
3ddef770c0 | ||
|
|
b0f2e2ccdf | ||
|
|
f97c83db03 | ||
|
|
742205b84b | ||
|
|
976f4fe8c0 | ||
|
|
cd79213b37 | ||
|
|
18c1c84044 | ||
|
|
7381797a28 | ||
|
|
c490bca265 | ||
|
|
e21b7ef584 | ||
|
|
84e3098b72 | ||
|
|
fbbaa1392b | ||
|
|
19d2dd630b | ||
|
|
e4687aab2f | ||
|
|
d3ae087cd6 | ||
|
|
9b02b2f86c | ||
|
|
7d86a9b40f | ||
|
|
0400aa429b | ||
|
|
68b0efb6c9 | ||
|
|
20b42ac6aa | ||
|
|
a97e5666a7 | ||
|
|
8bf1892bc7 | ||
|
|
3f664eb5c0 | ||
|
|
3c30664b2b | ||
|
|
fd4f2bdf35 | ||
|
|
7d1a4b735b | ||
|
|
a5431070d3 | ||
|
|
ef2597d114 | ||
|
|
1559bae11c | ||
|
|
b6ba167a86 | ||
|
|
4136c08cdb | ||
|
|
875f327c90 | ||
|
|
b53566aa41 | ||
|
|
d9ee195590 | ||
|
|
409872ed4d | ||
|
|
2ada1419d8 | ||
|
|
5a147a98bb | ||
|
|
1694dfb5c5 | ||
|
|
ff00ec5c91 | ||
|
|
c6abc0abca | ||
|
|
b020ded01c | ||
|
|
aa712284ce | ||
|
|
e71cdab353 | ||
|
|
bed4f4a0f2 | ||
|
|
19a6ff6dbe | ||
|
|
6c60ee3086 | ||
|
|
a0947e349a | ||
|
|
04a8b49177 | ||
|
|
63990bb36a | ||
|
|
60f6386415 | ||
|
|
7051cb92d5 | ||
|
|
64589ec11c | ||
|
|
1b12cd4aec | ||
|
|
4db9e68543 | ||
|
|
0dbf869d5d | ||
|
|
e69ff969f5 | ||
|
|
ff90fa5287 | ||
|
|
f09577d1d5 | ||
|
|
9fe4c51a67 | ||
|
|
f4ed04497e | ||
|
|
b21f9c0437 | ||
|
|
873e6d9f9a | ||
|
|
e713313aca | ||
|
|
addadacc47 | ||
|
|
9310aac4d2 | ||
|
|
2c7e7ca027 | ||
|
|
713fcb3c62 | ||
|
|
00a28588b7 | ||
|
|
ed97cba7a6 | ||
|
|
714642380e | ||
|
|
22efa3fd96 | ||
|
|
c93d84f3c3 | ||
|
|
9540aefd50 | ||
|
|
060c0500d3 | ||
|
|
740baa689e | ||
|
|
02f693c13e | ||
|
|
d1328eb67c | ||
|
|
5a13852432 | ||
|
|
d51d059535 | ||
|
|
5bb9134641 | ||
|
|
3403210efd | ||
|
|
6f0680f282 | ||
|
|
bab68af7dc | ||
|
|
9958724aaa | ||
|
|
cb9bd1648c | ||
|
|
a3d4354ef4 | ||
|
|
19f9983c9a | ||
|
|
17d99d080c |
@@ -1,5 +1,5 @@
|
||||
[Dolphin]
|
||||
Timestamp=2024,2,6,18,10,21.847
|
||||
Timestamp=2024,8,7,10,25,9.632
|
||||
Version=4
|
||||
ViewMode=1
|
||||
|
||||
|
||||
43
.env.prod.default
Normal file
43
.env.prod.default
Normal file
@@ -0,0 +1,43 @@
|
||||
# One Sky IT's Aether Framework and System
|
||||
TESTING=This is a test env variable
|
||||
PUBLIC_TESTING=This is a public test env variable
|
||||
|
||||
CONTAINER_AE_APP_NODE=ae_app_node_prod
|
||||
CONTAINER_AE_APP_NODE_RED=ae_app_node_prod_red
|
||||
CONTAINER_AE_APP_NODE_GREEN=ae_app_node_prod_green
|
||||
CONTAINER_AE_APP_NODE_BLUE=ae_app_node_prod_blue
|
||||
OSIT_WEB_HTTP_PORT=8082
|
||||
OSIT_WEB_HTTPS_PORT=4435
|
||||
|
||||
# DOCKER_AE_SERVER_EXTRA_HOST=srv-nyx.oneskyit.com:104.237.143.4
|
||||
# DOCKER_AE_API_SERVER_EXTRA_HOST=api.oneskyit.com:104.237.143.4
|
||||
# DOCKER_AE_API_BAK_SERVER_EXTRA_HOST=bak-api.oneskyit.com:104.237.143.4
|
||||
|
||||
# Aether general shared config options
|
||||
# For general shared config options like API access and use, database access and use, Redis, and SMTP
|
||||
# home development, live testing, live production, onsite development, onsite testing, onsite production???
|
||||
AE_CFG_ID=7
|
||||
|
||||
## Aether API access and use
|
||||
PUBLIC_AE_API_PROTOCOL=https
|
||||
PUBLIC_AE_API_SERVER=api.oneskyit.com
|
||||
PUBLIC_AE_API_BAK_SERVER=bak-api.oneskyit.com
|
||||
PUBLIC_AE_API_SERVER_INTERNAL=aether_api_gunicorn
|
||||
PUBLIC_AE_API_PORT=443
|
||||
PUBLIC_AE_API_PATH=
|
||||
PUBLIC_AE_API_SECRET_KEY=XXXX
|
||||
PUBLIC_AE_API_CRUD_SUPER_KEY=XXXX
|
||||
PUBLIC_AE_NO_ACCOUNT_ID=No_Account_ID_Here
|
||||
PUBLIC_AE_NO_ACCOUNT_ID_TOKEN=Nothing_to_see_here
|
||||
|
||||
# Aether app specific config (SvelteKit)
|
||||
AE_APP_CFG_ID=99
|
||||
AE_APP_ENV=development
|
||||
AE_APP_NODE_PORT=3001
|
||||
AE_APP_NODE_PORT_RED=3002
|
||||
AE_APP_NODE_PORT_GREEN=3003
|
||||
AE_APP_NODE_PORT_BLUE=3004
|
||||
|
||||
PUBLIC_AE_ACCOUNT_ID=XXXX # OSIT = _XY7DXtc9MY; CHOW = 3Iid1aIRY5j
|
||||
PUBLIC_AE_EVENT_ID=XXXX # OSIT = pjrcghqwert; CHOW = Mw6-Nv-Zf-5A
|
||||
PUBLIC_AE_SPONSORSHIP_CFG_ID=XXXX # OSIT = t8jdjONCs0k; CHOW = ygjEuQQCzvk
|
||||
45
.env.staging.default
Normal file
45
.env.staging.default
Normal file
@@ -0,0 +1,45 @@
|
||||
# One Sky IT's Aether Framework and System
|
||||
TESTING=This is a test env variable
|
||||
PUBLIC_TESTING=This is a public test env variable
|
||||
|
||||
CONTAINER_AE_APP_NODE=ae_app_node_prod
|
||||
CONTAINER_AE_APP_NODE_RED=ae_app_node_prod_red
|
||||
CONTAINER_AE_APP_NODE_GREEN=ae_app_node_prod_green
|
||||
CONTAINER_AE_APP_NODE_BLUE=ae_app_node_prod_blue
|
||||
OSIT_WEB_HTTP_PORT=8082
|
||||
OSIT_WEB_HTTPS_PORT=4435
|
||||
|
||||
# DOCKER_AE_SERVER_EXTRA_HOST=srv-nyx.oneskyit.com:104.237.143.4
|
||||
# DOCKER_AE_API_SERVER_EXTRA_HOST=dev-api.oneskyit.com:192.168.32.20 # Odd because this env is the development server
|
||||
# DOCKER_AE_API_SERVER_EXTRA_HOST=dev-api.oneskyit.com:192.168.32.99 # Odd because this env is the development server
|
||||
# DOCKER_AE_API_BAK_SERVER_EXTRA_HOST=test-api.oneskyit.com:104.237.143.4 # Odd because this env is the development server
|
||||
# DOCKER_AE_API_TEST_SERVER_EXTRA_HOST=test-api.oneskyit.com:104.237.143.4
|
||||
|
||||
# Aether general shared config options
|
||||
# For general shared config options like API access and use, database access and use, Redis, and SMTP
|
||||
# home development, live testing, live production, onsite development, onsite testing, onsite production???
|
||||
AE_CFG_ID=5
|
||||
|
||||
## Aether API access and use
|
||||
PUBLIC_AE_API_PROTOCOL=https
|
||||
PUBLIC_AE_API_SERVER=dev-api.oneskyit.com
|
||||
PUBLIC_AE_API_BAK_SERVER=test-api.oneskyit.com
|
||||
PUBLIC_AE_API_SERVER_INTERNAL=aether_api_gunicorn
|
||||
PUBLIC_AE_API_PORT=443
|
||||
PUBLIC_AE_API_PATH=
|
||||
PUBLIC_AE_API_SECRET_KEY=dFP6J9DVj9hUgIMn-fNIqg
|
||||
PUBLIC_AE_API_CRUD_SUPER_KEY=zp5PtX4zUsI
|
||||
PUBLIC_AE_NO_ACCOUNT_ID=No_Account_ID_Here
|
||||
PUBLIC_AE_NO_ACCOUNT_ID_TOKEN=Nothing_to_see_here
|
||||
|
||||
# Aether app specific config (SvelteKit)
|
||||
AE_APP_CFG_ID=99
|
||||
AE_APP_ENV=development
|
||||
AE_APP_NODE_PORT=3001
|
||||
AE_APP_NODE_PORT_RED=3002
|
||||
AE_APP_NODE_PORT_GREEN=3003
|
||||
AE_APP_NODE_PORT_BLUE=3004
|
||||
|
||||
PUBLIC_AE_ACCOUNT_ID=XXXX # OSIT = _XY7DXtc9MY; CHOW = 3Iid1aIRY5j
|
||||
PUBLIC_AE_EVENT_ID=XXXX # OSIT = pjrcghqwert; CHOW = Mw6-Nv-Zf-5A
|
||||
PUBLIC_AE_SPONSORSHIP_CFG_ID=XXXX # OSIT = t8jdjONCs0k; CHOW = ygjEuQQCzvk
|
||||
13
.eslintignore
Normal file
13
.eslintignore
Normal file
@@ -0,0 +1,13 @@
|
||||
.DS_Store
|
||||
node_modules
|
||||
/build
|
||||
/.svelte-kit
|
||||
/package
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
|
||||
# Ignore files for PNPM, NPM and YARN
|
||||
pnpm-lock.yaml
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
31
.eslintrc.cjs
Normal file
31
.eslintrc.cjs
Normal file
@@ -0,0 +1,31 @@
|
||||
/** @type { import("eslint").Linter.Config } */
|
||||
module.exports = {
|
||||
root: true,
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'plugin:svelte/recommended',
|
||||
'prettier'
|
||||
],
|
||||
parser: '@typescript-eslint/parser',
|
||||
plugins: ['@typescript-eslint'],
|
||||
parserOptions: {
|
||||
sourceType: 'module',
|
||||
ecmaVersion: 2020,
|
||||
extraFileExtensions: ['.svelte']
|
||||
},
|
||||
env: {
|
||||
browser: true,
|
||||
es2017: true,
|
||||
node: true
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: ['*.svelte'],
|
||||
parser: 'svelte-eslint-parser',
|
||||
parserOptions: {
|
||||
parser: '@typescript-eslint/parser'
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
38
.gitignore
vendored
38
.gitignore
vendored
@@ -1,27 +1,33 @@
|
||||
.DS_Store
|
||||
.directory
|
||||
node_modules
|
||||
/build
|
||||
/.svelte-kit
|
||||
/package
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
!.env.prod.default
|
||||
!.env.staging.default
|
||||
vite.config.js.timestamp-*
|
||||
vite.config.ts.timestamp-*
|
||||
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
*.log.*
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
|
||||
# Backups and archives
|
||||
*.bak
|
||||
*.tar.gz
|
||||
backups/
|
||||
|
||||
# Temporary files
|
||||
tmp/
|
||||
temp/
|
||||
*.kate-swp
|
||||
4
.prettierignore
Normal file
4
.prettierignore
Normal file
@@ -0,0 +1,4 @@
|
||||
# Ignore files for PNPM, NPM and YARN
|
||||
pnpm-lock.yaml
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
9
.prettierrc
Normal file
9
.prettierrc
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"useTabs": false,
|
||||
"tabWidth": 4,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "none",
|
||||
"printWidth": 100,
|
||||
"plugins": ["prettier-plugin-svelte"],
|
||||
"overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }]
|
||||
}
|
||||
3
.vscode/extensions.json
vendored
3
.vscode/extensions.json
vendored
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"recommendations": ["svelte.svelte-vscode"]
|
||||
}
|
||||
122
.vscode/settings.json
vendored
Normal file
122
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,122 @@
|
||||
{
|
||||
"prettier.documentSelectors": ["**/*.svelte"],
|
||||
"tailwindCSS.classAttributes": [
|
||||
"class",
|
||||
"accent",
|
||||
"active",
|
||||
"animIndeterminate",
|
||||
"aspectRatio",
|
||||
"background",
|
||||
"badge",
|
||||
"bgBackdrop",
|
||||
"bgDark",
|
||||
"bgDrawer",
|
||||
"bgLight",
|
||||
"blur",
|
||||
"border",
|
||||
"button",
|
||||
"buttonAction",
|
||||
"buttonBack",
|
||||
"buttonClasses",
|
||||
"buttonComplete",
|
||||
"buttonDismiss",
|
||||
"buttonNeutral",
|
||||
"buttonNext",
|
||||
"buttonPositive",
|
||||
"buttonTextCancel",
|
||||
"buttonTextConfirm",
|
||||
"buttonTextFirst",
|
||||
"buttonTextLast",
|
||||
"buttonTextNext",
|
||||
"buttonTextPrevious",
|
||||
"buttonTextSubmit",
|
||||
"caretClosed",
|
||||
"caretOpen",
|
||||
"chips",
|
||||
"color",
|
||||
"controlSeparator",
|
||||
"controlVariant",
|
||||
"cursor",
|
||||
"display",
|
||||
"element",
|
||||
"fill",
|
||||
"fillDark",
|
||||
"fillLight",
|
||||
"flex",
|
||||
"flexDirection",
|
||||
"gap",
|
||||
"gridColumns",
|
||||
"height",
|
||||
"hover",
|
||||
"inactive",
|
||||
"indent",
|
||||
"justify",
|
||||
"meter",
|
||||
"padding",
|
||||
"position",
|
||||
"regionAnchor",
|
||||
"regionBackdrop",
|
||||
"regionBody",
|
||||
"regionCaption",
|
||||
"regionCaret",
|
||||
"regionCell",
|
||||
"regionChildren",
|
||||
"regionChipList",
|
||||
"regionChipWrapper",
|
||||
"regionCone",
|
||||
"regionContent",
|
||||
"regionControl",
|
||||
"regionDefault",
|
||||
"regionDrawer",
|
||||
"regionFoot",
|
||||
"regionFootCell",
|
||||
"regionFooter",
|
||||
"regionHead",
|
||||
"regionHeadCell",
|
||||
"regionHeader",
|
||||
"regionIcon",
|
||||
"regionInput",
|
||||
"regionInterface",
|
||||
"regionInterfaceText",
|
||||
"regionLabel",
|
||||
"regionLead",
|
||||
"regionLegend",
|
||||
"regionList",
|
||||
"regionListItem",
|
||||
"regionNavigation",
|
||||
"regionPage",
|
||||
"regionPanel",
|
||||
"regionRowHeadline",
|
||||
"regionRowMain",
|
||||
"regionSummary",
|
||||
"regionSymbol",
|
||||
"regionTab",
|
||||
"regionTrail",
|
||||
"ring",
|
||||
"rounded",
|
||||
"select",
|
||||
"shadow",
|
||||
"slotDefault",
|
||||
"slotFooter",
|
||||
"slotHeader",
|
||||
"slotLead",
|
||||
"slotMessage",
|
||||
"slotMeta",
|
||||
"slotPageContent",
|
||||
"slotPageFooter",
|
||||
"slotPageHeader",
|
||||
"slotSidebarLeft",
|
||||
"slotSidebarRight",
|
||||
"slotTrail",
|
||||
"spacing",
|
||||
"text",
|
||||
"track",
|
||||
"transition",
|
||||
"width",
|
||||
"zIndex"
|
||||
],
|
||||
"explorer.fileNesting.enabled": false,
|
||||
"cSpell.words": [
|
||||
"prejoin"
|
||||
]
|
||||
}
|
||||
216
GEMINI.md
Normal file
216
GEMINI.md
Normal file
@@ -0,0 +1,216 @@
|
||||
# Aether (AE) SvelteKit Application
|
||||
|
||||
This project is a Svelte and SvelteKit based application, part of the Aether (AE) system. It uses Tailwind CSS and Skeleton for styling and some elements. This is the frontend UI/UX. The backend API uses Python FastAPI.
|
||||
|
||||
Core Aether modules
|
||||
|
||||
- accounts - client account, not user account
|
||||
- hosted_files
|
||||
- people
|
||||
- users
|
||||
- sites and site_domains
|
||||
|
||||
Additional Aether modules
|
||||
|
||||
- events
|
||||
- presentation management - import the program data (events, session, presentations, presenters, event files, locations/rooms, devices)
|
||||
- launcher - Technically this is used with presentation management. It is part of the native app that uses Electron. One of the libraries is for functions that only work when the site is opened in an Electron app. For example the regular browser can not move files around on the local computer or run local commands.
|
||||
- badge printing
|
||||
- lead retrieval - attendee tracking; QR codes
|
||||
- journals - journal, documentation, notes, diary, blog, etc
|
||||
- idaa - One of my clients
|
||||
|
||||
## Documentation
|
||||
|
||||
- TODO.md
|
||||
- Svelte - Introducing runes - https://svelte.dev/blog/runes
|
||||
- Svelte - Breaking changes in runes mode - https://svelte.dev/docs/svelte/v5-migration-guide#Breaking-changes-in-runes-mode
|
||||
- Dexie.js - Getting Started - https://dexie.org/docs/Tutorial/Getting-started
|
||||
- Dexie.js - API Quick Reference - https://dexie.org/docs/API-Reference#quick-reference
|
||||
|
||||
## Ignored Directories
|
||||
|
||||
The following directories are ignored for various operations (e.g., search, file listing) to focus on relevant source code:
|
||||
|
||||
- `build`
|
||||
- `node_modules`
|
||||
- `tests`
|
||||
|
||||
## Development Guidelines
|
||||
|
||||
### Svelte v5 and SvelteKit
|
||||
|
||||
This project uses Svelte v5 with runes enabled. This introduces significant differences from Svelte v4. It is critical to adhere to v5 conventions to avoid bugs.
|
||||
|
||||
- **Reactivity:** State is managed with `$state` and `$derived`. Props can be made two-way bindable with `$bindable`. Avoid direct mutation of props.
|
||||
- **Event Handling (Updated 2025-11-20):**
|
||||
- **DOM Events:** Use the lowercase `onevent` attribute (e.g., `onclick`, `oninput`). Event modifiers like `|preventDefault` may not work as expected; handle prevention logic inside the function (e.g., `event.preventDefault()`).
|
||||
- **Component Events:** Continue to use the `on:eventname` directive for events dispatched from child components.
|
||||
- **Stores and `liveQuery`:**
|
||||
- To access the value of a store in Svelte v5, you must use the `$store_name` syntax (e.g., `$ae_api`).
|
||||
- Dexie `liveQuery` returns an observable. To use it in a component, you must subscribe to it within `onMount` to avoid SSR errors. The value from the subscription should then be assigned to a `$state` variable.
|
||||
- **Migration Guide:** For a comprehensive overview of the changes, refer to the official [Svelte 5 Migration Guide](https://svelte.dev/docs/svelte/v5-migration-guide).
|
||||
|
||||
### ID Convention: `id` vs. `id_random`
|
||||
|
||||
- **Always use `id_random`:** The API returns both a numeric `id` and a string-based `[obj_type]_id_random`. For all frontend operations (routing, data fetching, local storage), you **must** use the `_id_random` string.
|
||||
- **Local Storage:** When saving an object to the local IndexedDB (Dexie), the `id_random` value should be aliased to both `id` (as the primary key) and `[obj_type]_id`. This ensures consistency with Dexie's expectations and the rest of the application's data access patterns.
|
||||
|
||||
---
|
||||
|
||||
## Refactoring Notes
|
||||
|
||||
### Data Fetching & Processing Pattern (2025-11-20)
|
||||
|
||||
A standard pattern for fetching, processing, and caching data has been established to ensure consistency and separation of concerns.
|
||||
|
||||
1. **API Function (`load_*`, `search_*`, etc.):** This function is responsible for interacting with the API. It takes parameters needed for the API call (e.g., `event_id`, search strings).
|
||||
2. **Data Processor (`process_ae_obj__*_props`):** The API function's results are immediately passed to this dedicated processor function for the specific object type.
|
||||
- The API function MUST pass any necessary contextual data (like a parent `event_id`) to the processor.
|
||||
- The processor is responsible for all data shaping and enrichment before the data is cached.
|
||||
3. **Handling API Inconsistencies:** The processor is the designated location for handling any inconsistencies in the data returned by the API.
|
||||
- **Example (`event_badge`):** The `search__event_badge` API endpoint does not include the `event_id` in its results. The `process_ae_obj__event_badge_props` function now accepts the `event_id` as a parameter and injects it into each badge object before it's saved. This centralizes the fix and keeps the API-calling function clean.
|
||||
4. **Database Caching (`db_save_ae_obj_li__ae_obj`):** After processing, the clean and consistent data is passed to the generic `db_save` function to be cached in IndexedDB.
|
||||
|
||||
This pattern isolates API logic from data shaping logic, making the code more modular, predictable, and easier to debug.
|
||||
|
||||
### `process_ae_obj__*_props()` Refactoring (2025-11-13)
|
||||
|
||||
The `process_ae_obj__*_props()` family of functions, which are responsible for transforming API data for frontend use, have been refactored to standardize their structure and improve maintainability.
|
||||
|
||||
The refactoring strategy involved creating a local, non-exported `_process_generic_props` helper function within each module (`ae_journals`, `ae_events`, `ae_archives`, `ae_posts`, `ae_core`). This approach was chosen to avoid altering the module import graph, which had previously caused a critical `InternalError: module record has unexpected status: New` in the SvelteKit development server when a shared utility file was introduced.
|
||||
|
||||
**Key aspects of the refactoring:**
|
||||
|
||||
- **In-file Generic Helper (`_process_generic_props`):** This function handles common data transformations:
|
||||
- **`*_random` ID Aliasing:** It automatically iterates over object keys and creates a non-suffixed alias for any key ending in `_random` (e.g., `person_id_random` becomes `person_id`). This is crucial for client-side logic that expects standard ID fields.
|
||||
- **`tmp_sort` Field Generation:** It creates a set of basic `tmp_sort` fields for client-side sorting.
|
||||
|
||||
- **`specific_processor` Callback:** Module-specific logic is handled by a `specific_processor` callback function passed to the `_process_generic_props` helper. This allows for:
|
||||
- **Unique `tmp_sort` Logic:** Modules can override the default `tmp_sort` fields with their own specific sorting requirements.
|
||||
- **Content Processing:** Asynchronous operations like Markdown parsing (using `marked.parse`) are handled within the `specific_processor` for the relevant modules (e.g., `ae_journals__journal_entry.ts`).
|
||||
- **Other Special Cases:** Any other module-specific data transformations are handled in this callback.
|
||||
|
||||
- **`core__crud_generic.ts` Cleanup:** The generic CRUD functions in `src/lib/ae_core/core__crud_generic.ts` were simplified:
|
||||
- The `process_ae_obj__props` function in this file was deprecated.
|
||||
- All calls to `process_ae_obj__props` and `db_save_ae_obj_li__ae_obj` were removed from the generic CRUD functions (`load_ae_obj_id`, `load_ae_obj_li`, etc.).
|
||||
- These functions are now responsible only for API interaction, delegating all data processing and caching to the module-specific functions that call them. This enforces a cleaner separation of concerns.
|
||||
|
||||
### Tiptap to CodeMirror Migration (2025-11-17)
|
||||
|
||||
The rich text editor component, previously based on Tiptap (`shad-editor`), has been replaced with a CodeMirror-based solution. This change was driven by the complexity of Tiptap and its compatibility issues with Tailwind CSS, aiming for a simpler, markdown-focused editing experience.
|
||||
|
||||
**Key aspects of the migration:**
|
||||
|
||||
- **Removal of Tiptap:** All `@tiptap/*` and `svelte-tiptap` dependencies were removed from `package.json`, and the `src/lib/components/shad-editor/` directory was deleted.
|
||||
- **CodeMirror Integration:** A new CodeMirror component (`src/lib/elements/element_codemirror_editor.svelte`) was created, providing basic markdown formatting capabilities.
|
||||
- **Wrapper Component Update:** The existing editor wrapper (`src/lib/elements/element_tiptap_editor.svelte`) was renamed to `src/lib/elements/element_codemirror_wrapper.svelte` and refactored to utilize the new CodeMirror component. Tiptap-specific logic and props were removed.
|
||||
- **Component Usage Updates:** All Svelte components that previously imported and used the Tiptap wrapper were updated to import `element_codemirror_wrapper.svelte`. Unsupported props such as `default_minimal`, `show_button_kv`, `bind:new_html`, and `bind:changed` were removed from their usage.
|
||||
- **Dependency Cleanup:** `npm install` was run to remove unneeded packages, and `npm run format` was executed to ensure consistent code style.
|
||||
|
||||
### CodeMirror Bug Fixes (2025-11-18)
|
||||
|
||||
Following the initial migration to CodeMirror, several issues were identified and resolved:
|
||||
|
||||
- **Initialization Errors:** An "Unrecognized extension value" error was fixed by refactoring `codemirror_modules.ts` to explicitly import individual CodeMirror extensions instead of relying on the `basicSetup` bundle. This ensures proper singleton usage and prevents module duplication.
|
||||
- **Text Wrapping:** The `EditorView.lineWrapping` extension was added to `element_codemirror_editor.svelte` and `e_app_codemirror_v5.svelte` to enable text wrapping.
|
||||
- **Content Saving:** Content binding issues were resolved in various IDAA components by correctly binding the `html_text` prop of the CodeMirror wrapper to the corresponding state variables.
|
||||
- **Save Button Enablement:** The logic for enabling the "Save" button was fixed in `ae_idaa_comp__post_obj_id_edit.svelte` to correctly detect changes in the CodeMirror editor.
|
||||
- **Editor Buttons:** A `TypeError` in the editor's formatting buttons was fixed by using `EditorSelection.range()` to correctly create selection ranges.
|
||||
- **Component Renaming:** The `Tiptap_editor` component alias was renamed to `CodeMirror_wrapper` across the project for clarity, and the wrapper file was renamed to `element_codemirror_editor_wrapper.svelte`.
|
||||
|
||||
### Badge Search Refactoring (2025-11-18)
|
||||
|
||||
The new Badge Search functionality was refactored to resolve several issues related to Svelte 5 reactivity and IndexedDB schema design.
|
||||
|
||||
- **Svelte 5 Reactivity Fixes:**
|
||||
- A `store_invalid_shape` error was fixed by removing the `$` prefix from Svelte 5 state variables in templates.
|
||||
- A Svelte 5 compilation error (`illegal variable name`) was resolved by using `$derived` to create a local reactive variable from a store.
|
||||
- A 500 Internal Error was resolved by moving Dexie `liveQuery` calls into an `onMount` block to ensure they only run on the client-side.
|
||||
- **IndexedDB Schema Refactoring:**
|
||||
- The primary key for the `badge` table was changed from a numeric `id` to the string-based `event_badge_id_random`.
|
||||
- All related components were updated to use the new primary key for data retrieval, allowing for more efficient lookups using `get()` and `bulkGet()`.
|
||||
- **Data Flow Simplification:**
|
||||
- The badge search data flow was refactored to pass full badge objects from the search component to the list component, simplifying the logic and resolving reactivity issues.
|
||||
- **Link Generation:**
|
||||
- Badge links were updated to use the string-based random IDs for both the event and the badge, ensuring consistency and avoiding the exposure of internal numeric IDs.
|
||||
|
||||
### Event Settings Page (2025-11-18)
|
||||
|
||||
A new event settings page was created at `/events/[event_id]/settings` to provide a user-friendly interface for managing event configurations.
|
||||
|
||||
**Key features:**
|
||||
|
||||
- **Form-Based UI:** Instead of raw JSON editing, the page uses form-based components for editing event properties. This includes basic event fields (name, code, dates, etc.) and the JSON configuration fields (`cfg_json`, `mod_pres_mgmt_json`, `mod_badges_json`, `mod_abstracts_json`).
|
||||
- **Collapsible Sections:** Each configuration section is wrapped in a `<details>` element, allowing them to be collapsed and expanded for better organization.
|
||||
- **View Toggling:** For the JSON configuration fields, a toggle switch allows the user to switch between the form-based UI and a raw JSON editor (using CodeMirror), providing flexibility for both simple and advanced editing.
|
||||
- **Svelte 5 Reactivity:** The components were built using Svelte 5's `bindable` props to ensure proper two-way data binding between the parent page and the child form components. This corrected an issue where changes in the child components were not being reflected in the parent's state.
|
||||
|
||||
### API Payload Cleaning (2025-11-19)
|
||||
|
||||
To address issues with the Aether API's strict handling of `POST` and `PATCH` request payloads, a more robust solution for cleaning data on the frontend has been implemented.
|
||||
|
||||
- **Svelte 5 Event Handlers:** Corrected the use of `on:click` to `onclick` in the event settings components to align with Svelte 5 conventions.
|
||||
- **Payload Cleaning:**
|
||||
- The `update_ae_obj__event` function in `src/lib/ae_events/ae_events__event.ts` was modified to remove read-only fields (`id`, `event_id`, `created_on`, `updated_on`, etc.) from the payload before sending it to the API.
|
||||
- The function now also correctly renames `account_id` to `account_id_random` to match the API's expectations.
|
||||
- **Editable Fields Whitelist:**
|
||||
- A new file, `src/lib/ae_events/ae_events__event.editable_fields.ts`, was created to define a whitelist of fields that are allowed to be sent in `POST` and `PATCH` requests for an event.
|
||||
- The `create_ae_obj__event` and `update_ae_obj__event` functions now use this whitelist to filter the `data_kv` object, ensuring only allowed fields are sent to the API. This provides a more maintainable and less error-prone way to manage which fields are sent to the API.
|
||||
- **Component Cleanup:** The temporary pre-cleaning logic from the `handle_save` function in `src/routes/events/[event_id]/settings/+page.svelte` has been removed, as the filtering is now handled centrally in `ae_events__event.ts`.
|
||||
- **Future Work:** This pattern of using a whitelist for editable fields will be applied to all other Aether object types to ensure consistent and correct API interactions across the application.
|
||||
|
||||
### Badge Search v3 Bug-Fixing Session (2025-11-19)
|
||||
|
||||
This session focused on resolving a series of cascading build and runtime errors that prevented the new "Badges v3" feature from loading and functioning correctly.
|
||||
|
||||
- **Initial State:** The page was failing with a `Cannot use <!-- Import failed: variant - ENOENT: no such file or directory, access '/home/scott/OSIT_dev/ae_app_svelte_tailwind_skeleton/variant' --> with unknown variant: md` error, caused by a conflict between Skeleton UI's CSS and the project's Tailwind CSS v4 configuration.
|
||||
- **Misguided Fix & Reversal:** An initial attempt to fix this by removing all global Skeleton UI CSS imports from `app.css` resolved the `@variant` error but broke site-wide styling, causing errors like `Cannot apply unknown utility class 'preset-tonal-secondary'`. The Skeleton imports were subsequently restored to stabilize the application.
|
||||
- **Svelte v5 Event Syntax:** A significant amount of time was spent incorrectly attempting to "fix" Svelte v5 event handlers. The correct understanding was eventually established:
|
||||
- **DOM Events:** Use the `onevent` prefix (e.g., `onclick`).
|
||||
- **Component Events:** Continue to use the `on:event` directive (e.g., `on:success`).
|
||||
- **Invalid Attribute Name Error:** An error (`'onsubmit|preventDefault' is not a valid attribute name`) was discovered in the new badge forms. This was resolved by removing the `|preventDefault` modifier from the `onsubmit` attribute and instead calling `event.preventDefault()` inside the handler function. This appears to be a nuance or bug in how the Svelte v5 compiler handles modifiers with the new `on` prefix.
|
||||
- **Svelte 5 Binding Error:** A runtime error, `props_invalid_value: Cannot do bind:prop={undefined}`, was fixed. It was caused by binding a parent component's `undefined` store value to a child component's prop that had a fallback. The fix involved adding a defensive initialization check directly in the parent component's `<script>` block to ensure the store value was not `undefined` before rendering. Using `onMount` was attempted first but proved incorrect as it runs too late in the lifecycle.
|
||||
- **API Fetch Error:** The final blocker was a `TypeError: NetworkError` during badge searches. This was traced to the `order_by_li` parameter being sent to the API in a format that was causing the `fetch` request to be aborted by the browser (likely due to a CORS preflight failure). The immediate fix, identified by the user, was to comment out the `order_by_li` parameter in the `search__event_badge` function call within `src/lib/ae_events/ae_events__event_badge.ts`.
|
||||
- **Git Issues:** A strange issue was encountered where `git add` commands were not successfully staging files, leading to multiple failed commit attempts. This resolved itself without a clear cause.
|
||||
|
||||
## UI Library Compatibility Re-evaluation (Current Focus - 2025-12-08)
|
||||
|
||||
**Context:** The project has been rolled back to a commit (`90ee6bb1`) where the application was "mostly working" with updated `skeletonlabs` packages. Previous attempts to update `tailwindcss` to v4 and `flowbite-svelte` alongside `skeletonlabs` led to dependency conflicts and build failures.
|
||||
|
||||
**New Strategy:** Instead of immediately abandoning existing UI libraries (Skeleton, Flowbite), we will re-evaluate their compatibility with the current Svelte v5 and Tailwind CSS v4 setup in a phased, cautious manner.
|
||||
|
||||
**Phase 1: Re-evaluate SkeletonLabs Compatibility (Primary Focus)**
|
||||
|
||||
**Rationale:** Skeleton UI appears to be the most deeply integrated UI library in the project. If it can be made to work, it will significantly reduce the need for custom component development.
|
||||
|
||||
1. **Create a new Git branch:** Name it `feature/re_evaluate_ui_libs`. (Pending)
|
||||
2. **Identify latest compatible `@skeletonlabs/skeleton` and `skeleton-svelte` versions:**
|
||||
* Consult their official documentation, release notes, and GitHub issues for compatibility with **Svelte v5** and **Tailwind CSS v4**.
|
||||
* Determine if there's a specific version range that is known to work.
|
||||
3. **Attempt to update SkeletonLabs packages (one at a time, or as a pair if tightly coupled):**
|
||||
* Modify `package.json` to specify the identified compatible versions of `@skeletonlabs/skeleton` and `@skeletonlabs/skeleton-svelte`.
|
||||
* Run `npm install`.
|
||||
* Run `npm run build` and `npm run dev`.
|
||||
* **Crucially:** Thoroughly check for *all* types of errors:
|
||||
* Terminal errors (build, compilation, server-side).
|
||||
* Browser console errors (client-side JS, hydration).
|
||||
* Visual regressions or missing styles.
|
||||
* **Document findings:** Note down exact errors or success status.
|
||||
4. **If successful:** If SkeletonLabs works without major issues, proceed to Phase 2.
|
||||
5. **If unsuccessful:** If significant conflicts or errors persist, revert changes on the branch and document the specific incompatibilities. This would then lead to immediately pursuing custom UI component implementation.
|
||||
|
||||
**Phase 2: Address Other UI Library Needs (Conditional, based on Phase 1 outcome)**
|
||||
|
||||
1. **If SkeletonLabs is working:**
|
||||
* Re-evaluate the need for `flowbite-svelte`. Is its functionality still required, or is it covered by Skeleton UI or can be easily done with pure Tailwind?
|
||||
* If still needed, attempt to update `flowbite-svelte` to the latest version, following the same cautious approach as with SkeletonLabs (package.json update, `npm install`, full testing).
|
||||
2. **If SkeletonLabs (and/or Flowbite) cannot be made to work with Svelte v5 / Tailwind v4:**
|
||||
* **Prioritize Custom Component Implementation:** Immediately proceed with implementing custom replacements, starting with critical components. The `element_modal_v1.svelte` (which was partially developed before the rollback) is a prime candidate for immediate completion and integration.
|
||||
* **Identify other critical missing UI components:** Systematically list other essential components (e.g., dropdowns, tabs, accordions, cards, forms elements) that were previously provided by these libraries and prioritize their custom implementation using pure Tailwind CSS and native Svelte. Consider headless UI libraries (e.g., Headless UI, Radix UI) for complex components where accessibility and functionality are key without dictating styling.
|
||||
|
||||
## User Request Confirmation
|
||||
|
||||
- **Incompatibility of essential packages:** Confirmed. `flowbite-svelte` and `skeletonlabs/skeleton` were incompatible with Svelte v5 / Tailwind v4 in our previous attempts. We *will* safely double-check this as part of Phase 1 and 2.
|
||||
- **CSS and missing style issues:** Confirmed. This was the direct consequence of removing the UI libraries.
|
||||
- **`<Modal>` component replacement:** Confirmed. This was our immediate focus for custom replacement if existing libraries fail.
|
||||
38
GEMINI_Flowbite_upgrade_2025-12.md
Normal file
38
GEMINI_Flowbite_upgrade_2025-12.md
Normal file
@@ -0,0 +1,38 @@
|
||||
# Flowbite-Svelte Upgrade Notes (December 2025)
|
||||
|
||||
## Overview
|
||||
This document tracks the process of upgrading the Flowbite-Svelte UI library within the Aether SvelteKit project. The primary goal is to determine if a compatible version exists for Svelte 5 and Tailwind CSS v4, and to plan for its integration or replacement if necessary.
|
||||
|
||||
## Current Status (Pre-Upgrade)
|
||||
- **Flowbite-Svelte Version:** v1.28.1 (as per `package.json` at commit `90ee6bb1`)
|
||||
- **Target Version:** v1.30.0 (or newest compatible)
|
||||
- **Initial Issue (Pre-Rollback):** Previous attempts to update `flowbite-svelte` (and other packages) indicated peer dependency conflicts. Earlier versions of `flowbite-svelte` (compatible with Tailwind v3) required Svelte v4, which conflicted with the project's Svelte v5.
|
||||
- **Current Re-evaluation:** After rolling back to commit `90ee6bb1` and updating SkeletonLabs (which failed the build due to other reasons), `npm install` succeeded with `flowbite-svelte@1.28.1` present in `package.json`. This implies it *can install* alongside Svelte 5 and Tailwind 4. However, its runtime compatibility and rendering correctness with Svelte 5 (runes mode) and Tailwind CSS v4 remain untested.
|
||||
- **Svelte Version:** Svelte 5 (runes mode)
|
||||
- **Tailwind CSS Version:** v4.1.10
|
||||
|
||||
## Phase 1: Research and Planning (No Code Changes Yet)
|
||||
|
||||
### Goal
|
||||
Determine if Flowbite-Svelte has a version that is explicitly compatible with Svelte 5 (runes mode) and Tailwind CSS v4, and to identify any breaking changes or migration paths.
|
||||
|
||||
### Steps
|
||||
1. **Thoroughly Review Flowbite-Svelte Changelog:**
|
||||
* **Link:** `https://github.com/themesberg/flowbite-svelte/blob/main/CHANGELOG.md`
|
||||
* **Action:** Read the changelog for versions from `1.28.1` up to the latest stable release (e.g., `1.30.0` or newer).
|
||||
* **Goal:** Look for specific mentions of Svelte 5 support, "runes mode" compatibility, or compatibility with Tailwind CSS v4. Note any breaking changes or migration instructions related to Svelte version or component API changes.
|
||||
|
||||
### Expected Outcome of Phase 1
|
||||
A clear understanding of Flowbite-Svelte's compatibility with our current stack. This will inform the decision on whether to attempt an upgrade or if abandoning it (and creating custom replacements) is necessary. The expectation is that if a version is compatible, any breaking changes to component APIs (like renaming `Modal` to `Dialog`) will be identified.
|
||||
|
||||
## Phase 2: Execution (After Approval)
|
||||
|
||||
### Steps (To be detailed after Phase 1)
|
||||
1. **If a compatible version exists:**
|
||||
* Update `package.json` to the compatible version.
|
||||
* Run `npm install`.
|
||||
* Run `npm run build` and `npm run dev` and thoroughly check for errors and visual regressions.
|
||||
* Apply any necessary code changes based on identified breaking changes (e.g., component name changes like `Modal` to `Dialog`).
|
||||
2. **If no compatible version exists or issues persist:**
|
||||
* **Decision:** Abandon Flowbite-Svelte.
|
||||
* **Action:** Systematically replace its components with custom-built Svelte/Tailwind components, starting with critical ones like `Modal` (using our `element_modal_v1.svelte` if not using Skeleton's `Dialog`).
|
||||
48
GEMINI_SkeletonLabs_upgrade_2025-12.md
Normal file
48
GEMINI_SkeletonLabs_upgrade_2025-12.md
Normal file
@@ -0,0 +1,48 @@
|
||||
# SkeletonLabs Upgrade Notes (December 2025)
|
||||
|
||||
## Overview
|
||||
This document tracks the process of upgrading the SkeletonLabs UI library (from v3 to v4.7.4) within the Aether SvelteKit project. The primary goal is to resolve build issues caused by incompatibility with Svelte 5 and Tailwind CSS v4, and to integrate the updated library correctly.
|
||||
|
||||
## Current Status (Pre-Upgrade)
|
||||
- **SkeletonLabs Version:** v3.2.2 (as per `package.json` at commit `90ee6bb1`)
|
||||
- **Target Version:** v4.7.4
|
||||
- **Issue:** Previous attempts to upgrade SkeletonLabs to v4.7.4 resulted in a persistent, blocking build error: `[@tailwindcss/vite:generate:build] Cannot use `@variant` with unknown variant: md` originating from `node_modules/@skeletonlabs/skeleton/src/index.css`. This indicates a fundamental incompatibility in how Tailwind CSS v4 processes SkeletonLabs' pre-compiled CSS.
|
||||
- **Svelte Version:** Svelte 5 (runes mode)
|
||||
- **Tailwind CSS Version:** v4.1.10
|
||||
|
||||
## Phase 1: Research and Planning (No Code Changes Yet)
|
||||
|
||||
### Goal
|
||||
Understand the required migration steps from Skeleton v3 to v4 as per official documentation, specifically to address the `@variant` build error and ensure compatibility with Svelte 5 and Tailwind CSS v4.
|
||||
|
||||
### Steps
|
||||
1. **Thoroughly Review Skeleton v3 to v4 Migration Guide:**
|
||||
* **Link:** `https://www.skeleton.dev/docs/svelte/get-started/migrate-from-v3`
|
||||
* **Action:** Read the guide carefully to identify all breaking changes related to:
|
||||
* Tailwind CSS plugin setup in `tailwind.config.ts`.
|
||||
* Required changes to `app.css` or any other global CSS files.
|
||||
* Changes in component class names, especially theme-related classes (`preset-*`, `variant-*`, etc.), which could be related to the `@variant` error.
|
||||
* The new `Dialog` component and how it replaces any previous modal-like components.
|
||||
* **Deliverable:** Summarize the required code changes based on this guide.
|
||||
|
||||
2. **Review Skeleton v4.0 Launch Discussion:**
|
||||
* **Link:** `https://github.com/skeletonlabs/skeleton/discussions/3920`
|
||||
* **Action:** Look for community insights, common issues, and suggested solutions related to upgrading.
|
||||
|
||||
3. **Review Skeleton Dialog Documentation:**
|
||||
* **Link:** `https://www.skeleton.dev/docs/svelte/framework-components/dialog`
|
||||
* **Action:** Understand the API and usage of Skeleton's native dialog component, as this will be the preferred replacement for any missing `<Modal>` components.
|
||||
|
||||
### Expected Outcome of Phase 1
|
||||
A detailed, step-by-step plan for migrating SkeletonLabs from v3 to v4, specifically targeting the resolution of the `@variant` build error and outlining the new usage of its UI components. This plan will be presented for approval before any code changes are made.
|
||||
|
||||
## Phase 2: Execution (After Approval)
|
||||
|
||||
### Steps (To be detailed after Phase 1)
|
||||
1. **Update `package.json`:** Set `@skeletonlabs/skeleton` and `@skeletonlabs/skeleton-svelte` to `4.7.4`.
|
||||
2. **Adjust `tailwind.config.ts`:** Apply changes as per migration guide (e.g., plugin configuration).
|
||||
3. **Adjust `src/app.css`:** Apply changes as per migration guide (e.g., CSS imports, custom theme definitions).
|
||||
4. **Run `npm install`**.
|
||||
5. **Run `npm run build` and `npm run dev`** to verify the build and functionality.
|
||||
6. **Replace `Modal` components:** Update existing components that used an older `<Modal>` (e.g., from `flowbite-svelte` or previous custom efforts) with Skeleton's new `Dialog` component.
|
||||
7. **Address Svelte 5 reactivity warnings:** Fix any warnings related to data handling or non-reactive updates.
|
||||
71
GEMINI_debug_notes.md
Normal file
71
GEMINI_debug_notes.md
Normal file
@@ -0,0 +1,71 @@
|
||||
# Skeleton/Tailwind Build Debugging Log
|
||||
|
||||
This file tracks the troubleshooting steps taken to resolve the build and dev server errors after updating packages.
|
||||
|
||||
## Initial State (Pre-Rollback to 90ee6bb1)
|
||||
|
||||
- **Packages Updated:** Attempted to update `@skeletonlabs/skeleton` to `4.7.4`, `tailwindcss` to `4.1.10`, and `flowbite-svelte` (version not explicitly stated in previous logs but was part of the update attempts).
|
||||
- **`dev` Error:** `Cannot apply unknown utility class 'preset-tonal-secondary'`
|
||||
- **`build` Error:** `Cannot use @variant with unknown variant: md`
|
||||
- **Dependency Conflicts:** Persistent `ERESOLVE` errors, primarily due to:
|
||||
- `flowbite-svelte` versions compatible with Tailwind v3 requiring `svelte@^4.0.0` (while project is Svelte v5).
|
||||
- `@skeletonlabs/skeleton` versions requiring `tailwindcss@^4.0.0` (while attempting to use Tailwind v3 for `flowbite-svelte` compatibility).
|
||||
- **Conclusion:** A fundamental incompatibility between Svelte v5, Tailwind v4, and the existing versions of UI component libraries (Skeleton, Flowbite-Svelte) when trying to achieve a stable `npm install`.
|
||||
|
||||
## Troubleshooting Steps (Pre-Rollback)
|
||||
|
||||
(Summarized from previous extensive debugging logs)
|
||||
- Multiple attempts to downgrade/upgrade Tailwind, Skeleton, and Flowbite-Svelte led to a "dependency nightmare."
|
||||
- Identified that Flowbite-Svelte was the primary blocker for maintaining Svelte v5 compatibility while also using an older Tailwind.
|
||||
- Attempted a strategy to remove *all* pre-built UI component libraries (Skeleton, Flowbite-Svelte) to achieve a clean Svelte v5 + Tailwind v4 base. This led to:
|
||||
- `ReferenceError: Modal is not defined` due to the removal of the underlying `Modal` component.
|
||||
- `</form>` syntax error due to incorrect commenting out of the `<Modal>` component's block.
|
||||
- Server-side `500 Internal Error` (diagnosis interrupted by rollback decision).
|
||||
|
||||
## Current State (Post-Rollback to 90ee6bb1)
|
||||
|
||||
- **Commit:** `90ee6bb1 - All packages have now been updated. This includes the skeletonlabs packages. Everything seems to be working. (Except for some unrelated known bugs. Why did the badge search stop working (AGAIN)?)`
|
||||
- **Status:** Application is confirmed to be "mostly working" at this commit. This provides a stable baseline.
|
||||
- **Key Observation from Commit Message:** "All packages have now been updated. This includes the skeletonlabs packages. Everything seems to be working." This implies that at this point, the `skeletonlabs` packages *were* working with some configuration of Svelte and Tailwind.
|
||||
|
||||
## Revised Path Forward: Re-evaluate UI Library Compatibility
|
||||
|
||||
**Context:** The previous issues stemmed from an inability to reconcile `skeletonlabs/skeleton` (requiring Tailwind v4), `flowbite-svelte` (preferring Svelte v4 for Tailwind v3 compatibility), and the project's Svelte v5 base. Before attempting to re-implement all UI components from scratch, we will re-evaluate if the latest versions of these libraries have resolved their internal conflicts or if a stable configuration now exists.
|
||||
|
||||
**Phase 1: Re-evaluate SkeletonLabs Compatibility (Primary Focus)**
|
||||
|
||||
**Rationale:** Skeleton UI appears to be the most deeply integrated UI library in the project. If it can be made to work, it will significantly reduce the need for custom component development.
|
||||
|
||||
1. **Update `GEMINI.md` and related notes:** (Completed in this step) Document this new strategy and the decision to re-evaluate packages.
|
||||
2. **Create a new Git branch:** Name it `feature/re_evaluate_ui_libs`. (Pending)
|
||||
3. **Identify latest compatible `@skeletonlabs/skeleton` and `skeleton-svelte` versions:**
|
||||
* Consult their official documentation, release notes, and GitHub issues for compatibility with **Svelte v5** and **Tailwind CSS v4**.
|
||||
* Determine if there's a specific version range that is known to work.
|
||||
4. **Attempt to update SkeletonLabs packages (one at a time, or as a pair if tightly coupled):**
|
||||
* Modify `package.json` to specify the identified compatible versions of `@skeletonlabs/skeleton` and `@skeletonlabs/skeleton-svelte`.
|
||||
* Run `npm install`.
|
||||
* Run `npm run build` and `npm run dev`.
|
||||
* **Crucially:** Thoroughly check for *all* types of errors:
|
||||
* Terminal errors (build, compilation, server-side).
|
||||
* Browser console errors (client-side JS, hydration).
|
||||
* Visual regressions or missing styles.
|
||||
* **Document findings:** Note down exact errors or success status.
|
||||
5. **If successful:** If SkeletonLabs works without major issues, proceed to Phase 2.
|
||||
6. **If unsuccessful:** If significant conflicts or errors persist, revert changes on the branch and document the specific incompatibilities. This would then lead to immediately pursuing custom UI component implementation.
|
||||
|
||||
**Phase 2: Address Other UI Library Needs (Conditional, based on Phase 1 outcome)**
|
||||
|
||||
1. **If SkeletonLabs is working:**
|
||||
* Re-evaluate the need for `flowbite-svelte`. Is its functionality still required, or is it covered by Skeleton UI or can be easily done with pure Tailwind?
|
||||
* If still needed, attempt to update `flowbite-svelte` to the latest version, following the same cautious approach as with SkeletonLabs (package.json update, `npm install`, full testing).
|
||||
2. **If SkeletonLabs (and/or Flowbite) cannot be made to work with Svelte v5 / Tailwind v4:**
|
||||
* **Prioritize Custom Component Implementation:** Immediately proceed with implementing custom replacements, starting with critical components. The `element_modal_v1.svelte` (which was partially developed before the rollback) is a prime candidate for immediate completion and integration.
|
||||
* **Identify other critical missing UI components:** Systematically list other essential components (e.g., dropdowns, tabs, accordions, cards, forms elements) that were previously provided by these libraries and prioritize their custom implementation using pure Tailwind CSS and native Svelte. Consider headless UI libraries (e.g., Headless UI, Radix UI) for complex components where accessibility and functionality are key without dictating styling.
|
||||
|
||||
## User Request Confirmation
|
||||
|
||||
- **Incompatibility of essential packages:** Confirmed. `flowbite-svelte` and `skeletonlabs/skeleton` were incompatible with Svelte v5 / Tailwind v4 in our previous attempts. We *will* safely double-check this as part of Phase 1 and 2.
|
||||
- **CSS and missing style issues:** Confirmed. This was the direct consequence of removing the UI libraries.
|
||||
- **`<Modal>` component replacement:** Confirmed. This was our immediate focus for custom replacement.
|
||||
|
||||
**The immediate next steps are to update my internal `GEMINI.md` for this project with this new plan and create the `feature/re_evaluate_ui_libs` branch.**
|
||||
222
README.md
222
README.md
@@ -1,2 +1,220 @@
|
||||
# OSIT AE - Sponsorships App (Svelte)
|
||||
This was created for One Sky IT's Aether system.
|
||||
# One Sky IT's Aether App - SvelteKit v2
|
||||
|
||||
This uses SvelteKit version 2.x with Svelte version 5.x, TailwindCSS 4.1, and Skelton.
|
||||
|
||||
# Current Modules
|
||||
|
||||
## AE Events - Speakers (/events_speakers)
|
||||
|
||||
### Components
|
||||
|
||||
- +page.svelte - The main page for the Events - Speakers module
|
||||
- 10_edit_modal\_\_event_presenter_obj.svelte - The modal for editing a presenter
|
||||
- 10_list\_\_event_presenter_obj.svelte - The list of presenters/speakers
|
||||
- 10_view_modal\_\_event_presenter_obj.svelte - The modal for viewing a presenter
|
||||
|
||||
### Path [slug]
|
||||
|
||||
- +page.svelte - The main page for the presenter ID [slug]
|
||||
|
||||
## AE Sponsorships (/sponsorships)
|
||||
|
||||
- +page.svelte - The main page for the Sponsorships module
|
||||
- 10_edit_modal\_\_sponsorship_obj.svelte - The modal for editing a sponsorship
|
||||
- 10_list\_\_sponsorship_obj.svelte - The list of sponsorships
|
||||
- 10_view_modal\_\_sponsorship_obj.svelte - The modal for viewing a sponsorship
|
||||
|
||||
### Path [slug]
|
||||
|
||||
- +page.svelte - The main page for the sponsorship ID [slug]
|
||||
|
||||
## AE Events - Exhibit Leads (/events_exhibit_leads)
|
||||
|
||||
### Components
|
||||
|
||||
- +page.svelte - The main page for the Events - Exhibit Leads module
|
||||
- 10_list\_\_event_exhibit_lead_obj.svelte - The list of exhibit leads
|
||||
- 10_edit_modal\_\_event_exhibit_lead_obj.svelte - The modal for editing an exhibit lead
|
||||
- 10_view_modal\_\_event_exhibit_lead_obj.svelte - The modal for viewing an exhibit lead
|
||||
|
||||
# Future Modules
|
||||
|
||||
## AE Events - Badges (/events_badges)
|
||||
|
||||
- +page.svelte - The main page for the Events - Badges module
|
||||
- 10_list\_\_event_badge_obj.svelte - The list of badges
|
||||
- 10_view_modal\_\_event_badge_obj.svelte - The modal for viewing a badge
|
||||
|
||||
## AE Events - Presentation Management (/events_pres_mgmt)
|
||||
|
||||
# How to build and deploy SvelteKit:
|
||||
|
||||
Copy the contents of the "build" directory to ./npm_deploy/build/
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
If this is just a quick build update then only the build directory needs to be copied (rsync).
|
||||
|
||||
```bash
|
||||
rsync -vhrz --exclude 'node_modules' ~/OSIT_dev/ae_app_svelte_tailwind_skeleton/build/ ~/OSIT_dev/ae_env_node_app/npm_deploy/build/ --delete
|
||||
|
||||
rsync -vhrz ~/OSIT_dev/ae_env_node_app/npm_deploy/build/ scott@linode.oneskyit.com:/srv/env/prod_aether_sveltekit/npm_deploy/build/ --delete
|
||||
```
|
||||
|
||||
If this includes package updates (not development) we need to copy the new package.json. Manually copy the new package.json file to ./npm_deploy/. This also needs to be copied to the server. Copy the package.json even though not really used.
|
||||
|
||||
Run the --omit dev to clear out the node_modules directory. Copy the root node_modules directory to ./npm_deploy/build/node_modules/ after running te omit dev command.
|
||||
|
||||
```bash
|
||||
npm ci --omit dev
|
||||
|
||||
# copy/paste, rsync, or cp
|
||||
rsync -vhrz ~/OSIT_dev/ae_app_svelte_tailwind_skeleton/node_modules ~/OSIT_dev/ae_env_node_app/npm_deploy/build/ --delete
|
||||
|
||||
# copy package.json as well
|
||||
|
||||
npm install
|
||||
```
|
||||
|
||||
Everything should be ready to run on the development server and production server.
|
||||
|
||||
# Rebuild the node_modules directory and manually install extra Svelte packages
|
||||
|
||||
Run the npm update to fix the node_modules directory and package.json
|
||||
|
||||
```bash
|
||||
npm list
|
||||
npm outdated
|
||||
npm update
|
||||
npm outdated
|
||||
npm list
|
||||
```
|
||||
|
||||
Other installs?:
|
||||
Are both still needed? I know at least one of these is. 2024-07-23
|
||||
|
||||
```bash
|
||||
npm install --save-dev svelte-highlight
|
||||
npm install --save-dev typescript-svelte-plugin
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Set up and run
|
||||
|
||||
## Packages and dependencies
|
||||
|
||||
```bash
|
||||
npm install --save-dev svelte-highlight typescript-svelte-plugin
|
||||
npm install flowbite flowbite-svelte tailwind-merge @popperjs/core
|
||||
```
|
||||
|
||||
I am slowly switching from Font-Awesome to Lucide
|
||||
|
||||
## Tiptap Editor
|
||||
|
||||
- Eventually use Edra? https://edra.tsuzat.com/
|
||||
- Best Rich Text Editor, made for Svelte Developers with Tiptap
|
||||
- ShadEditor is "evolving" to be Edra.
|
||||
- ShadCN is still stuck on Tailwind 3. Waiting to upgrade to Tailwind 4.x. Tailwind 4.x was released in late January 2025. ShadCN is still being worked on as of late March 2025.
|
||||
- [https://github.com/huntabyte/shadcn-svelte/issues/1643](https://github.com/huntabyte/shadcn-svelte/issues/1643)
|
||||
|
||||
Need to install ShadCN and Lucide for the Tiptap editor.
|
||||
|
||||
```bash
|
||||
npm install shadcn-svelte
|
||||
npm install lucide-svelte
|
||||
npm install mode-watcher
|
||||
```
|
||||
|
||||
Now we initialize the ShadCN and ShadEditor packages. Follow the command line instructions.
|
||||
|
||||
```bash
|
||||
npx shadcn-svelte@next init
|
||||
npx shadcn-svelte@next add dropdown-menu button tooltip input popover separator
|
||||
npx shadeditor init
|
||||
```
|
||||
|
||||
More packages related to the Tiptap editor???
|
||||
|
||||
```bash
|
||||
npm install @tiptap/extension-link @tiptap/extension-bullet-list @tiptap/extension-history @tiptap/extension-typography @tiptap/extension-underline
|
||||
```
|
||||
|
||||
## Build
|
||||
|
||||
## Environment file
|
||||
|
||||
### ".env"
|
||||
|
||||
This is the default used if others are not found when when "npm run dev" or "npm run build" is run.
|
||||
|
||||
### ".env.local"
|
||||
|
||||
This is used when "npm run dev" is run. This is not used in the production build.
|
||||
|
||||
### ".env.production"
|
||||
|
||||
This is used when "npm run build" is run. This is not used in the development build.
|
||||
|
||||
### ".env:prod"
|
||||
|
||||
This is modified to allow for a staging environment and production environment built.
|
||||
|
||||
### ".env:staging"
|
||||
|
||||
This is modified to allow for a staging environment and production environment built.
|
||||
|
||||
### Example Important Values when running in dev:
|
||||
|
||||
Note: Environment values need to be updated when our home IP address changes. Be sure to check the Aether Container Environment and Aether Node App (SvelteKit) Environment files for the correct IP address. The Node Docker environment needs to be updated here and in the .env file that Docker will read. This needs to be improved later...
|
||||
|
||||
```bash
|
||||
DOCKER_AE_API_DEV_SERVER_EXTRA_HOST=dev-api.oneskyit.com:108.48.200.147
|
||||
|
||||
DOCKER_AE_API_SERVER_EXTRA_HOST=dev-api.oneskyit.com:108.48.200.147
|
||||
|
||||
PUBLIC_AE_API_SERVER=api.oneskyit.com
|
||||
PUBLIC_AE_API_BAK_SERVER=bak-api.oneskyit.com
|
||||
```
|
||||
|
||||
# create-svelte
|
||||
|
||||
Everything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/main/packages/create-svelte).
|
||||
|
||||
## Creating a project
|
||||
|
||||
If you're seeing this, you've probably already done this step. Congrats!
|
||||
|
||||
```bash
|
||||
# create a new project in the current directory
|
||||
npm create svelte@latest
|
||||
|
||||
# create a new project in my-app
|
||||
npm create svelte@latest my-app
|
||||
```
|
||||
|
||||
## Developing
|
||||
|
||||
Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
|
||||
# or start the server and open the app in a new browser tab
|
||||
npm run dev -- --open
|
||||
```
|
||||
|
||||
## Building
|
||||
|
||||
To create a production version of your app:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
You can preview the production build with `npm run preview`.
|
||||
|
||||
> To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment.
|
||||
|
||||
379
TODO.md
Normal file
379
TODO.md
Normal file
@@ -0,0 +1,379 @@
|
||||
# One Sky IT's Aether UI/UX Project TODO
|
||||
|
||||
This is a list of tasks to be completed before the next event/show/conference.
|
||||
|
||||
---
|
||||
|
||||
## Recent Accomplishments
|
||||
|
||||
- [x] **Badges v3:** Resolved a series of cascading build and runtime errors on the new badge search page. This involved restoring Skeleton CSS, fixing Svelte 5 event handler syntax (`onsubmit|preventDefault`), resolving a prop binding error (`props_invalid_value`), and temporarily disabling a problematic `order_by_li` API parameter to fix a network fetch error.
|
||||
- [x] **Refactoring:** Standardized data processing in `events`, `archives`, `posts`, and `sponsorships` modules using a new generic pattern.
|
||||
- [x] **Bug Fix:** Corrected data fetching logic for session-related presentations and files that were not displaying correctly due to `id` vs `id_random` issues.
|
||||
- [x] **Core:** Defined `Account`, `Site`, and `Site_Domain` interfaces in new files under `src/lib/ae_core/`.
|
||||
- [x] **Journals:** Improve the empty state message in `src/routes/journals/+page.svelte`.
|
||||
- [x] **Journals:** Add a loading indicator to the main journals page.
|
||||
- [x] **IDAA:** Add a loading indicator to the archives page (`src/routes/idaa/(idaa)/archives/+page.svelte`).
|
||||
- [x] **Events:** Add pagination to the main event list in `src/routes/events/+page.svelte`.
|
||||
|
||||
---
|
||||
|
||||
## Big Picture Goals
|
||||
|
||||
- Everything needs to work with Svelte 5.x and SvelteKit 2.x.
|
||||
- Able to cache data and mostly work offline.
|
||||
- The new Events Launcher must be able to work offline and query the API for changes to data.
|
||||
- The new Events Launcher must be able to run inside an Electron app and have access to local files and OS shell commands and applications. This includes loading a special library that only works in Electron.
|
||||
|
||||
---
|
||||
|
||||
## Codebase Standardization
|
||||
|
||||
### 1. Naming Conventions
|
||||
|
||||
- [ ] **Goal:** Enforce a single, consistent naming standard across the entire codebase.
|
||||
- [ ] **Files:**
|
||||
- Logic: `ae_<module>__<concept>.ts`
|
||||
- DB Definitions: `db_<module>.ts`
|
||||
- Svelte Stores: `ae_<module>_stores.ts`
|
||||
- Consolidate helper files (e.g., `ae_core_functions.ts`) into the above files.
|
||||
- [ ] **Functions & Variables:**
|
||||
- [x] Enforce `snake_case` for all function and variable names.
|
||||
- [x] Deprecate and remove `camelCase`.
|
||||
- [x] Deprecate and refactor ambiguous `handle_` prefixes.
|
||||
- [ ] **Object & Property Naming:**
|
||||
- Use singular nouns for objects and properties (e.g., `example.id`, not `examples.id`).
|
||||
- [ ] **List Suffixes:**
|
||||
- Use `_li` for simple, unordered arrays.
|
||||
- Use `_kv` for key-value objects/maps.
|
||||
- [ ] **Process:**
|
||||
- Refactor one module at a time to ensure internal consistency before moving to the next. Start with `ae_core`.
|
||||
- **Update 2025-11-13:** `ae_core_functions.ts` has been temporarily restored to resolve a critical issue. The refactoring of `process_ae_obj__*_props()` functions will now proceed module by module, ensuring stability at each step.
|
||||
|
||||
### 2. Component Standardization
|
||||
|
||||
- [x] **CodeMirror Migration:** Replaced all instances of the old Tiptap editor with a new CodeMirror wrapper. This includes fixing initialization errors, enabling text wrapping, and ensuring content is correctly saved.
|
||||
- [ ] **Component Review:** Audit third-party components to understand their conventions and isolate them from internal standards.
|
||||
|
||||
### 3. Aether Object Field Definitions
|
||||
|
||||
- [ ] **Goal:** Create a common way to define which fields can be sent in when creating or updating a record for all Aether objects.
|
||||
- [ ] **Process:**
|
||||
- For each Aether object type, create a `ae_<module>__<object>.editable_fields.ts` file that exports a whitelist of editable fields.
|
||||
- Modify the `create` and `update` functions for each object type to use this whitelist to filter the data before sending it to the API.
|
||||
- Start with the `event` object type as a proof of concept. (DONE)
|
||||
- Apply this pattern to all other Aether object types.
|
||||
|
||||
---
|
||||
|
||||
## Priority Tasks (Easy & Quick)
|
||||
|
||||
- [ ] **API:** Properly investigate and fix the `order_by_li` parameter in the `search__event_badge` function. The parameter is currently commented out as a temporary workaround to prevent a network fetch error.
|
||||
- [ ] **Formatting:** Run `npm run format` to fix code style issues across the project.
|
||||
|
||||
---
|
||||
|
||||
## Critical Functions for Review
|
||||
|
||||
These functions are frequently used and critical to the application's data flow. Reviewing and cleaning them up will significantly improve the codebase.
|
||||
|
||||
1. **`get_ae_obj_li_for_obj_id_crud_v2()`** (from `src/lib/ae_api/api_get__crud_obj_li_v2.ts`)
|
||||
- **Why:** This is the main function for fetching lists of data from the backend, used extensively across all modules.
|
||||
- **Cleanup:** Review parameters and return types for consistency, improve error handling, and add more detailed logging for debugging.
|
||||
|
||||
2. **`db_save_ae_obj_li__ae_obj()`** (from `src/lib/ae_core/core__idb_dexie.ts`)
|
||||
- **Why:** This function is the single point of entry for saving data to the local Dexie database, critical for performance and reliability.
|
||||
- **Cleanup:** Optimize for bulk operations, add robust error handling and logging, and ensure correct handling of updates to existing objects.
|
||||
|
||||
3. **The `process_ae_obj__*_props()` family of functions** (e.g., `process_ae_obj__journal_props()` from `src/lib/ae_journals/ae_journals__journal.ts`)
|
||||
- **Why:** These functions transform API data for the frontend and are a common source of bugs and inconsistencies.
|
||||
- **Cleanup:** Standardize their structure across all modules, ensure they are pure functions, and add unit tests for correctness.
|
||||
- **Update 2025-11-13 (Temporary Rollback):** The previous refactoring of these functions has been temporarily rolled back due to an `InternalError`. `ae_core_functions.ts` has been restored. The new plan is to refactor these functions module by module, ensuring stability at each step. The generic CRUD functions in `core__crud_generic.ts` were simplified to remove data processing and caching, delegating those responsibilities to the module-specific functions. The deprecated `process_ae_obj__props` function in that file was left in place but is no longer used by the generic CRUD functions.
|
||||
- **Update 2025-11-20 (Successful Refactor):** The `event_badge` module has been successfully refactored to use the new "API Function -> Processor -> DB Save" pattern. The `process_ae_obj__event_badge_props` function now handles inconsistencies in the API search results (i.e., a missing `event_id`) by accepting the `event_id` as a parameter and injecting it. This serves as a successful proof-of-concept for this architectural pattern.
|
||||
|
||||
4. **Usage of `liveQuery` from Dexie**
|
||||
- **Why:** `liveQuery` is powerful for reactive UIs, but current usage suggests complexity and potential issues.
|
||||
- **Cleanup:** Review `liveQuery` usage throughout the application, simplify queries, and investigate reactivity issues. Consider wrapping `liveQuery` in a custom Svelte store for a more predictable interface.
|
||||
|
||||
---
|
||||
|
||||
- [x] Improve the `e_app_codemirror_v5.svelte` component and plan the migration from Tiptap to CodeMirror for rich text editing. The migration is complete, and the component has been improved to handle individual extensions and fix various bugs.
|
||||
|
||||
---
|
||||
|
||||
## Core Module Improvements
|
||||
|
||||
### 1. Core Module Dashboard
|
||||
|
||||
- [ ] Create a central dashboard at `/core` to provide an overview and links to all core data management pages.
|
||||
|
||||
### 2. Account Management
|
||||
|
||||
- [ ] **Route:** Create a new route at `/core/accounts`.
|
||||
- [ ] **Data:** Define the `Account` interface in a new file `src/lib/ae_core/core__account.ts`.
|
||||
- [ ] **API:** Implement functions in `core__account.ts` for CRUD operations on accounts.
|
||||
- [ ] **UI:**
|
||||
- [ ] Create a `+page.svelte` to list all accounts.
|
||||
- [ ] Create a `[account_id]` dynamic route to view and edit account details.
|
||||
|
||||
### 3. Site & Domain Management
|
||||
|
||||
- [ ] **Route:** Create a new route at `/core/sites`.
|
||||
- [ ] **Data:** Define `Site` and `Site_Domain` interfaces in a new file `src/lib/ae_core/core__site.ts`.
|
||||
- [ ] **API:** Implement functions in `core__site.ts` for CRUD operations on sites and domains.
|
||||
- [ ] **UI:**
|
||||
- [ ] Create a `+page.svelte` to list all sites.
|
||||
- [ ] Create a `[site_id]` dynamic route to view and edit site details and manage associated domains.
|
||||
|
||||
### 4. Person Management
|
||||
|
||||
- [ ] **Enhance:** Improve the existing person management components under `/core/person`.
|
||||
- [ ] **UI:**
|
||||
- [ ] Create a dedicated page for creating new person records.
|
||||
- [ ] Add search and filtering capabilities to the person list.
|
||||
|
||||
### 5. User Management
|
||||
|
||||
- [ ] **Route:** Create a new route at `/core/users`.
|
||||
- [ ] **UI:**
|
||||
- [ ] Create a `+page.svelte` to list all users.
|
||||
- [ ] Create a `[user_id]` dynamic route to view and edit user details, including permissions.
|
||||
- [ ] Implement a component to link users to person records.
|
||||
|
||||
### 6. Hosted File Management
|
||||
|
||||
- [ ] **Route:** Create a new route at `/core/hosted_files`.
|
||||
- [ ] **UI:**
|
||||
- [ ] Create a `+page.svelte` to list all hosted files with filters (e.g., by file type, uploader).
|
||||
- [ ] Implement a file viewer for common file types.
|
||||
- [ ] Add functionality to upload new files and associate them with other objects (e.g., a person, a journal entry).
|
||||
|
||||
### 7. Shared Lookup Lists
|
||||
|
||||
- [ ] **Route:** Create a new route at `/core/lookups`.
|
||||
- [ ] **UI:**
|
||||
- [ ] Create a simple UI to view and manage the shared lookup lists (e.g., `countries`, `time_zones`).
|
||||
|
||||
---
|
||||
|
||||
## Journals Module Improvements
|
||||
|
||||
### Code Cleanup & Refactoring
|
||||
|
||||
- [ ] **Consolidate Data Functions:** Refactor `ae_journals__journal.ts` and `ae_journals__journal_entry.ts` to reduce code duplication, especially in data loading and processing functions.
|
||||
- [ ] **Remove Dead Code:** Clean up commented-out code blocks and unused variables across the module.
|
||||
- [ ] **Logging:** Implement a more structured logging solution to replace the widespread use of `console.log`.
|
||||
- [ ] **Promise Handling:** Standardize promise handling to use `async/await` consistently and remove mixed `.then()` and `async/await` syntax.
|
||||
- [ ] **Type Safety:** Replace `any` types with more specific interfaces, particularly in function parameters and API responses.
|
||||
|
||||
### Features & Enhancements
|
||||
|
||||
- [ ] **Offline Support:** Improve offline capabilities by pre-fetching and caching more data. Review the current Dexie implementation for optimizations.
|
||||
- [ ] **Search & Filtering:** Enhance the UI with more advanced search and filtering options for journals and entries (e.g., by date range, content, tags).
|
||||
- [ ] **User Experience (UX):**
|
||||
- Implement better loading indicators and skeleton loaders.
|
||||
- Provide clearer empty state messages (e.g., "No journals found, create one!").
|
||||
- Improve error handling and provide more informative error messages to the user.
|
||||
- [ ] **Encryption:** Review and enhance the encryption implementation for journal entries to ensure it is secure and user-friendly.
|
||||
- [ ] **Templates:** Fully implement and document the "templates" feature for creating new journals and entries.
|
||||
|
||||
### Bug Fixes & Potential Issues
|
||||
|
||||
- [ ] **Reactivity:** Investigate potential reactivity issues between Svelte stores and Dexie's `liveQuery`.
|
||||
- [ ] **Data Sync:** Add logic to handle data synchronization conflicts between the local database and the server.
|
||||
- [ ] **Performance:** Profile the application with a large number of journals and entries to identify and address any performance bottlenecks.
|
||||
|
||||
---
|
||||
|
||||
## IDAA Modules Improvements
|
||||
|
||||
### General
|
||||
|
||||
- [ ] **Component Refactoring:** Audit the `ae_idaa_comp__` components and refactor them to be more generic and reusable where possible.
|
||||
- [ ] **State Management:** Simplify state management by reducing the number of stores and triggers, and relying more on derived state and component props.
|
||||
|
||||
### Archives Module (`/idaa/archives`)
|
||||
|
||||
- [ ] **UI/UX:**
|
||||
- [ ] Add a loading indicator while archives are being fetched.
|
||||
- [ ] Implement a more engaging "empty state" when no archives are available.
|
||||
- [ ] **Performance:**
|
||||
- [ ] Implement pagination or infinite scrolling for the archive list.
|
||||
|
||||
### Bulletin Board Module (`/idaa/bb`)
|
||||
|
||||
- [ ] **UI/UX:**
|
||||
- [ ] Improve the UI for creating and editing posts and comments.
|
||||
- [x] Add a rich text editor for a better writing experience.
|
||||
- [ ] **Features:**
|
||||
- [ ] Implement user-specific features, such as editing their own posts and comments.
|
||||
|
||||
### Recovery Meetings Module (`/idaa/recovery_meetings`)
|
||||
|
||||
- [ ] **Refactoring:**
|
||||
- [ ] Simplify the search and filtering logic. The current implementation with `setInterval` is complex and could be replaced with a more modern approach using debouncing or reactive statements.
|
||||
- [ ] **UI/UX:**
|
||||
- [ ] Make the search and filtering interface more intuitive and responsive.
|
||||
- [ ] Provide instant feedback to the user as they type in the search box.
|
||||
- [ ] **Performance:**
|
||||
- [ ] Optimize the search query to be faster and more efficient.
|
||||
|
||||
---
|
||||
|
||||
## Aether Events Module Improvements
|
||||
|
||||
### General
|
||||
|
||||
- [ ] **Dashboard:** Create a central dashboard for each event at `/events/[event_id]` that provides an overview of the event and links to all the management pages.
|
||||
- [ ] **Component Refactoring:** The module has a large number of `ae_comp__` components. Audit and refactor them to be more modular and reusable.
|
||||
- [ ] **UI/UX Consistency:** Ensure a consistent look and feel across all the different event management pages.
|
||||
|
||||
### Core Event Management
|
||||
|
||||
- [ ] **Event List (`/events`):**
|
||||
- [ ] Add search and filtering capabilities to the main event list.
|
||||
- [ ] Implement pagination for the event list.
|
||||
- [ ] **Event Creation/Editing:**
|
||||
- [ ] Create a dedicated page or modal for creating and editing events.
|
||||
|
||||
### Sub-modules (`/events/[event_id]/...`)
|
||||
|
||||
- [ ] **Sessions, Presentations, Presenters, etc.:**
|
||||
- [ ] For each sub-module (sessions, presentations, etc.), implement a consistent set of features:
|
||||
- [ ] List view with search and filtering.
|
||||
- [ ] Detail view.
|
||||
- [ ] Create and edit forms.
|
||||
- [ ] Delete functionality with confirmation.
|
||||
- [ ] **File Management:**
|
||||
- [ ] Improve the file upload component (`ae_comp__event_files_upload.svelte`) with features like drag-and-drop and progress bars.
|
||||
- [ ] Enhance the file list view with more details and actions.
|
||||
- [ ] \*\*Launcher (`/events/[event_id]/launcher`):
|
||||
- [ ] Add documentation to explain the purpose and usage of the launcher.
|
||||
- [ ] Improve the UI to make it more intuitive for users.
|
||||
- [ ] \*\*Badges (`/events/[event_id]/badges`):
|
||||
- [ ] Enhance the badge printing interface with more customization options.
|
||||
- [ ] Add a preview of the badge before printing.
|
||||
|
||||
### Performance
|
||||
|
||||
- [ ] **Live Queries:** Review the use of `liveQuery` throughout the module and optimize for performance, especially on pages with a large amount of data.
|
||||
- [ ] **Data Loading:** Implement more efficient data loading strategies to avoid fetching unnecessary data.
|
||||
|
||||
---
|
||||
|
||||
## UI/UX Consistency
|
||||
|
||||
- [ ] **Broad UI/UX Review:** Conduct a comprehensive review of UI elements across the application to ensure consistency. This includes, but is not limited to:
|
||||
- Buttons (style, placement, wording)
|
||||
- Lists (style, actions)
|
||||
- Links vs. Buttons (correct semantic usage)
|
||||
- Menus (style, options)
|
||||
- Debug components and other developer-facing UI.
|
||||
- **Wording:** Standardize the text used in common UI elements (e.g., "Save", "Cancel", "Delete", "Add New").
|
||||
- **Scope:** This should be done on a per-module basis to ensure local consistency, with a goal of achieving global consistency where possible.
|
||||
- **Note on IDAA:** The `idaa` modules are semi-custom for a client and may have their own specific UI/UX requirements. Their consistency should be evaluated separately, keeping the client's needs in mind.
|
||||
- [ ] **Component Migration:** Replace remaining Skeleton UI classes (e.g., `preset-tonal-*`, `variant-filled-*`) with standard Tailwind CSS to avoid CSS conflicts and dependency issues.
|
||||
|
||||
---
|
||||
|
||||
## Scott's Quick Notes
|
||||
|
||||
These are just quick notes, thoughts, ideas, and reminders for myself.
|
||||
|
||||
- I need to explain the purpose and thought behind the data_store element or component and how it works. The short version: It is a hierarchy of database results, but only the last result is returned. The results are filtered by data store key/code, then by account_id, and then by for_type and for_id. This allows for shared data among accounts, but also account specific overrides. Finally, it allows for object specific overrides.
|
||||
- Use old Events Leads module as reference for new one
|
||||
- Use old Events Badges module as reference for new one
|
||||
- Use old Events Launcher module as reference for new one
|
||||
- The Launcher will need some work to make it work offline and in Electron
|
||||
- Events Leads: mobile first, but still works on desktop
|
||||
- Need to be able to enable and disable modules per event (e.g., some events may not need Leads or Badges)
|
||||
- In theory session codes should be unique per event. This depends somewhat on the client's data and needs.
|
||||
- The codes for locations/rooms should also be unique per event.
|
||||
- The codes for devices should also be unique per event.
|
||||
- Reports are manually created and shared among events and clients. We need to be able to enable/disable reports per event. Each report will have its own Svelte page.
|
||||
|
||||
### Events modules and main landing pages
|
||||
|
||||
- **Presentation Management**
|
||||
- Manage
|
||||
- Session Search
|
||||
- View Session
|
||||
- View Presenter
|
||||
- Locations List
|
||||
- View Location
|
||||
- Devices List
|
||||
- View Device
|
||||
- Reports
|
||||
- **Launcher** (desktop first; tablet second; mobile last)
|
||||
- Manage - Various admin and configuration options
|
||||
- Menu Section - Event; Location; Sessions; Show/Hide
|
||||
- Content Section - Shows session specific files; Shows session specific presentations; presentation specific presenters are shown per presentation; presenter specific files are shown per presenter
|
||||
- Header Section - Event Name; Location Name; Current Time; Offline/Online Status; Sync Status
|
||||
- Footer Section - Other status indicators; sync button
|
||||
- **Badge Printing**
|
||||
- Manage
|
||||
- Print Badges
|
||||
- View Badge (show full preview before printing)
|
||||
- Review Badge (attendee confirms key info before printing; agree/disagree to terms; agree/disagree to lead retrieval and tracking)
|
||||
- Manually add Badge
|
||||
- Reports
|
||||
- **Lead Retrieval**
|
||||
- Manage
|
||||
- View Leads
|
||||
- Add Lead (Scan or Manual Entry)
|
||||
- License Management and Payment (Stripe)
|
||||
- **Admin or Manage or Configure Event**
|
||||
|
||||
### New Directory Structure?
|
||||
|
||||
- src/lib/ - Shared libraries and components
|
||||
- src/routes/core/ - Core Aether management module
|
||||
- sub-directories for:
|
||||
- accounts
|
||||
- account (by ID)
|
||||
- sites
|
||||
- site (by ID)
|
||||
- site_domains
|
||||
- site_domain (by ID)
|
||||
- people
|
||||
- person (by ID)
|
||||
- users
|
||||
- user (by ID)
|
||||
- hosted_files
|
||||
- hosted_file (by ID or partial hash match???)
|
||||
- lookups
|
||||
- (countries)
|
||||
- (state_provinces)
|
||||
- (time_zones)
|
||||
- src/routes/events/ - Events main landing page and event management
|
||||
- src/routes/events/[event_id]/(presentations)/ - Event presentation management module
|
||||
- sub-directories for:
|
||||
- sessions
|
||||
- session (by ID or code)
|
||||
- presentations
|
||||
- presenters
|
||||
- presenter (by ID or code???)
|
||||
- event_files
|
||||
- locations
|
||||
- location (by ID or code)
|
||||
- devices
|
||||
- device (by ID or code)
|
||||
- reports
|
||||
- report (by name of report)
|
||||
- src/routes/events/[event_id]/(launcher)/ - Event launcher module
|
||||
- src/routes/events/[event_id]/(badges)/ - Event badge printing module
|
||||
- src/routes/events/[event_id]/(leads)/ - Event lead retrieval module
|
||||
- src/routes/events/[event_id]/+page.svelte - Event main dashboard
|
||||
- [event_id]/exhibit/[exhibit_id]/ - Exhibitor specific lead retrieval pages
|
||||
- src/routes/journals/ - Journals module
|
||||
- src/routes/idaa/ - IDAA custom modules
|
||||
- (archives)/ - Archives module
|
||||
- (bb)/ - Bulletin Board module
|
||||
- (recovery_meetings)/ - Recovery Meetings module
|
||||
- src/lib/ae_core/ - Core Aether logic and data models
|
||||
- src/lib/ae_events/ - Events module logic and data models
|
||||
- src/lib/ae_journals/ - Journals module logic and data models
|
||||
- src/lib/ae_idaa/ - IDAA custom modules logic and data models
|
||||
- src/lib/components/ - Shared Svelte components
|
||||
- src/lib/stores/ - Shared Svelte stores
|
||||
- src/assets/ - Assets like CSS, Tailwind config, etc.???
|
||||
- static/ - Static assets like images, fonts, etc.
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"folders": [
|
||||
{
|
||||
"path": "."
|
||||
}
|
||||
],
|
||||
"settings": {}
|
||||
}
|
||||
12
ae_app_svelte_tailwind_skeleton.code-workspace
Normal file
12
ae_app_svelte_tailwind_skeleton.code-workspace
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"folders": [
|
||||
{
|
||||
"path": "."
|
||||
}
|
||||
],
|
||||
"settings": {
|
||||
"cSpell.words": ["filelist"],
|
||||
"git.autofetch": true,
|
||||
"editor.defaultFormatter": "svelte.svelte-vscode"
|
||||
}
|
||||
}
|
||||
17
components.json
Normal file
17
components.json
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"$schema": "https://next.shadcn-svelte.com/schema.json",
|
||||
"style": "default",
|
||||
"tailwind": {
|
||||
"config": "tailwind.config.ts",
|
||||
"css": "src/app.css",
|
||||
"baseColor": "gray"
|
||||
},
|
||||
"aliases": {
|
||||
"components": "$lib/components",
|
||||
"utils": "$lib/utils",
|
||||
"ui": "$lib/components/ui",
|
||||
"hooks": "$lib/hooks"
|
||||
},
|
||||
"typescript": true,
|
||||
"registry": "https://next.shadcn-svelte.com/registry"
|
||||
}
|
||||
2274
documentation/AETHER_API_OBJECTS.md
Normal file
2274
documentation/AETHER_API_OBJECTS.md
Normal file
File diff suppressed because it is too large
Load Diff
142
documentation/ARCHITECTURE.md
Normal file
142
documentation/ARCHITECTURE.md
Normal file
@@ -0,0 +1,142 @@
|
||||
# Aether Project Architecture
|
||||
|
||||
This document outlines the overall architecture and key technologies used in the Aether SvelteKit frontend project.
|
||||
|
||||
## 1. Project Overview
|
||||
|
||||
The Aether project is a Svelte and SvelteKit based application, utilizing Tailwind CSS and Skeleton for styling and UI elements. It serves as the frontend UI/UX for the Aether system, which interacts with a Python FastAPI backend.
|
||||
|
||||
## 2. Core Technologies
|
||||
|
||||
- **Frontend Framework:** Svelte 5 and SvelteKit v2
|
||||
- **Routing:** SvelteKit's file-system based routing.
|
||||
- **Styling:** Tailwind CSS v4
|
||||
- **UI Component Libraries:**
|
||||
- Skeleton (Design System, Tailwind Components, Functional Components - being phased out due to conflicts with Tailwind CSS v4)
|
||||
- Flowbite (Tailwind Components)
|
||||
- Custom Components (a growing library of `ae_comp__*` and `element_*` components)
|
||||
- **Text/Code Editors:**
|
||||
- CodeMirror 6.x (primary text and code editor, planned for rich text editing)
|
||||
- Edra (TipTap based Rich Text Editor)
|
||||
- **Note:** ShadEditor TipTap is present but marked for removal, with CodeMirror being the preferred solution for all text editing needs.
|
||||
- **Icons:** Lucide Icons (SVG Icons)
|
||||
- **Markdown Parsing:** `marked` library
|
||||
- **State Management:** Svelte stores, potentially with `liveQuery` from Dexie for reactive IndexedDB interactions.
|
||||
|
||||
## 3. Module Structure
|
||||
|
||||
The Aether project is organized into several modules, categorized as Core, Extended, and Custom.
|
||||
|
||||
### 3.1. Official Modules
|
||||
|
||||
#### Core Modules
|
||||
|
||||
These are foundational modules essential for the application's basic functionality.
|
||||
|
||||
- **Accounts:** Minimal implementation.
|
||||
- **Files:** Manages hosted files.
|
||||
- **People:** Minimal implementation for person records.
|
||||
- **Sites:** Minimal implementation for site configurations.
|
||||
- **Users:** Minimal implementation for user management.
|
||||
|
||||
#### Extended Modules
|
||||
|
||||
These modules provide additional features and functionalities.
|
||||
|
||||
- **Archives:** Minimal implementation.
|
||||
- **Events:** Includes features for Badges and Presentation Management.
|
||||
- **Posts:** Minimal implementation.
|
||||
- **Journals:** Manages journal entries.
|
||||
|
||||
#### Custom Modules
|
||||
|
||||
These modules are tailored for specific client needs.
|
||||
|
||||
- **IDAA:** Includes Archives, Bulletin Board (BB), and Recovery Meetings functionalities.
|
||||
|
||||
## 4. Data Storage Mechanisms
|
||||
|
||||
### 4.1. Local Storage
|
||||
|
||||
Used for client-side persistence of various application states and configurations.
|
||||
|
||||
- `api`: API-related settings.
|
||||
- `app`: Global application settings.
|
||||
- `core`: Settings and data specific to core modules.
|
||||
- `<module>`: Settings and data specific to extended modules.
|
||||
- `<custom>`: Settings and data specific to custom modules.
|
||||
|
||||
### 4.2. IndexedDB (Dexie.js)
|
||||
|
||||
Used for more structured client-side data storage, often for caching and offline capabilities.
|
||||
|
||||
- `ae_core_db`: Core database instance.
|
||||
- `<module>`: Module-specific database instances.
|
||||
- `<custom>`: Custom module-specific database instances (none currently defined).
|
||||
|
||||
## 5. Data Sorting
|
||||
|
||||
Standardized sorting orders are applied across various data lists.
|
||||
|
||||
- **Default/General:** `group > priority > sort > updated_on/created_on`
|
||||
- **Specific (e.g., Events):** `type > start_date/time > code or name`
|
||||
|
||||
## 6. Object Properties and Fields
|
||||
|
||||
A set of standardized field names and types are used across Aether objects.
|
||||
|
||||
### 6.1. Core Standard Fields
|
||||
|
||||
These fields are expected to be present in most Aether objects.
|
||||
|
||||
- `id`: Primary key for an object (internal use, often a UUID).
|
||||
- `id_random`: Randomly generated ID for an object (often used for external exposure or URL parameters).
|
||||
- `<object_type>_id_random`: Specific random ID for an object (e.g., `person_id_random`).
|
||||
- `code`: Short, unique identifier.
|
||||
- `name`: Display name.
|
||||
- `enable`: Boolean for active/inactive status.
|
||||
- `hide`: Boolean for visibility.
|
||||
- `priority`: Numeric value for ordering.
|
||||
- `sort`: Numeric value for ordering.
|
||||
- `group`: Categorization string.
|
||||
- `notes`: General notes/comments.
|
||||
- `created_on`: Timestamp of creation.
|
||||
- `updated_on`: Timestamp of last update.
|
||||
|
||||
### 6.2. Special Use Fields
|
||||
|
||||
Fields with specific purposes or conditional usage.
|
||||
|
||||
- `for_type`: Indicates the type of object this object is linked to.
|
||||
- `for_id`: The ID of the object this object is linked to.
|
||||
- `archive_on`: Timestamp for archiving.
|
||||
- `passcode`: Password or access code.
|
||||
- `external_id`: ID from an external system.
|
||||
|
||||
### 6.3. Configuration and JSON Fields
|
||||
|
||||
Fields designed to store JSON data.
|
||||
|
||||
- `cfg_json`: Configuration data in JSON format.
|
||||
- `data_json`: General data in JSON format.
|
||||
- `linked_li_json`: List of linked items in JSON format.
|
||||
|
||||
### 6.4. Special Generated Fields (Client-side)
|
||||
|
||||
Fields generated on the client-side, primarily for sorting or UI logic.
|
||||
|
||||
- `tmp_sort_1`
|
||||
- `tmp_sort_2`
|
||||
- `tmp_sort_3`
|
||||
|
||||
### 6.5. Future Standard Fields
|
||||
|
||||
A list of potential future standard fields, often prefixed with `obj_`. These are currently conceptual and not yet fully integrated.
|
||||
|
||||
- `obj_id`, `obj_ext_uid`, `obj_ext_id`, `obj_import_id`, `obj_code`, `obj_account_id`, `obj_passcode`, `obj_type`, `obj_type_ver_id`, `obj_name`, `obj_summary`, `obj_outline`, `obj_description`, `obj_enable`, `obj_enable_on`, `obj_archive_on`, `obj_hide`, `obj_priority`, `obj_sort`, `obj_group`, `obj_cfg_json`, `obj_notes`, `obj_created_on`, `obj_updated_on`.
|
||||
|
||||
## 7. IndexedDB LiveQuery Usage
|
||||
|
||||
- `lq__xyz_obj`: Used for general read-only access to liveQuery results.
|
||||
- `lqw__xyz_obj`: Used for forms and binding values, representing a writable snapshot of liveQuery results.
|
||||
- **Note:** Care must be taken when binding to `lqw__xyz_obj` to manage updates and potential conflicts with the underlying liveQuery.
|
||||
148
documentation/COMPONENTS.md
Normal file
148
documentation/COMPONENTS.md
Normal file
@@ -0,0 +1,148 @@
|
||||
# Aether Project Components
|
||||
|
||||
This document details the various UI components used throughout the Aether SvelteKit frontend project, categorized by their scope and functionality.
|
||||
|
||||
## 1. Aether Components (UI/UX)
|
||||
|
||||
### 1.1. System Components
|
||||
|
||||
These components are part of the core application shell and provide global functionalities.
|
||||
|
||||
- **`header`**: Application-wide header.
|
||||
- **`main/module`s**: Main content area for modules.
|
||||
- **`footer`**: Application-wide footer.
|
||||
- **`app`**: Provides global application functionalities such as:
|
||||
- Refresh application state.
|
||||
- Clear IndexedDB.
|
||||
- Clear local storage (settings).
|
||||
- Toggle iframe visibility (also updates URL parameter).
|
||||
- Copy current URL.
|
||||
- Generate and display QR codes.
|
||||
- **`menu`**: Various menus for different purposes:
|
||||
- **`mode`**: Edit mode toggle, more options (all or details).
|
||||
- **`access_type`**: Passcode input, clear access.
|
||||
- **`user`**: Sign in/out, reset password, email link, change username and email.
|
||||
- **`theme`**: Mode (light/dark), name (theme list).
|
||||
- **`debug`**: Developer-facing tools:
|
||||
- Toggle debug mode (also updates URL parameter).
|
||||
- Show core and module storages.
|
||||
- Manually set initial timestamp.
|
||||
- **`scroll_to`**: Navigation controls for scrolling:
|
||||
- Scroll to top of the page.
|
||||
- Scroll page up.
|
||||
- Scroll page down.
|
||||
- Scroll to bottom of the page.
|
||||
|
||||
### 1.2. Core Components
|
||||
|
||||
These are reusable components that provide common functionalities across different modules.
|
||||
|
||||
- **`copy_btn`**: A button to copy content to the clipboard.
|
||||
- Properties: `clipboard`, `bind:value`, `btn_text`, `btn_html`.
|
||||
- **`txt_editor`**: A basic text area editor.
|
||||
- **`md_editor`**: Markdown editor.
|
||||
- Uses CodeMirror (planned for rich text editing).
|
||||
- **Note:** ShadEditor TipTap is present but marked for removal. ShadCN components are also being phased out in favor of CodeMirror for text editing.
|
||||
- **`html_editor`**: HTML editor.
|
||||
- **`media_player`**: Component for playing media files.
|
||||
- Properties: `hosted_file`, `archive_content`, `media_player`.
|
||||
- Bindings: `bind:host_id`, `bind:media_type`.
|
||||
- Status: `stopped`, `paused`, `playing`.
|
||||
- **`hosted_file_li`**: Manages a list of hosted files, making them available for selection.
|
||||
- **`hosted_file_link_to`**: Lists links per object, with bindings to add/remove links.
|
||||
- **`upload_to_host`**: Component for uploading files to the host.
|
||||
- Handles multiple files.
|
||||
- Properties: `link_type`, `link_id`, `inner fragment` (label html).
|
||||
- Bindings: `bind:trigger`, `bind:show_spinner`, `bind:show_percent`.
|
||||
- Status: `started`, `uploading`, `finished`.
|
||||
- **`upload_file_tbl`**: Table for uploaded files, includes checks for duplicate file hashes and removal from the list.
|
||||
- **`download_from_host`**: Component for downloading files from the host.
|
||||
- Bindings: `bind:host_file_id`, `bind:filename`, `bind:file_ext`.
|
||||
- Properties: `btn inner fragment`.
|
||||
- Bindings: `bind:trigger`, `bind:show_spinner`, `bind:show_percent`.
|
||||
- Status: `started`, `downloading`, `finished`.
|
||||
- **`data_store`**: Component for interacting with data stores.
|
||||
- **`ae_crud`**: Generic CRUD (Create, Read, Update, Delete) component.
|
||||
- **Note:** Needs simplification.
|
||||
- Properties: `obj`, `prop`, `current_value`.
|
||||
- Bindings: `bind:value`, `bind:trigger`, `inner fragment`.
|
||||
- **`ae_obj_prop_val`**: A wrapper for a function to manage object property values.
|
||||
- Bindings: `bind:obj_type`, `bind:obj_id`, `bind:obj_prop`, `bind:obj_value`, `bind:obj_new_value`, `bind:trigger`, `bind:show_spinner`, `bind:show_percent`.
|
||||
- Status: `status`, `result`.
|
||||
- **`sql_qry`**: Component for executing SQL queries.
|
||||
- **`obj_tbl`**: Object SQL results table or similar.
|
||||
- **`qr_scanner`**: Component for scanning QR codes.
|
||||
- **`websocket`**: Component for WebSocket communication.
|
||||
|
||||
### 1.3. Main / Module Components
|
||||
|
||||
These are components specific to main application sections or individual modules.
|
||||
|
||||
- **`menu`**:
|
||||
- **`options`**: Various settings, show/hide content and options, limit, sorting options.
|
||||
- **`actions`**: Various actions, sign in/out, email.
|
||||
|
||||
### 1.4. Object Menu
|
||||
|
||||
A standardized menu for interacting with objects.
|
||||
|
||||
- **Properties Displayed:** `id`, `name`, `group`, `priority`, `sort`, `alert`, `hide`, `enable`, `note`.
|
||||
- **Future Properties:** `ext_id`, `ext_sys_id`, `code` (not yet ready).
|
||||
- **Actions:** `create`, `view`, `edit`, `update`, `hide`, `disable`, `delete`, `alert` (message), `archive` (not yet ready).
|
||||
- **Future Actions:** `copy`, `import`.
|
||||
- **Sort Options:**
|
||||
- `[default]`: `group > priority > sort (ASC/DESC) > alert > name`
|
||||
- `[sort_updated]`: `group > priority > sort (ASC/DESC) > alert > updated_on > created_on`
|
||||
- `[priority_updated]`: `group > priority > updated_on (ASC/DESC) > created_on`
|
||||
- `[priority_name]`: `group > priority > name (ASC/DESC) > sort > alert > updated_on > created_on`
|
||||
- `[name]`: `priority > name (ASC/DESC) > sort > alert > updated_on > created_on`
|
||||
- `[created_on]`: `priority > created_on (ASC/DESC)`
|
||||
- `[updated_on]`: `priority > updated_on (ASC/DESC) > created_on`
|
||||
|
||||
## 2. Pop-ups
|
||||
|
||||
Standardized structure for various types of pop-up elements.
|
||||
|
||||
- **`modal_header`**:
|
||||
- `title`
|
||||
- `close` button
|
||||
- **`modal_main`**: Main content area of the modal.
|
||||
- **`modal_meta`**: Meta-information section.
|
||||
- **`modal_footer`**:
|
||||
- `close` button
|
||||
- **`Pop-up Modal (blocking)`**: A modal that blocks interaction with the rest of the page.
|
||||
- `modal position`
|
||||
- **`Pop-up Modal Inline`**: A modal that appears inline with content.
|
||||
- `inline`, `inline-block`, `block` display options.
|
||||
- **`Pop-up Dialog`**: A dialog box.
|
||||
- `dialog position`
|
||||
|
||||
## 3. Containers
|
||||
|
||||
Generic container types used for layout and grouping.
|
||||
|
||||
### 3.1. Navigation
|
||||
|
||||
- `link`
|
||||
- `download`
|
||||
|
||||
### 3.2. Forms
|
||||
|
||||
- `save` button/action
|
||||
- `clear value` action
|
||||
- `set null value` action
|
||||
|
||||
### 3.3. Other Containers
|
||||
|
||||
- `help`: Blue themed container.
|
||||
- `info`: Blue themed container.
|
||||
- `alert`: Yellow themed container.
|
||||
- `warning`: Orange themed container.
|
||||
- `error`: Red themed container.
|
||||
- `message`: Green themed container.
|
||||
|
||||
## 4. CSS Styling for UI Elements
|
||||
|
||||
- **Warning/Hide Buttons:** `variant-soft-warning hover:variant-filled-warning`
|
||||
- **Error/Delete/Disable Buttons:** `variant-soft-error hover:variant-filled-error`
|
||||
- **Submenu:** `flex flex-row items-center justify-center gap-1`
|
||||
90
documentation/DATA_STRUCTURES.md
Normal file
90
documentation/DATA_STRUCTURES.md
Normal file
@@ -0,0 +1,90 @@
|
||||
# Aether Project Data Structures
|
||||
|
||||
This document outlines the key data structures and their properties used within the Aether SvelteKit frontend project. It covers object properties, field definitions, and how data is managed.
|
||||
|
||||
## 1. Object Properties and Fields
|
||||
|
||||
### 1.1. Core Standard Fields
|
||||
|
||||
These fields are expected to be present in most Aether objects, providing a consistent base structure.
|
||||
|
||||
- `id`: Primary key for an object (internal use, often a UUID).
|
||||
- `id_random`: Randomly generated ID for an object (often used for external exposure or URL parameters).
|
||||
- `<object_type>_id_random`: Specific random ID for an object (e.g., `person_id_random`).
|
||||
- `code`: Short, unique identifier.
|
||||
- `name`: Display name.
|
||||
- `enable`: Boolean for active/inactive status.
|
||||
- `hide`: Boolean for visibility.
|
||||
- `priority`: Numeric value for ordering.
|
||||
- `sort`: Numeric value for ordering.
|
||||
- `group`: Categorization string.
|
||||
- `notes`: General notes/comments.
|
||||
- `created_on`: Timestamp of creation.
|
||||
- `updated_on`: Timestamp of last update.
|
||||
|
||||
### 1.2. Special Use Fields
|
||||
|
||||
Fields with specific purposes or conditional usage across different object types.
|
||||
|
||||
- `for_type`: Indicates the type of object this object is linked to (e.g., 'account', 'event').
|
||||
- `for_id`: The ID of the object this object is linked to.
|
||||
- `archive_on`: Timestamp indicating when an object was archived.
|
||||
- `passcode`: A password or access code associated with an object.
|
||||
- `external_id`: An identifier from an external system.
|
||||
|
||||
### 1.3. Configuration and JSON Fields
|
||||
|
||||
Fields designed to store structured data in JSON format.
|
||||
|
||||
- `cfg_json`: Configuration data for an object, stored as a JSON string.
|
||||
- `data_json`: General purpose data for an object, stored as a JSON string.
|
||||
- `linked_li_json`: A list of linked items, stored as a JSON string.
|
||||
|
||||
### 1.4. Special Generated Fields (Client-side)
|
||||
|
||||
These fields are generated on the client-side, primarily for facilitating UI logic, such as sorting. They are not typically stored in the backend database.
|
||||
|
||||
- `tmp_sort_1`: Temporary sort field 1.
|
||||
- `tmp_sort_2`: Temporary sort field 2.
|
||||
- `tmp_sort_3`: Temporary sort field 3.
|
||||
|
||||
### 1.5. Future Standard Fields
|
||||
|
||||
A list of potential future standard fields, often prefixed with `obj_`. These are conceptual and represent planned expansions to the data model.
|
||||
|
||||
- `obj_id`, `obj_ext_uid`, `obj_ext_id`, `obj_import_id`, `obj_code`, `obj_account_id`, `obj_passcode`, `obj_type`, `obj_type_ver_id`, `obj_name`, `obj_summary`, `obj_outline`, `obj_description`, `obj_enable`, `obj_enable_on`, `obj_archive_on`, `obj_hide`, `obj_priority`, `obj_sort`, `obj_group`, `obj_cfg_json`, `obj_notes`, `obj_created_on`, `obj_updated_on`.
|
||||
|
||||
## 2. Data Sorting
|
||||
|
||||
Standardized sorting orders are applied across various data lists to ensure consistent presentation.
|
||||
|
||||
- **Default/General Sorting:** `group > priority > sort > updated_on/created_on`
|
||||
- **Specific Sorting (e.g., for time-based events):** `type > start_date/time > code or name`
|
||||
|
||||
## 3. Data Storage Mechanisms
|
||||
|
||||
### 3.1. Local Storage
|
||||
|
||||
Used for client-side persistence of various application states and configurations.
|
||||
|
||||
- `api`: Stores API-related settings and tokens.
|
||||
- `app`: Stores global application settings and preferences.
|
||||
- `core`: Stores settings and data specific to core modules.
|
||||
- `<module>`: Stores settings and data specific to extended modules (e.g., `journals`, `events`).
|
||||
- `<custom>`: Stores settings and data specific to custom modules (e.g., `idaa`).
|
||||
|
||||
### 3.2. IndexedDB (Dexie.js)
|
||||
|
||||
Used for more structured client-side data storage, often for caching, offline capabilities, and larger datasets.
|
||||
|
||||
- `ae_core_db`: The primary Dexie database instance for core application data.
|
||||
- `<module>`: Module-specific database instances (e.g., `db_journals` for journal data).
|
||||
- `<custom>`: Custom module-specific database instances (none currently defined, but reserved for future use).
|
||||
|
||||
### 3.3. IndexedDB LiveQuery Usage
|
||||
|
||||
Dexie's `liveQuery` is used to provide reactive data streams from IndexedDB.
|
||||
|
||||
- `lq__xyz_obj`: Represents a read-only liveQuery result for a single object.
|
||||
- `lqw__xyz_obj`: Represents a writable liveQuery result, typically used for forms and data binding.
|
||||
- **Note:** When using `lqw__xyz_obj`, developers must carefully manage updates to avoid conflicts with the underlying liveQuery and ensure data integrity.
|
||||
93
documentation/NAMING_CONVENTIONS.md
Normal file
93
documentation/NAMING_CONVENTIONS.md
Normal file
@@ -0,0 +1,93 @@
|
||||
# Aether Project Naming Conventions
|
||||
|
||||
## 1. General Principles
|
||||
|
||||
- **Clarity:** Names should clearly convey their purpose and meaning.
|
||||
- **Consistency:** Adhere strictly to these guidelines across the entire codebase.
|
||||
- **Readability:** Prioritize names that are easy to read and understand.
|
||||
- **Conciseness:** Avoid unnecessary verbosity, but not at the expense of clarity.
|
||||
|
||||
## 2. File Naming
|
||||
|
||||
- **Logic/Service Files:** `ae_<module>__<concept>.ts` (e.g., `ae_core__account.ts`, `ae_events__event.ts`)
|
||||
- **Database Definition Files:** `db_<module>.ts` (e.g., `db_core.ts`, `db_journals.ts`)
|
||||
- **Svelte Store Files:** `ae_<module>_stores.ts` (e.g., `ae_core_stores.ts`, `ae_journals_stores.ts`)
|
||||
- **Svelte Components:**
|
||||
- **Module-specific components:** `ae_comp__<module>__<component_name>.svelte` (e.g., `ae_comp__events__event_card.svelte`)
|
||||
- **Generic/reusable components:** `element_<component_name>.svelte` (e.g., `element_input_file.svelte`, `element_qr_scanner_v2.svelte`)
|
||||
- **SvelteKit Routes:** Follow SvelteKit's standard routing conventions (e.g., `+page.svelte`, `+layout.svelte`, `[id]/+page.svelte`).
|
||||
- **CSS Files:** `ae-<module>-<purpose>.css` (e.g., `ae-c-idaa-light.css`, `ae-osit-default.css`)
|
||||
|
||||
## 3. Function and Variable Naming
|
||||
|
||||
- **Style:** Strictly `snake_case` for all function and variable names.
|
||||
- **Deprecated:** `camelCase` should be refactored to `snake_case`.
|
||||
- **Prefixes:**
|
||||
- `load_ae_obj_id__<object_type>`: For loading a single Aether object by ID.
|
||||
- `load_ae_obj_li__<object_type>`: For loading a list of Aether objects.
|
||||
- `create_ae_obj__<object_type>`: For creating an Aether object.
|
||||
- `update_ae_obj__<object_type>`: For updating an Aether object.
|
||||
- `delete_ae_obj_id__<object_type>`: For deleting an Aether object by ID.
|
||||
- `db_save_ae_obj_li__<object_type>`: For saving a list of Aether objects to IndexedDB.
|
||||
- `db_update_ae_obj_id__<object_type>`: For updating an Aether object in IndexedDB.
|
||||
- `process_ae_obj__<object_type>_props`: For module-specific data transformation functions.
|
||||
- **Deprecated:** Ambiguous `handle_` prefixes should be replaced with more descriptive `snake_case` names (e.g., `handle_submit_form` -> `submit_form`).
|
||||
|
||||
## 4. Object and Property Naming
|
||||
|
||||
- **Singularity:** Use singular nouns for objects and properties (e.g., `example.id`, not `examples.id`).
|
||||
- **IDs:**
|
||||
- `id`: Primary key for an object (internal use, often a UUID).
|
||||
- `<object_type>_id`: Specific ID for an object (e.g., `person_id`).
|
||||
- `<object_type>_id_random`: Randomly generated ID for an object (often used for external exposure or URL parameters).
|
||||
- `account_id`, `site_id`, `user_id`, etc.: Foreign keys.
|
||||
- **Common Properties:**
|
||||
- `code`: Short, unique identifier.
|
||||
- `name`: Display name.
|
||||
- `description`: Longer text description.
|
||||
- `enable`: Boolean for active/inactive status.
|
||||
- `hide`: Boolean for visibility.
|
||||
- `priority`: Numeric value for ordering.
|
||||
- `sort`: Numeric value for ordering.
|
||||
- `group`: Categorization string.
|
||||
- `notes`: General notes/comments.
|
||||
- `created_on`: Timestamp of creation.
|
||||
- `updated_on`: Timestamp of last update.
|
||||
- **Special Use Properties:** `for_type`, `for_id`, `archive_on`, `passcode`, `external_id`.
|
||||
- **Config/JSON Properties:** `cfg_json`, `data_json`, `linked_li_json`.
|
||||
- **Special Generated Fields (Client-side):** `tmp_sort_1`, `tmp_sort_2`, `tmp_sort_3` (for client-side sorting).
|
||||
|
||||
## 5. List Suffixes
|
||||
|
||||
- **Simple Arrays:** Use `_li` suffix for simple, unordered arrays (e.g., `user_li`, `hosted_file_id_li`).
|
||||
- **Key-Value Maps/Objects:** Use `_kv` suffix for key-value objects/maps (e.g., `user_kv`, `hosted_file_obj_kv`).
|
||||
|
||||
## 6. Interface and Type Naming
|
||||
|
||||
- **Style:** Use `PascalCase` for interface and type names (e.g., `Account`, `HostedFile`, `GenericCrudArgs`).
|
||||
|
||||
## 7. Constants
|
||||
|
||||
- **Style:** Use `SCREAMING_SNAKE_CASE` for constants (e.g., `MAX_RETRIES`, `DEFAULT_TIMEOUT`).
|
||||
|
||||
## 8. CSS Classes and IDs
|
||||
|
||||
- **Style:** Use `kebab-case` for CSS classes and IDs (e.g., `my-component-class`, `main-header-id`).
|
||||
|
||||
## 9. Data Sorting
|
||||
|
||||
- **Standard Order:** `group > priority > sort > updated_on/created_on`
|
||||
- **Specific Order:** `type > start_date/time > code or name`
|
||||
|
||||
## 10. Local Storage and IndexedDB Keys
|
||||
|
||||
- **Local Storage:**
|
||||
- `api`
|
||||
- `app` (global)
|
||||
- `core` (core modules)
|
||||
- `<module>` (extended modules)
|
||||
- `<custom>` (custom modules)
|
||||
- **IndexedDB:**
|
||||
- `ae_core_db`
|
||||
- `<module>`
|
||||
- `<custom>`
|
||||
137
documentation/OLD_README_guidelines_ui_ux.md
Normal file
137
documentation/OLD_README_guidelines_ui_ux.md
Normal file
@@ -0,0 +1,137 @@
|
||||
# AE UI Components, Layout, and Style Standards (HTML/CSS)
|
||||
|
||||
## Aether Components
|
||||
|
||||
### System Components
|
||||
|
||||
- [header]
|
||||
- [main/module]s
|
||||
- [footer]
|
||||
- [app] refresh, clear IDB, clear local storage (settings), iframe toggle (also updates URL param), copy URL, generate and show QR
|
||||
- [menu][mode] edit, more (all or details)
|
||||
- [menu][access_type] passcode input, clear
|
||||
- [menu][user] sign in/out, reset password, email link, change username and email
|
||||
- [menu][theme] mode (light/dark), name (theme list)
|
||||
- [debug] toggle (also updates URL param), show core and module storages, manually set init timestamp
|
||||
- [scroll_to] top, page up, page down, bottom
|
||||
|
||||
### Core Components
|
||||
|
||||
- [copy_btn] clipboard, bind:value, btn_text, btn_html
|
||||
- [txt_editor] textarea
|
||||
- [md_editor] CodeMirror, ShadEditor TipTap (need to remove)
|
||||
- [html_editor]
|
||||
- [media_player]
|
||||
- hosted_file archive_content media_player,
|
||||
- bind:host_id,
|
||||
- bind:media_type
|
||||
- status - stopped, paused, playing
|
||||
- [hosted_file_li] manage_hosted_file_li, make available for selection
|
||||
- [hosted_file_link_to] list links per object, bind:add link, bind:remove link
|
||||
- [upload_to_host] - input_hosted_file; needs to handle multiple files
|
||||
- link_type,
|
||||
- link_id,
|
||||
- inner fragment - label html
|
||||
- bind:trigger
|
||||
- bind:show_spinner
|
||||
- bind:show_percent
|
||||
- status
|
||||
- result - started, uploading, finished
|
||||
- [upload_file_tbl] input_hosted_file_tbl, check for dup file hash, remove from list
|
||||
- [download_from_host]
|
||||
- bind:host_file_id
|
||||
- bind:filename
|
||||
- bind:file_ext
|
||||
- btn inner fragment
|
||||
- bind:trigger
|
||||
- bind:show_spinner
|
||||
- bind:show_percent
|
||||
- status
|
||||
- result - started, downloading, finished
|
||||
- [data_store]
|
||||
- [ae_crud] need to simplify! obj, prop, current_value, bind:value, bind:trigger, inner fragment
|
||||
- [ae_obj_prop_val] - essentially a wrapper for the function
|
||||
- bind:obj_type
|
||||
- bind:obj_id
|
||||
- bind:obj_prop
|
||||
- bind:obj_value
|
||||
- bind:obj_new_value
|
||||
- bind:trigger
|
||||
- bind:show_spinner
|
||||
- bind:show_percent
|
||||
- status
|
||||
- result
|
||||
- [sql_qry]
|
||||
- [obj_tbl] obj sql results tbl or similar
|
||||
- [qr_scanner]
|
||||
- [websocket]
|
||||
|
||||
### Main / Module Components
|
||||
|
||||
- [menu][options] various settings, show/hide content and options, limit, sorting options, etc
|
||||
- [menu][actions] various actions, sign in/out, email
|
||||
|
||||
### Object Menu
|
||||
|
||||
- properties: id, name, group, priority, sort, alert, hide, enable, note
|
||||
- future properties: ext_id (not ready yet), ext_sys_id (not ready yet), code (not ready yet)
|
||||
- actions: create, view, edit, update, hide, disable, delete, alert (message), archive (not ready yet)
|
||||
- future actions: copy, import
|
||||
- sort options:
|
||||
- [default] group > priority > sort (ASC/DESC) > alert > name
|
||||
- [sort_updated] group > priority > sort (ASC/DESC) > alert > updated_on > created_on
|
||||
- [priority_updated] group > priority > updated_on (ASC/DESC) > created_on
|
||||
- [priority_name] group > priority > name (ASC/DESC) > sort > alert > updated_on > created_on
|
||||
- [name] priority > name (ASC/DESC) > sort > alert > updated_on > created_on
|
||||
- [created_on] priority > created_on (ASC/DESC)
|
||||
- [updated_on] priority > updated_on (ASC/DESC) > created_on
|
||||
|
||||
### Pop-ups:
|
||||
|
||||
- modal_header
|
||||
- title
|
||||
- close
|
||||
- modal_main
|
||||
- modal_meta
|
||||
- modal_footer
|
||||
- close
|
||||
|
||||
#### Pop-up Modal (blocking)
|
||||
|
||||
- modal position
|
||||
|
||||
#### Pop-up Modal Inline
|
||||
|
||||
- inline, inline-block, block
|
||||
|
||||
#### Pop-up Dialog
|
||||
|
||||
- dialog position
|
||||
|
||||
## Containers
|
||||
|
||||
### Navigation
|
||||
|
||||
- link
|
||||
- download
|
||||
|
||||
### Forms
|
||||
|
||||
- save
|
||||
- clear value
|
||||
- set null value
|
||||
|
||||
### Other Containers
|
||||
|
||||
- help - blue
|
||||
- info - blue
|
||||
- alert - yellow
|
||||
- warning - orange
|
||||
- error - red
|
||||
- message - green
|
||||
|
||||
---
|
||||
|
||||
## Need to organize:
|
||||
|
||||
- lu: id, account_id, for_obj_id, code, name, description, group, sort, priority, enable, perm_level
|
||||
80
documentation/OLD_README_guidelines_v1.md
Normal file
80
documentation/OLD_README_guidelines_v1.md
Normal file
@@ -0,0 +1,80 @@
|
||||
# One Sky IT's Aether App - UI and UX Guidelines and Rules
|
||||
|
||||
## General
|
||||
|
||||
### Events
|
||||
|
||||
#### layout header
|
||||
|
||||
#### layout footer
|
||||
|
||||
### Journals
|
||||
|
||||
#### buttons
|
||||
|
||||
##### alert
|
||||
|
||||
##### info
|
||||
|
||||
##### priority, flag
|
||||
|
||||
##### warning, hide
|
||||
|
||||
```css
|
||||
variant-soft-warning hover:variant-filled-warning
|
||||
```
|
||||
|
||||
##### error, delete, disable
|
||||
|
||||
```css
|
||||
variant-soft-error hover:variant-filled-error
|
||||
```
|
||||
|
||||
#### new root layout header
|
||||
|
||||
#### submenu
|
||||
|
||||
```css
|
||||
flex flex-row items-center justify-center gap-1
|
||||
```
|
||||
|
||||
#### new layout footer
|
||||
|
||||
## Svelte 5 and SvelteKit v2 (framework and routing)
|
||||
|
||||
## Tailwind 3.x CSS (styles)
|
||||
|
||||
Waiting to upgrade to 4.x when ShadCN is ready. ShadCN is still being worked on as of late March 2025.
|
||||
|
||||
- https://ui.shadcn.com/docs/tailwind-v4
|
||||
|
||||
## CodeMirror 6.x (text and code editor)
|
||||
|
||||
- https://codemirror.net
|
||||
|
||||
## ShadCN (Tailwind Components)
|
||||
|
||||
- https://ui.shadcn.com/docs
|
||||
- https://github.com/shadcn-ui/ui
|
||||
|
||||
## Skeleton (Design System, Tailwind Components, Functional Components)
|
||||
|
||||
Waiting to upgrade to Skeleton v3. Mostly because of the Tailwind 4.x upgrade needed for ShadCN.
|
||||
|
||||
- https://www.skeleton.dev/docs/get-started/migrate-from-v2
|
||||
|
||||
## Flowbite (Tailwind Components)
|
||||
|
||||
## Lucide Icons (SVG Icons)
|
||||
|
||||
- https://lucide.dev/icons/
|
||||
|
||||
## Markdown
|
||||
|
||||
Using marked for Markdown parsing.
|
||||
|
||||
- https://marked.js.org/
|
||||
|
||||
## Edra (TipTap based Rich Text Editor)
|
||||
|
||||
- https://edra.tsuzat.com/
|
||||
173
documentation/OLD_README_guidelines_v2.md
Normal file
173
documentation/OLD_README_guidelines_v2.md
Normal file
@@ -0,0 +1,173 @@
|
||||
# AE Svelte and SvelteKit Technical Standards
|
||||
|
||||
## Official Modules
|
||||
|
||||
### Core
|
||||
|
||||
- Accounts - Minimal
|
||||
- Files
|
||||
- People - Minimal
|
||||
- Sites - Minimal
|
||||
- Users - Minimal
|
||||
|
||||
### Extended
|
||||
|
||||
Archives - Minimal, Events - Badges, Events - Presentation Management, Posts - Minimal, Journals
|
||||
|
||||
### Custom
|
||||
|
||||
IDAA - Archives, IDAA - BB, IDAA - Recovery Meetings
|
||||
|
||||
---
|
||||
|
||||
## localStorage:
|
||||
|
||||
- api
|
||||
- app - global
|
||||
- core - core modules
|
||||
- [module] - extended modules
|
||||
- [custom] - custom modules
|
||||
|
||||
---
|
||||
|
||||
## Indexed DB
|
||||
|
||||
- ae_core_db
|
||||
- [module]
|
||||
- [custom] - custom modules: none currently
|
||||
|
||||
---
|
||||
|
||||
## Data Sorting
|
||||
|
||||
- group > priority > sort > updated/created on
|
||||
- type > start date/time > code or name
|
||||
|
||||
---
|
||||
|
||||
## Objects
|
||||
|
||||
### Function - Obj Prop Update
|
||||
|
||||
- obj_type
|
||||
- obj_id
|
||||
- obj_prop
|
||||
- obj_value
|
||||
|
||||
### Core
|
||||
|
||||
### Extended
|
||||
|
||||
### Custom
|
||||
|
||||
---
|
||||
|
||||
## Object Properties or Fields
|
||||
|
||||
### Core
|
||||
|
||||
Expected standard field names: id, id_random, [obj-type]\_id_random, code, name, enable, hide, priority, sort, group, notes, created_on, updated_on
|
||||
Special use field names: for_type, for_id, archive_on, passcode, external_id
|
||||
|
||||
### Configs and Fields with JSON
|
||||
|
||||
- cfg_json
|
||||
- data_json
|
||||
- linked_li_json
|
||||
|
||||
### Special Generated Fields
|
||||
|
||||
tmp_sort_1, tmp_sort_2,
|
||||
|
||||
### Future standard fields!!!
|
||||
|
||||
obj_id?: null|string;
|
||||
obj_ext_uid?: null|string; // Probably not needed for journals
|
||||
obj_ext_id?: null|string; // Probably not needed for journals
|
||||
obj_import_id?: null|string; // Probably not needed for journals
|
||||
obj_code?: null|string;
|
||||
obj_account_id?: null|string;
|
||||
obj_passcode?: null|string;
|
||||
obj_type?: null|string; // Should always be 'journal' in this case
|
||||
obj_type_ver_id?: null|string; // The ID from the table for the object type
|
||||
obj_name?: null|string;
|
||||
obj_summary?: null|string; // LLM (AI) generated summary...???
|
||||
obj_outline?: null|string; // LLM (AI) generated outline...???
|
||||
obj_description?: null|string; // Probably not needed for journals
|
||||
obj_enable?: null|boolean;
|
||||
obj_enable_on?: null|Date;
|
||||
obj_archive_on?: null|Date;
|
||||
obj_hide?: null|boolean;
|
||||
obj_priority?: null|number;
|
||||
obj_sort?: null|number;
|
||||
obj_group?: null|string;
|
||||
obj_cfg_json?: null|string;
|
||||
obj_notes?: null|string;
|
||||
obj_created_on?: Date;
|
||||
obj_updated_on?: null|Date;
|
||||
|
||||
## Dixie IDB liveQuery with Select Objects (slct) and Lists of Objects (slct_x_li)
|
||||
|
||||
Use this method below to create a read/write snapshot of the current liveQuery results. This allows you to use it as part of a form and binding values. It might make since to call this something like "lqw**x_obj" and "lqw**x_obj_li". lqw = liveQuery writable
|
||||
|
||||
lq**xyz_obj - Use for general read only
|
||||
lqw**xyz_obj - Use for forms and binding values. What happens if the actual LQ obj is updated after the bind?
|
||||
$slct or $lqw ?
|
||||
|
||||
Sort of related.... more permission/security though: Create a new table that will be attached to every v\_ view in the DB. This new table would be a field permission list. It could work similar to the data_store table and related view. This seems like a good idea????? 2025-08-11
|
||||
|
||||
```ts
|
||||
let lq__post_obj = $derived(
|
||||
liveQuery(async () => {
|
||||
if (log_lvl) {
|
||||
console.log(`lq__post_obj: post_id = ${$idaa_slct?.post_id}`);
|
||||
}
|
||||
let results = await db_posts.post.get($idaa_slct.post_id ?? ''); // null or undefined does not reset things like '' does
|
||||
|
||||
// Check if results are different than the current $idaa_slct.post_obj
|
||||
if ($idaa_slct.post_obj && results) {
|
||||
if (JSON.stringify($idaa_slct.post_obj) !== JSON.stringify(results)) {
|
||||
$idaa_slct.post_obj = { ...results };
|
||||
if (log_lvl) {
|
||||
console.log(`$idaa_slct.post_obj = `, $idaa_slct.post_obj);
|
||||
}
|
||||
} else {
|
||||
if (log_lvl) {
|
||||
console.log(`Post object has not changed for post_id: ${$idaa_slct.post_id}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
})
|
||||
);
|
||||
|
||||
let lq__post_comment_obj_li = $derived(
|
||||
liveQuery(async () => {
|
||||
let results = await db_posts.comment
|
||||
.where('post_id')
|
||||
.equals($idaa_slct.post_id ?? '') // null or undefined does not reset things like '' does
|
||||
.reverse()
|
||||
.sortBy('updated_on');
|
||||
// .sortBy('title');
|
||||
|
||||
if (
|
||||
$idaa_slct.post_comment_obj_li &&
|
||||
JSON.stringify($idaa_slct.post_comment_obj_li) !== JSON.stringify(results)
|
||||
) {
|
||||
$idaa_slct.post_comment_obj_li = [...results];
|
||||
if (log_lvl) {
|
||||
console.log(`$idaa_slct.post_comment_obj_li = `, $idaa_slct.post_comment_obj_li);
|
||||
}
|
||||
} else {
|
||||
if (log_lvl) {
|
||||
console.log(
|
||||
`Post comment object list has not changed for post_id: ${$idaa_slct.post_id}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
})
|
||||
);
|
||||
```
|
||||
108
documentation/SVELTE_DEXIE_GUIDE.md
Normal file
108
documentation/SVELTE_DEXIE_GUIDE.md
Normal file
@@ -0,0 +1,108 @@
|
||||
# Svelte and Dexie.js Integration Guide
|
||||
|
||||
This document provides a guide to integrating Svelte (with a focus on Runes) and Dexie.js for building reactive web applications. It covers key concepts and best practices for managing reactivity between Svelte components and the Dexie.js database.
|
||||
|
||||
## Svelte 5 Migration Guide
|
||||
|
||||
Svelte 5 introduces "runes" as a new way to manage reactivity. This is a major change from previous versions of Svelte, and it's important to understand the breaking changes before migrating.
|
||||
|
||||
### Key Breaking Changes
|
||||
|
||||
- **`let` is no longer reactive:** In Svelte 4, any `let` variable declared in the top-level scope of a component was automatically reactive. In Svelte 5, you must explicitly declare reactive state using the `$state` rune.
|
||||
- **`$:` is replaced by `$derived` and `$effect`:** The `$` label is no longer used for reactive statements. Instead, you should use the `$derived` rune for computed values and the `$effect` rune for side effects.
|
||||
- **`export let` is replaced by `$props`:** Component props are now declared using the `$props` rune, which provides a more flexible and explicit way to define component APIs.
|
||||
- **Event handling:** The `on:` directive is replaced by event attributes (e.g., `onclick`). Component events are now handled using callback props instead of `createEventDispatcher`.
|
||||
- **Slots are replaced by snippets:** The `<slot>` element is replaced by the `{#snippet ...}` block, which provides a more powerful and flexible way to pass content to components.
|
||||
|
||||
For a complete list of breaking changes, refer to the [Svelte 5 migration guide](https://svelte.dev/docs/svelte/v5-migration-guide).
|
||||
|
||||
## Dexie.js Quick Reference
|
||||
|
||||
Dexie.js is a lightweight, minimalistic wrapper for IndexedDB that makes it easier to work with client-side databases.
|
||||
|
||||
### Key Classes and Methods
|
||||
|
||||
- **`Dexie`:** The main class for creating and managing IndexedDB databases.
|
||||
- `new Dexie(databaseName)`: Creates a new database instance.
|
||||
- `version(versionNumber).stores({ ... })`: Defines the database schema.
|
||||
- **`Table`:** Represents an object store (table) in the database.
|
||||
- `add(item)`: Adds a new item to the table.
|
||||
- `put(item)`: Adds or updates an item in the table.
|
||||
- `update(key, changes)`: Updates an existing item.
|
||||
- `delete(key)`: Deletes an item by its primary key.
|
||||
- `get(key)`: Retrieves an item by its primary key.
|
||||
- `where(index)`: Starts a query using an index.
|
||||
- `toArray()`: Retrieves all items from the table as an array.
|
||||
- **`Collection`:** Represents a collection of items resulting from a query.
|
||||
- `toArray()`: Retrieves all items in the collection as an array.
|
||||
- `first()`: Retrieves the first item in the collection.
|
||||
- `last()`: Retrieves the last item in the collection.
|
||||
- `each(callback)`: Iterates over each item in the collection.
|
||||
- `modify(changes)`: Updates all items in the collection.
|
||||
- `delete()`: Deletes all items in the collection.
|
||||
|
||||
For a complete list of API methods, refer to the [Dexie.js API Reference](https://dexie.org/docs/API-Reference).
|
||||
|
||||
## Integrating Svelte Runes and Dexie.js
|
||||
|
||||
The combination of Svelte Runes and Dexie.js allows for the creation of highly reactive and efficient web applications.
|
||||
|
||||
### The `liveQuery` Function
|
||||
|
||||
Dexie.js provides a `liveQuery` function that returns an observable of the query result. This observable can be used to automatically update the UI whenever the data in the database changes.
|
||||
|
||||
### Using `liveQuery` with Svelte Runes
|
||||
|
||||
To use `liveQuery` with Svelte Runes, you can create a custom readable store that wraps the `liveQuery` observable. This store can then be used in your Svelte components to display and interact with the data.
|
||||
|
||||
**1. Create a `liveQuery` store:**
|
||||
|
||||
```typescript
|
||||
import { liveQuery } from 'dexie';
|
||||
import { readable } from 'svelte/store';
|
||||
import { db } from './db'; // Your Dexie database instance
|
||||
|
||||
export function createLiveQueryStore<T>(query: () => T | Promise<T>) {
|
||||
return readable<T | undefined>(undefined, (set) => {
|
||||
const subscription = liveQuery(query).subscribe({
|
||||
next: (result) => set(result),
|
||||
error: (error) => console.error(error)
|
||||
});
|
||||
return () => subscription.unsubscribe();
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
**2. Use the `createLiveQueryStore` in your component:**
|
||||
|
||||
```html
|
||||
<script>
|
||||
import { createLiveQueryStore } from './stores';
|
||||
import { db } from './db';
|
||||
|
||||
const friends = createLiveQueryStore(() => db.friends.toArray());
|
||||
</script>
|
||||
|
||||
<ul>
|
||||
{#if $friends} {#each $friends as friend}
|
||||
<li>{friend.name}</li>
|
||||
{/each} {/if}
|
||||
</ul>
|
||||
```
|
||||
|
||||
The `createLiveQueryStore` function creates a readable store that automatically updates whenever the data in the `friends` table changes. The `$friends` variable in the component will always contain the latest data from the database.
|
||||
|
||||
## Current Data Flow in `ae_journals` Module
|
||||
|
||||
The `ae_journals` module currently uses a manual, API-first caching strategy. It does not use Dexie.js's `liveQuery` function for reactivity.
|
||||
|
||||
### Data Flow
|
||||
|
||||
1. **Fetch from API:** The `load_ae_obj_id__journal` and `load_ae_obj_li__journal` functions are used to fetch data from the API.
|
||||
2. **Process Data:** The `process_ae_obj__journal_props` and `process_ae_obj__journal_entry_props` functions are used to process the data before it's saved to the database. This includes parsing Markdown, creating temporary sorting fields, and combining passcodes.
|
||||
3. **Save to IndexedDB:** The `db_save_ae_obj_li__ae_obj` function is used to save the processed data to the `journal` and `journal_entry` tables in the `ae_journals_db` IndexedDB database.
|
||||
4. **Manual Store Updates:** The Svelte stores in `src/lib/ae_journals/ae_journals_stores.ts` are manually updated with the fetched data.
|
||||
|
||||
### Future Improvements
|
||||
|
||||
The current implementation could be improved by refactoring it to use Dexie.js's `liveQuery` function. This would simplify the code, reduce boilerplate, and improve the reactivity of the application. By using `liveQuery`, the UI would automatically update whenever the data in the IndexedDB database changes, without the need for manual store updates.
|
||||
38
eslint.config.js
Normal file
38
eslint.config.js
Normal file
@@ -0,0 +1,38 @@
|
||||
// @ts-check
|
||||
|
||||
import eslint from '@eslint/js';
|
||||
import tseslint from 'typescript-eslint';
|
||||
import svelte from 'eslint-plugin-svelte';
|
||||
import prettier from 'eslint-config-prettier';
|
||||
import globals from 'globals';
|
||||
|
||||
export default tseslint.config(
|
||||
eslint.configs.recommended,
|
||||
...tseslint.configs.recommended,
|
||||
svelte.configs['flat/recommended'],
|
||||
prettier,
|
||||
{
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.browser,
|
||||
...globals.node
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
files: ['**/*.svelte'],
|
||||
languageOptions: {
|
||||
parserOptions: {
|
||||
parser: tseslint.parser
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
ignores: ['build/', '.svelte-kit/', 'node_modules/']
|
||||
},
|
||||
{
|
||||
rules: {
|
||||
'@typescript-eslint/no-unused-vars': 'warn'
|
||||
}
|
||||
}
|
||||
);
|
||||
49
index.html
49
index.html
@@ -1,49 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<!-- Load dayjs library: https://cdnjs.com/libraries/dayjs -->
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/dayjs/1.11.10/dayjs.min.js" integrity="sha512-FwNWaxyfy2XlEINoSnZh1JQ5TRRtGow0D6XcmAWmYCRgvqOUTnzCxPc9uF35u5ZEpirk1uhlPVA19tflhvnW1g==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/dayjs/1.11.10/plugin/utc.min.js" integrity="sha512-z84O912dDT9nKqvpBnl1tri5IN0j/OEgMzLN1GlkpKLMscs5ZHVu+G2CYtA6dkS0YnOGi3cODt3BOPnYc8Agjg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/dayjs/1.11.10/plugin/timezone.min.js" integrity="sha512-jmsGNYDezdyZ+W3bVeZy83kZp/2n5BgWe/0solkveG0vSSrP9XIVTD1tNiM1OqImc4H3OxHfs1uSfVclOU3mWw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
||||
<script src="https://static.oneskyit.com/js/tinymce/tinymce.min.js"></script>
|
||||
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css" integrity="sha512-1ycn6IcaQQ40/MKBW2W4Rhis/DbILU74C1vSrLJxCq57o941Ym01SwNsOMqvEBFlcgUa6xLiPY/NS5R+E6ztJQ==" crossorigin="anonymous" referrerpolicy="no-referrer" />
|
||||
|
||||
<!-- <link rel="stylesheet" href="/src/main.css" /> -->
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Æ AE App (The Hub) - Sponsorships - Vite + Svelte + TS</title>
|
||||
<script>
|
||||
let api_base_url = 'https://dev-api.oneskyit.com';
|
||||
let api_base_url_backup = 'https://bak-api.oneskyit.com';
|
||||
let app_base_url = 'https://dev-demo.oneskyit.com';
|
||||
let app_base_url_backup = 'https://bak-demo.oneskyit.com';
|
||||
</script>
|
||||
|
||||
<script>
|
||||
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<section id="Site-Header">Site-Header</section>
|
||||
<section id="Site-Nav-Menu"></section>
|
||||
<!-- <section id="Notifications">Notifications</section> -->
|
||||
|
||||
<div class="svelte_target ae_svelte_app ae_sponsorships_main"></div>
|
||||
|
||||
<section id="Site-Set-Access-Type" class="svelte_target set_access_type"></section>
|
||||
|
||||
<section id="Site-Footer">Site-Footer</section>
|
||||
|
||||
<section id="Site-Modals"><!-- Site-Modals --></section>
|
||||
|
||||
<div class="svelte_target ae_svelte_app_hub"></div>
|
||||
|
||||
<!-- The ae_bridge_init.js and main.ts should be run back to back -->
|
||||
<script src="/ae_bridge_init.js"></script>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
</html>
|
||||
7
jsconfig.json
Normal file
7
jsconfig.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"paths": {
|
||||
"$lib/*": ["./src/lib/*"]
|
||||
}
|
||||
}
|
||||
}
|
||||
9708
package-lock.json
generated
9708
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
140
package.json
140
package.json
@@ -1,26 +1,118 @@
|
||||
{
|
||||
"name": "ae_sponsorships_app_svelte",
|
||||
"private": true,
|
||||
"version": "0.0.1",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview",
|
||||
"check": "svelte-check --tsconfig ./tsconfig.json"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sveltejs/adapter-static": "^3.0.1",
|
||||
"@sveltejs/vite-plugin-svelte": "^3.0.0",
|
||||
"@tsconfig/svelte": "^5.0.0",
|
||||
"svelte": "^4.2.8",
|
||||
"svelte-check": "^3.6.0",
|
||||
"tslib": "^2.6.0",
|
||||
"typescript": "^5.3.0",
|
||||
"vite": "^5.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"aether_npm_lib": "bitbucket:oneskyit/one-sky-it-npm-library",
|
||||
"axios": "^1.6.0"
|
||||
}
|
||||
"name": "osit-aether-app-svelte",
|
||||
"version": "3.11.18",
|
||||
"description": "One Sky IT's Aether App created with Svelte, SvelteKit, Tailwind CSS, Lucide, Font Awesome, and Skeleton UI. -Scott Idem",
|
||||
"homepage": "https://oneskyit.com/",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vite dev",
|
||||
"build": "vite build",
|
||||
"build:prod": "cp .env.prod .env.production && vite build",
|
||||
"build:staging": "cp .env.staging .env.production && vite build",
|
||||
"preview": "vite preview",
|
||||
"test": "npm run test:integration && npm run test:unit",
|
||||
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
||||
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
||||
"lint": "prettier --check . && eslint .",
|
||||
"format": "prettier --write .",
|
||||
"test:integration": "playwright test",
|
||||
"test:unit": "vitest"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.39.1",
|
||||
"@playwright/test": "^1.56.1",
|
||||
"@skeletonlabs/skeleton": "3.2.2",
|
||||
"@skeletonlabs/skeleton-svelte": "1.5.3",
|
||||
|
||||
"@sveltejs/adapter-auto": "^7.0.0",
|
||||
"@sveltejs/adapter-node": "^5.0.0",
|
||||
"@sveltejs/adapter-static": "^3.0.1",
|
||||
"@sveltejs/kit": "^2.48.5",
|
||||
"@sveltejs/vite-plugin-svelte": "^6.0.0",
|
||||
"@tailwindcss/forms": "^0.5.7",
|
||||
"@tailwindcss/typography": "^0.5.10",
|
||||
"@types/eslint": "^9.0.0",
|
||||
"@types/node": "^24.0.0",
|
||||
"@types/qrcode": "^1.5.5",
|
||||
"@typescript-eslint/eslint-plugin": "^8.47.0",
|
||||
"@typescript-eslint/parser": "^8.47.0",
|
||||
"bits-ui": "^2.14.3",
|
||||
"clsx": "^2.1.1",
|
||||
"eslint": "^9.0.0",
|
||||
"eslint-config-prettier": "^10.0.0",
|
||||
"eslint-plugin-svelte": "^3.13.0",
|
||||
"flowbite": "^4.0.0",
|
||||
"globals": "^16.5.0",
|
||||
"highlight.js": "^11.10.0",
|
||||
"lowlight": "^3.2.0",
|
||||
"mode-watcher": "^1.0.0",
|
||||
"prettier": "^3.6.2",
|
||||
"prettier-plugin-svelte": "^3.2.6",
|
||||
"sass-embedded": "^1.81.0",
|
||||
"svelte": "^5.43.10",
|
||||
"svelte-awesome-color-picker": "^4.0.0",
|
||||
"svelte-check": "^4.0.0",
|
||||
"svelte-highlight": "^7.8.4",
|
||||
"svelte-idle": "^3.0.1",
|
||||
"tailwind-merge": "^3.0.0",
|
||||
"tailwind-variants": "^3.*.*",
|
||||
"tailwindcss": "^4.1.10",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"tslib": "^2.4.1",
|
||||
"typescript": "^5.5.0",
|
||||
"typescript-svelte-plugin": "^0.3.50",
|
||||
"vite": "^7.0.0",
|
||||
"vitest": "^4.0.0"
|
||||
},
|
||||
"vitest": {
|
||||
"exclude": [
|
||||
"tests"
|
||||
]
|
||||
},
|
||||
"type": "module",
|
||||
"overrides": {
|
||||
"@codemirror/state": "^6.5.2",
|
||||
"@codemirror/view": "^6.38.8",
|
||||
"@codemirror/language": "^6.11.3",
|
||||
"@codemirror/commands": "^6.10.0",
|
||||
"@codemirror/lang-markdown": "^6.5.0",
|
||||
"@codemirror/autocomplete": "^6.20.0",
|
||||
"@codemirror/search": "^6.5.11",
|
||||
"@codemirror/lint": "^6.9.2",
|
||||
"@lezer/common": "^1.4.0",
|
||||
"@lezer/highlight": "^1.2.3",
|
||||
"@lezer/lr": "^1.4.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"@codemirror/autocomplete": "^6.20.0",
|
||||
"@codemirror/commands": "^6.10.0",
|
||||
"@codemirror/lang-css": "^6.3.1",
|
||||
"@codemirror/lang-html": "^6.4.9",
|
||||
"@codemirror/lang-javascript": "^6.2.3",
|
||||
"@codemirror/lang-json": "^6.0.1",
|
||||
"@codemirror/lang-markdown": "^6.5.0",
|
||||
"@codemirror/language": "^6.11.3",
|
||||
"@codemirror/language-data": "^6.5.1",
|
||||
"@codemirror/lint": "^6.9.2",
|
||||
"@codemirror/search": "^6.5.11",
|
||||
"@codemirror/state": "^6.5.2",
|
||||
"@codemirror/theme-one-dark": "^6.1.2",
|
||||
"@codemirror/view": "^6.38.8",
|
||||
"@floating-ui/dom": "^1.6.0",
|
||||
"@lucide/svelte": "^0.*.0",
|
||||
"@popperjs/core": "^2.11.0",
|
||||
"@tailwindcss/vite": "^4.1.10",
|
||||
"axios": "^1.7.0",
|
||||
"dayjs": "^1.11.10",
|
||||
"dexie": "^4.0.0",
|
||||
"flowbite-svelte": "^1.28.1",
|
||||
"html5-qrcode": "^2.3.8",
|
||||
"lucide-svelte": "^0.*.0",
|
||||
"marked": "^17.0.0",
|
||||
"openai": "^6.10.0",
|
||||
"qrcode": "^1.5.4",
|
||||
"shadcn-svelte": "^1.0.11",
|
||||
"svelte-persisted-store": "^0.12.0",
|
||||
"typescript-eslint": "^8.47.0"
|
||||
}
|
||||
}
|
||||
|
||||
23
playwright.config.ts
Normal file
23
playwright.config.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import type { PlaywrightTestConfig } from '@playwright/test';
|
||||
|
||||
const config: PlaywrightTestConfig = {
|
||||
webServer: {
|
||||
command: 'npm run build && npm run preview',
|
||||
port: 4173
|
||||
// url: 'http://scott.localhost:5173',
|
||||
// reuseExistingServer: true,
|
||||
// stderr: 'pipe',
|
||||
// stdout: 'pipe',
|
||||
},
|
||||
testDir: 'tests',
|
||||
testMatch: /(.+\.)?(test|spec)\.[jt]s/,
|
||||
reporter: 'list',
|
||||
use: {
|
||||
// Collect trace when retrying the failed test.
|
||||
trace: 'on-first-retry'
|
||||
}
|
||||
// grep: /@node_modules/,
|
||||
// grepInverse: /@node_modules/,
|
||||
};
|
||||
|
||||
export default config;
|
||||
@@ -1,175 +0,0 @@
|
||||
|
||||
// These localStorage values were created when generating the HTML
|
||||
|
||||
// let ae_local = window.localStorage.getItem('ae'); // Includes: cfg, client, page, other
|
||||
// let ae_session = window.sessionStorage.getItem('ae'); // Includes: cfg, client, page, other
|
||||
// let ae_com_local = window.localStorage.getItem('ae_com');
|
||||
// let ae_com_session = window.sessionStorage.getItem('ae_com');
|
||||
|
||||
if (window.localStorage.getItem('ae') === null) {
|
||||
window.localStorage.setItem('ae', JSON.stringify({ 'cfg': {}, 'client': {}, 'page': {}, 'other': {}, 'test': {} }));
|
||||
}
|
||||
|
||||
if (window.sessionStorage.getItem('ae') === null) {
|
||||
window.sessionStorage.setItem('ae', JSON.stringify({ 'cfg': {}, 'client': {}, 'page': {}, 'other': {}, 'test': {} }));
|
||||
}
|
||||
// JSON.parse(window.sessionStorage.getItem('ae'))
|
||||
|
||||
// export let ae_bridge = {
|
||||
const ae_bridge = {
|
||||
// example_var: 'Example Default Value',
|
||||
// get example() {
|
||||
// return this.example_var;
|
||||
// },
|
||||
// set example(new_value) {
|
||||
// this.example_var = new_value;
|
||||
// this.example_var_listener(new_value);
|
||||
// this.example_var_core_listener(new_value);
|
||||
// this.example_var_mods_listener(new_value);
|
||||
// },
|
||||
|
||||
// example_var_listener: function (new_value) {},
|
||||
// registerNewListener: function (external_listener_function) {
|
||||
// this.example_var_listener = external_listener_function;
|
||||
// },
|
||||
|
||||
// example_var_core_listener: function (new_value) {},
|
||||
// registerNewCoreListener: function (external_core_listener_function) {
|
||||
// this.example_var_core_listener = external_core_listener_function;
|
||||
// },
|
||||
|
||||
// example_var_mods_listener: function (new_value) {},
|
||||
// registerNewModsListener: function (external_mods_listener_function) {
|
||||
// this.example_var_mods_listener = external_mods_listener_function;
|
||||
// },
|
||||
|
||||
|
||||
// Monitor change in **local** storage AE
|
||||
// Created and set when generating and then rendering the inital HTML and JS
|
||||
// ae_local_var: true,
|
||||
ae_local_var: JSON.parse(window.localStorage.getItem('ae')),
|
||||
get ae_local() {
|
||||
return this.ae_local_var;
|
||||
},
|
||||
set ae_local(new_value) {
|
||||
console.log('ae_local_var: new_value: ', new_value);
|
||||
this.ae_local_var = new_value;
|
||||
this.ae_local_listener(new_value);
|
||||
window.localStorage.setItem('ae', new_value);
|
||||
},
|
||||
|
||||
ae_local_listener: function (new_value) {},
|
||||
register_ae_local_listener: function (external_listener_function) {
|
||||
this.ae_local_listener = external_listener_function;
|
||||
},
|
||||
|
||||
|
||||
// Monitor change in **session* storage AE
|
||||
// Created and set when generating and then rendering the inital HTML and JS
|
||||
// ae_session_var: true,
|
||||
// ae_session_var: JSON.parse((window.sessionStorage.getItem('ae') ? window.sessionStorage.getItem('ae') : {'cfg': true, 'client': true, 'page': true, 'other': true})),
|
||||
// ae_session_var: {'example': 'This is just an example from init.js!'},
|
||||
ae_session_var: JSON.parse(window.sessionStorage.getItem('ae')),
|
||||
get ae_session() {
|
||||
return this.ae_session_var;
|
||||
},
|
||||
set ae_session(new_value) {
|
||||
console.log('ae_session_var: new_value: ', new_value);
|
||||
this.ae_session_var = new_value;
|
||||
this.ae_session_listener(new_value);
|
||||
window.sessionStorage.setItem('ae', new_value);
|
||||
},
|
||||
|
||||
ae_session_listener: function (new_value) {},
|
||||
register_ae_session_listener: function (external_listener_function) {
|
||||
this.ae_session_listener = external_listener_function;
|
||||
},
|
||||
|
||||
|
||||
// Monitor change in Access Type
|
||||
access_type_var: 'anonymous',
|
||||
get access_type() {
|
||||
return this.access_type_var;
|
||||
},
|
||||
set access_type(new_value) {
|
||||
this.access_type_var = new_value;
|
||||
this.access_type_var_core_listener(new_value);
|
||||
this.access_type_var_mods_listener(new_value);
|
||||
},
|
||||
|
||||
access_type_var_core_listener: function (new_value) {},
|
||||
register_core_access_type_listener: function (external_core_listener_function) {
|
||||
this.access_type_var_core_listener = external_core_listener_function;
|
||||
},
|
||||
|
||||
access_type_var_mods_listener: function (new_value) {},
|
||||
register_mods_access_type_listener: function (external_mods_listener_function) {
|
||||
this.access_type_var_mods_listener = external_mods_listener_function;
|
||||
},
|
||||
|
||||
|
||||
// Monitor change in AE Common
|
||||
// ae_com_var: true,
|
||||
ae_com_var: JSON.parse(window.localStorage.getItem('ae_com')),
|
||||
get ae_com() {
|
||||
return this.ae_com_var;
|
||||
},
|
||||
set ae_com(new_value) {
|
||||
this.ae_com_var = new_value;
|
||||
this.ae_com_var_core_listener(new_value);
|
||||
this.ae_com_var_mods_listener(new_value);
|
||||
},
|
||||
|
||||
ae_com_var_core_listener: function (new_value) {},
|
||||
register_core_ae_com_listener: function (external_core_listener_function) {
|
||||
this.ae_com_var_core_listener = external_core_listener_function;
|
||||
},
|
||||
|
||||
ae_com_var_mods_listener: function (new_value) {},
|
||||
register_mods_ae_com_listener: function (external_mods_listener_function) {
|
||||
this.ae_com_var_mods_listener = external_mods_listener_function;
|
||||
},
|
||||
|
||||
|
||||
// Monitor change in Client
|
||||
client_var: true,
|
||||
get client() {
|
||||
return this.client_var;
|
||||
},
|
||||
set client(new_value) {
|
||||
this.client_var = new_value;
|
||||
this.client_var_core_listener(new_value);
|
||||
this.client_var_mods_listener(new_value);
|
||||
},
|
||||
|
||||
client_var_core_listener: function (new_value) {},
|
||||
register_core_client_listener: function (external_core_listener_function) {
|
||||
this.client_var_core_listener = external_core_listener_function;
|
||||
},
|
||||
|
||||
client_var_mods_listener: function (new_value) {},
|
||||
register_mods_client_listener: function (external_mods_listener_function) {
|
||||
this.client_var_mods_listener = external_mods_listener_function;
|
||||
},
|
||||
|
||||
};
|
||||
console.log('ae_bridge_init.js loaded');
|
||||
|
||||
|
||||
// Updated: 2024-02-09
|
||||
/* BEGIN: Add this to the stores.ts */
|
||||
// This adds a listener to the ae_bridge object. This can then be exported and used in the Svelte components.
|
||||
// export let ae_example = writable(ae_bridge.ae_example);
|
||||
// ae_bridge.register_ae_example_listener((new_value) => {
|
||||
// console.log(`AE Bridge: AE Example: ${new_value}`);
|
||||
// console.log(new_value);
|
||||
|
||||
// ae_example.set(new_value);
|
||||
// console.log(ae_example);
|
||||
// });
|
||||
/* END: Add this to the stores.ts */
|
||||
|
||||
|
||||
/* BEGIN: Add this to the Svelte components */
|
||||
// import { ae_example } from './stores';
|
||||
/* END: Add this to the Svelte components */
|
||||
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
||||
|
Before Width: | Height: | Size: 1.5 KiB |
@@ -1,617 +0,0 @@
|
||||
<script lang="ts">
|
||||
type key_val = {
|
||||
[key: string]: any;
|
||||
};
|
||||
// *** Import Svelte core
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
// *** Import Aether core variables and functions
|
||||
import { ae, api, Element_modal_v3 } from 'aether_npm_lib';
|
||||
|
||||
import { slct, slct_trigger, ae_app } from './stores';
|
||||
|
||||
// *** Import Aether core components
|
||||
// import { get_data_store_obj_w_code } from '../data_store/stores_data_store_api.js';
|
||||
|
||||
// *** Import Aether module variables and functions
|
||||
// import { get_account_archive_obj_list } from './stores_ae_api.js';
|
||||
|
||||
// *** Import Aether module components
|
||||
import Edit_archive_obj from './10_edit__archive_obj.svelte';
|
||||
import List_archive_obj from './10_list__archive_obj.svelte';
|
||||
import View_archive_obj from './10_view__archive_obj.svelte';
|
||||
|
||||
// *** Export/Exposed variables and functions for component
|
||||
// export let account_id: string = $page['page_for']['account_id'];
|
||||
export let account_id: string = $ae_app.account_id;
|
||||
export let archive_id: string = $ae_app.archives.archive_id;
|
||||
|
||||
export let novi_uuid: string = $ae_app.novi_uuid;
|
||||
export let novi_email: string = $ae_app.novi_email;
|
||||
export let novi_full_name: string = $ae_app.novi_full_name;
|
||||
export let novi_admin_li: string = $ae_app.novi_admin_li;
|
||||
export let novi_trusted_li: string = $ae_app.novi_trusted_li;
|
||||
|
||||
// *** Set initial variables
|
||||
$ae_app.novi_uuid = novi_uuid;
|
||||
$ae_app.novi_email = decodeURIComponent(novi_email);
|
||||
$ae_app.novi_full_name = decodeURIComponent(novi_full_name);
|
||||
$ae_app.novi_admin_li = novi_admin_li;
|
||||
$ae_app.novi_trusted_li = novi_trusted_li;
|
||||
|
||||
$ae_app.current_timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
||||
if (!$ae_app.lu_timezone_list) {
|
||||
$ae_app.lu_timezone_list = [];
|
||||
}
|
||||
|
||||
$ae_app.archives.show_main__options = true; // Section for: buttons for creating new archives, show/hide archives, and search archives
|
||||
// $ae_app.archives.show_list__archive_obj_li = true;
|
||||
// $ae_app.archives.show_view__archive_obj = $ae_app.archives.show_view__archive_obj;
|
||||
$ae_app.archives.fulltext_search_qry_str = '';
|
||||
$ae_app.archives.qry_type = false
|
||||
|
||||
// NOTE: Check if the novi_uuid is in the novi_admin_li list
|
||||
if ($ae_app.novi_uuid && $ae_app.novi_admin_li) {
|
||||
if ($ae_app.novi_admin_li.includes($ae_app.novi_uuid)) {
|
||||
$ae_app.access_type = 'administrator';
|
||||
$ae_app.administrator_access = true;
|
||||
$ae_app.trusted_access = true;
|
||||
}
|
||||
}
|
||||
// NOTE: Check if the novi_uuid is in the novi_trusted_li list
|
||||
if ($ae_app.novi_uuid && $ae_app.novi_trusted_li) {
|
||||
if ($ae_app.novi_trusted_li.includes($ae_app.novi_uuid)) {
|
||||
$ae_app.access_type = 'trusted';
|
||||
$ae_app.trusted_access = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($ae_app.administrator_access) {
|
||||
$ae_app.archives.enabled = 'enabled';
|
||||
$ae_app.archives.hidden = 'not_hidden';
|
||||
$ae_app.archives.limit = 150;
|
||||
} else if ($ae_app.trusted_access) {
|
||||
$ae_app.archives.enabled = 'enabled';
|
||||
$ae_app.archives.hidden = 'not_hidden';
|
||||
$ae_app.archives.limit = 75;
|
||||
} else {
|
||||
$ae_app.archives.enabled = 'enabled';
|
||||
$ae_app.archives.hidden = 'not_hidden';
|
||||
$ae_app.archives.limit = 75;
|
||||
}
|
||||
|
||||
let idaa_archive_obj_li_get_promise;
|
||||
let idaa_archive_obj_get_promise;
|
||||
|
||||
if (account_id) {
|
||||
$slct.account_id = account_id;
|
||||
handle_load_archive_obj_li({account_id: $slct.account_id, try_cache: false});
|
||||
}
|
||||
|
||||
if (archive_id) {
|
||||
console.log(`Selected Archive ID: ${archive_id}`);
|
||||
$slct.archive_id = archive_id;
|
||||
$slct_trigger = 'load__archive_obj';
|
||||
|
||||
// $ae_app.archives.show_main__options = true;
|
||||
$ae_app.archives.show_list__archive_obj_li = false;
|
||||
$ae_app.archives.show_view__archive_obj = true;
|
||||
$ae_app.archives.show_edit__archive_obj = false;
|
||||
} else {
|
||||
// $ae_app.archives.show_main__options = true;
|
||||
$ae_app.archives.show_list__archive_obj_li = true;
|
||||
$ae_app.archives.show_view__archive_obj = false;
|
||||
$ae_app.archives.show_edit__archive_obj = false;
|
||||
}
|
||||
|
||||
if (!$ae_app.client_content) {
|
||||
$ae_app.client_content = {};
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
console.log('** Component Mounted: ** IDAA Archives - AE Archives: Main');
|
||||
});
|
||||
|
||||
|
||||
$: if ($ae_app.iframe_height && $ae_app.iframe_height_modal_body) {
|
||||
console.log('getting new dimensions for iframe:', $ae_app.iframe_height, $ae_app.iframe_height_modal_body);
|
||||
|
||||
let iframe_height = 0;
|
||||
|
||||
if ($ae_app.iframe_height > $ae_app.iframe_height_modal_body) {
|
||||
iframe_height = $ae_app.iframe_height;
|
||||
} else {
|
||||
iframe_height = $ae_app.iframe_height_modal_body;
|
||||
|
||||
// console.log($ae_app.modal_dimensions);
|
||||
|
||||
if ($ae_app.modal_dimensions && $ae_app.modal_dimensions.header_height) {
|
||||
iframe_height = iframe_height + $ae_app.modal_dimensions.header_height;
|
||||
}
|
||||
if ($ae_app.modal_dimensions && $ae_app.modal_dimensions.footer_height) {
|
||||
iframe_height = iframe_height + $ae_app.modal_dimensions.footer_height;
|
||||
}
|
||||
// iframe_height = iframe_height + 50; // Just in case
|
||||
}
|
||||
|
||||
console.log(`Suggested new iframe_height: ${iframe_height}`);
|
||||
window.parent.postMessage({'iframe_height': iframe_height}, "*"); // This should be in pixels
|
||||
} else if ($ae_app.iframe_height) {
|
||||
console.log('setting new iframe_height:', $ae_app.iframe_height);
|
||||
|
||||
// let iframe_height = $ae_app.iframe_height;
|
||||
|
||||
window.parent.postMessage({'iframe_height': $ae_app.iframe_height}, "*"); // This should be in pixels
|
||||
}
|
||||
|
||||
$: if ($slct_trigger == 'load__archive_obj' && $slct.archive_id) {
|
||||
console.log('*** $slct_trigger == load__archive_obj ***');
|
||||
$slct_trigger = null;
|
||||
|
||||
handle_load_archive_obj({archive_id: $slct.archive_id, try_cache: false});
|
||||
|
||||
// Auto show the selected Archive ID
|
||||
// Is this pushState needed here?
|
||||
// Set the URL param "archive_id" to the current Archive ID. This is a just in case.
|
||||
// const url = new URL(location);
|
||||
// url.searchParams.set('archive_id', $slct.archive_id);
|
||||
// history.pushState({}, '', url);
|
||||
|
||||
// Is this postMessage needed here?
|
||||
let message = {'archive_id': $slct.archive_id};
|
||||
window.parent.postMessage(message, "*");
|
||||
|
||||
// $ae_app.archives.show_main__options = false;
|
||||
// $ae_app.archives.show_list__archive_obj_li = false;
|
||||
// $ae_app.archives.show_view__archive_obj = true;
|
||||
// $ae_app.archives.show_edit__archive_obj = false;
|
||||
}
|
||||
|
||||
$: if ($slct_trigger == 'load__archive_obj_li' && $slct.account_id) {
|
||||
console.log('*** $slct_trigger == load__archive_obj_li ***');
|
||||
$slct_trigger = null;
|
||||
|
||||
handle_load_archive_obj_li({account_id: $slct.account_id, try_cache: false});
|
||||
}
|
||||
|
||||
async function handle_load_archive_obj_li({account_id, try_cache=true}) {
|
||||
console.log('*** handle_load_archive_obj_li() ***');
|
||||
console.log($ae_app.archives);
|
||||
|
||||
let enabled = $ae_app.archives.enabled;
|
||||
let hidden = $ae_app.archives.hidden;
|
||||
let limit = $ae_app.archives.limit;
|
||||
let offset = $ae_app.archives.offset;
|
||||
|
||||
let params = {};
|
||||
|
||||
let params_json: key_val = {};
|
||||
if ($ae_app.archives.fulltext_search_qry_str && $ae_app.archives.fulltext_search_qry_str.length > 2) {
|
||||
params_json['ft_qry'] = {
|
||||
'default_qry_str': $ae_app.archives.fulltext_search_qry_str,
|
||||
};
|
||||
}
|
||||
|
||||
if ($ae_app.archives.qry_audio || $ae_app.archives.qry_video || $ae_app.archives.qry_other) {
|
||||
params_json['and_qry'] = {};
|
||||
if ($ae_app.archives.qry_audio) params_json['and_qry']['audio'] = true;
|
||||
if ($ae_app.archives.qry_video) params_json['and_qry']['video'] = true;
|
||||
if ($ae_app.archives.qry_other) params_json['and_qry']['other'] = $ae_app.archives.qry_other;
|
||||
}
|
||||
|
||||
console.log('params_json:', params_json);
|
||||
|
||||
idaa_archive_obj_li_get_promise = api.get_ae_obj_li_for_obj_id_crud({
|
||||
api_cfg: $ae_app.ae_api,
|
||||
obj_type: 'archive', // Archive in this case is an IDAA archive.
|
||||
for_obj_type: 'account',
|
||||
for_obj_id: account_id,
|
||||
use_alt_table: false, // NOTE: This will use the table_name_alt value instead of the table_name value in the API config.
|
||||
use_alt_base: false, // NOTE: This will use the base_name_alt value instead of the base_name value in the API config.
|
||||
enabled: enabled,
|
||||
hidden: hidden,
|
||||
order_by_li: {'priority': 'DESC', 'sort': 'DESC', 'created_on': 'DESC', 'updated_on': 'DESC'},
|
||||
limit: limit,
|
||||
offset: offset,
|
||||
params_json: params_json,
|
||||
params: params,
|
||||
log_lvl: 1
|
||||
})
|
||||
|
||||
.then(function (archive_obj_li_get_result) {
|
||||
if (archive_obj_li_get_result) {
|
||||
$slct.archive_obj_li = archive_obj_li_get_result;
|
||||
console.log(`Archive list:`, $slct.archive_obj_li);
|
||||
} else {
|
||||
$slct.archive_obj_li = [];
|
||||
}
|
||||
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log('No results returned or failed.', error);
|
||||
});
|
||||
|
||||
return idaa_archive_obj_li_get_promise;
|
||||
}
|
||||
|
||||
async function handle_load_archive_obj({archive_id, try_cache=false}) {
|
||||
console.log('*** handle_load_archive_obj() ***');
|
||||
|
||||
// let enabled = $ae_app.archives.enabled;
|
||||
// let hidden = $ae_app.archives.hidden;
|
||||
// let limit = $ae_app.archives.limit;
|
||||
// let offset = $ae_app.archives.offset;
|
||||
|
||||
let params = {};
|
||||
|
||||
idaa_archive_obj_get_promise = api.get_ae_obj_id_crud({
|
||||
api_cfg: $ae_app.ae_api,
|
||||
obj_type: 'archive',
|
||||
obj_id: archive_id,
|
||||
use_alt_table: false, // NOTE: This will use the table_name_alt value instead of the table_name value in the API config.
|
||||
use_alt_base: false, // NOTE: This will use the base_name_alt value instead of the base_name value in the API config.
|
||||
params: params,
|
||||
log_lvl: 0
|
||||
})
|
||||
.then(function (archive_obj_get_result) {
|
||||
if (archive_obj_get_result) {
|
||||
$slct.archive_obj = archive_obj_get_result;
|
||||
// console.log($slct.archive_obj.cfg_json.content_group_sort);
|
||||
$ae_app.archives.content_group_sort = $slct.archive_obj.cfg_json.content_group_sort;
|
||||
console.log(`Archive object:`, $slct.archive_obj);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log('No results returned or failed.', error);
|
||||
});
|
||||
|
||||
return idaa_archive_obj_get_promise;
|
||||
}
|
||||
|
||||
function handle_created_archive_obj(event) {
|
||||
console.log('*** handle_created_archive_obj() ***');
|
||||
console.log(event.detail);
|
||||
|
||||
handle_load_archive_obj({archive_id: $slct.archive_id, try_cache: false});
|
||||
|
||||
const url = new URL(location);
|
||||
url.searchParams.set('archive_id', $slct.archive_id);
|
||||
history.pushState({}, '', url);
|
||||
|
||||
let message = {'archive_id': $slct.archive_id};
|
||||
window.parent.postMessage(message, "*");
|
||||
|
||||
// $slct_trigger = 'load__archive_obj';
|
||||
$slct_trigger = 'load__archive_obj_li';
|
||||
|
||||
// $ae_app.archives.show_main__options = false;
|
||||
$ae_app.archives.show_list__archive_obj_li = false;
|
||||
$ae_app.archives.show_view__archive_obj = true;
|
||||
$ae_app.archives.show_edit__archive_obj = false;
|
||||
}
|
||||
|
||||
function handle_updated_archive_obj(event) {
|
||||
console.log('*** handle_updated_archive_obj() ***');
|
||||
console.log(event.detail);
|
||||
|
||||
$slct_trigger = 'load__archive_obj';
|
||||
// NOTE: If the next trigger is set too quickly it will cause the one above to be missed.
|
||||
// $slct_trigger = 'load__archive_obj_li';
|
||||
|
||||
// $ae_app.archives.show_main__options = false;
|
||||
$ae_app.archives.show_list__archive_obj_li = false;
|
||||
$ae_app.archives.show_view__archive_obj = true;
|
||||
$ae_app.archives.show_edit__archive_obj = false;
|
||||
}
|
||||
|
||||
function handle_deleted_archive_obj(event) {
|
||||
console.log('*** handle_deleted_archive_obj() ***');
|
||||
console.log(event.detail);
|
||||
|
||||
const url = new URL(location);
|
||||
url.searchParams.delete('archive_id');
|
||||
history.pushState({}, '', url);
|
||||
|
||||
let message = {'archive_id': null};
|
||||
window.parent.postMessage(message, "*");
|
||||
|
||||
$slct_trigger = 'load__archive_obj_li';
|
||||
|
||||
$ae_app.archives.show_main__options = true;
|
||||
$ae_app.archives.show_list__archive_obj_li = true;
|
||||
$ae_app.archives.show_view__archive_obj = false;
|
||||
$ae_app.archives.show_edit__archive_obj = false;
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<section id="osit_idaa_archives" class="osit_archives ae_main c_idaa c_idaa_archives" bind:clientHeight={$ae_app.iframe_height}>
|
||||
<!-- <header>
|
||||
<h1>IDAA Archives</h1>
|
||||
</header> -->
|
||||
|
||||
<section class="ae_section ae_meta">
|
||||
<p>
|
||||
Novi: {$ae_app.novi_full_name}
|
||||
<span class="details">
|
||||
(
|
||||
{$ae_app.novi_email}
|
||||
{#if $ae_app.administrator_access}
|
||||
<span class="access_type administrator_access">Administrator</span>
|
||||
{:else if $ae_app.trusted_access}
|
||||
<span class="access_type trusted_access">Trusted</span>
|
||||
{/if}
|
||||
<span class="novi_uuid">UUID: {$ae_app.novi_uuid}</span>
|
||||
)
|
||||
</span>
|
||||
</p>
|
||||
<!-- <p>Page height: {window.innerHeight}</p> -->
|
||||
</section>
|
||||
|
||||
{#if $ae_app.archives.show_main__options}
|
||||
<section class="ae_section ae_options ae_column archive_obj__options">
|
||||
|
||||
<!-- <div class="note">A comment about the IDAA archives in general can go here.</div> -->
|
||||
|
||||
<div class="filters_and_search ae_group ae_row">
|
||||
|
||||
<!-- Show/hide hidden content -->
|
||||
|
||||
{#if $ae_app.trusted_access}
|
||||
{#if $ae_app.archives.hidden == 'not_hidden'}
|
||||
<button
|
||||
on:click={() => {
|
||||
$ae_app.archives.hidden = 'all';
|
||||
$ae_app.archives.limit = 150;
|
||||
$slct_trigger = 'load__archive_obj_li';
|
||||
}}
|
||||
class="btn_new_bb_post ae_btn btn_xs ae_smallest btn btn-xs btn-info"
|
||||
>
|
||||
<span class="fas fa-eye"></span> Show Hidden Archives
|
||||
</button>
|
||||
{:else}
|
||||
<button
|
||||
on:click={() => {
|
||||
$ae_app.archives.hidden = 'not_hidden';
|
||||
$slct_trigger = 'load__archive_obj_li';
|
||||
}}
|
||||
class="btn_new_bb_post ae_btn btn_xs btn btn-xs btn-info"
|
||||
>
|
||||
<span class="fas fa-eye-slash"></span> Hide Hidden Archives
|
||||
</button>
|
||||
{/if}
|
||||
|
||||
<!-- We only want these options to show if a specific archive is showing. -->
|
||||
{#if $ae_app.archives.show_view__archive_obj}
|
||||
{#if $ae_app.archives.hidden == 'not_hidden'}
|
||||
<button
|
||||
on:click={() => {
|
||||
$ae_app.archives.hidden = 'all';
|
||||
$ae_app.archives.limit = 150;
|
||||
$slct_trigger = 'load__archive_content_obj_li';
|
||||
}}
|
||||
class="btn_new_bb_post ae_btn btn_xs ae_smallest btn btn-xs btn-info"
|
||||
>
|
||||
<span class="fas fa-eye"></span> Show Hidden Content
|
||||
</button>
|
||||
{:else}
|
||||
<button
|
||||
on:click={() => {
|
||||
$ae_app.archives.hidden = 'not_hidden';
|
||||
$slct_trigger = 'load__archive_content_obj_li';
|
||||
}}
|
||||
class="btn_new_bb_post ae_btn btn_xs btn btn-xs btn-info"
|
||||
>
|
||||
<span class="fas fa-eye-slash"></span> Hide Hidden Content
|
||||
</button>
|
||||
{/if}
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
<!-- For administrator access: Show/hide disabled content -->
|
||||
|
||||
{#if $ae_app.administrator_access}
|
||||
{#if $ae_app.archives.enabled == 'enabled'}
|
||||
<button
|
||||
on:click={() => {
|
||||
$ae_app.archives.hidden = 'all';
|
||||
$ae_app.archives.enabled = 'all';
|
||||
$ae_app.archives.limit = 500;
|
||||
$slct_trigger = 'load__archive_obj_li';
|
||||
}}
|
||||
class="ae_btn btn_xs ae_smallest btn btn-xs btn-warning"
|
||||
>
|
||||
<span class="fas fa-eye"></span> Show Disabled Archives
|
||||
</button>
|
||||
{:else}
|
||||
<button
|
||||
on:click={() => {
|
||||
$ae_app.archives.enabled = 'enabled';
|
||||
$slct_trigger = 'load__archive_obj_li';
|
||||
}}
|
||||
class="ae_btn btn_xs ae_smallest btn btn-xs btn-warning"
|
||||
>
|
||||
<span class="fas fa-eye-slash"></span> Hide Disabled Archives
|
||||
</button>
|
||||
{/if}
|
||||
|
||||
{#if $ae_app.archives.enabled == 'enabled'}
|
||||
<button
|
||||
on:click={() => {
|
||||
$ae_app.archives.hidden = 'all';
|
||||
$ae_app.archives.enabled = 'all';
|
||||
$ae_app.archives.limit = 500;
|
||||
$slct_trigger = 'load__archive_content_obj_li';
|
||||
}}
|
||||
class="ae_btn btn_xs ae_smallest btn btn-xs btn-warning"
|
||||
>
|
||||
<span class="fas fa-eye"></span> Show Disabled Content
|
||||
</button>
|
||||
{:else}
|
||||
<button
|
||||
on:click={() => {
|
||||
$ae_app.archives.enabled = 'enabled';
|
||||
$slct_trigger = 'load__archive_content_obj_li';
|
||||
}}
|
||||
class="ae_btn btn_xs btn btn-xs btn-warning"
|
||||
>
|
||||
<span class="fas fa-eye-slash"></span> Hide Disabled Content
|
||||
</button>
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
<!-- END: div filters_and_search -->
|
||||
|
||||
<div class="view_archvies_create_archive ae_group ae_row">
|
||||
{#if $slct.archive_id}
|
||||
<button
|
||||
on:click={ () => {
|
||||
|
||||
$slct.archive_id = null;
|
||||
$slct.archive_obj = {};
|
||||
|
||||
$ae_app.archives.show_main__options = true;
|
||||
$ae_app.archives.show_list__archive_obj_li = true;
|
||||
$ae_app.archives.show_view__archive_obj = false;
|
||||
$ae_app.archives.show_edit__archive_obj = false;
|
||||
// $ae_app.iframe_height_modal_body = 0;
|
||||
|
||||
const url = new URL(location);
|
||||
url.searchParams.delete('archive_id');
|
||||
history.pushState({}, '', url);
|
||||
|
||||
let message = {'archive_id': null};
|
||||
window.parent.postMessage(message, "*");
|
||||
}}
|
||||
class="btn_new_archive ae_btn btn btn-secondary"
|
||||
>
|
||||
<span class="fas fa-times"></span> View Other Archives
|
||||
</button>
|
||||
{/if}
|
||||
{#if $ae_app.trusted_access}
|
||||
<button
|
||||
on:click={() => {
|
||||
$slct.archive_id = null;
|
||||
$slct.archive_obj = {};
|
||||
|
||||
const url = new URL(location);
|
||||
url.searchParams.delete('archive_id');
|
||||
history.pushState({}, '', url);
|
||||
|
||||
$ae_app.archives.show_main__options = true;
|
||||
$ae_app.archives.show_list__archive_obj_li = false;
|
||||
$ae_app.archives.show_view__archive_obj = false;
|
||||
$ae_app.archives.show_edit__archive_obj = true;
|
||||
}}
|
||||
class="ae_btn ae_smallest btn_new_archive ae_btn btn btn-warning"
|
||||
>
|
||||
<span class="fas fa-plus"></span> Create new Archive
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
</section>
|
||||
{/if}
|
||||
|
||||
|
||||
{#if $ae_app.archives.show_list__archive_obj_li}
|
||||
<List_archive_obj
|
||||
on:created__archive_obj={handle_created_archive_obj}
|
||||
on:updated__archive_obj={handle_updated_archive_obj}
|
||||
on:deleted__archive_obj={handle_deleted_archive_obj}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
|
||||
{#if $ae_app.archives.show_view__archive_obj && $slct.archive_obj}
|
||||
<View_archive_obj />
|
||||
{/if}
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
{#if $ae_app.archives.show_edit__archive_obj}
|
||||
<Element_modal_v3
|
||||
show = { true }
|
||||
modal_cover_body = { false }
|
||||
report_client_dimensions = { true }
|
||||
on:close={ () => {
|
||||
$ae_app.archives.show_main__options = true;
|
||||
$ae_app.archives.show_list__archive_obj_li = true;
|
||||
$ae_app.archives.show_edit__archive_obj = false;
|
||||
$ae_app.archives.show_view__archive_obj = false;
|
||||
|
||||
const url = new URL(location);
|
||||
url.searchParams.delete('archive_id');
|
||||
history.pushState({}, '', url);
|
||||
|
||||
let message = {'archive_id': null};
|
||||
window.parent.postMessage(message, "*");
|
||||
}}
|
||||
on:report__modal_dimensions={ (event) => {
|
||||
console.log('*** on:report__modal_dimensions ***');
|
||||
console.log(event.detail);
|
||||
|
||||
$ae_app.modal_dimensions = event.detail.modal_dimensions;
|
||||
}}
|
||||
>
|
||||
<span slot="header_title">{@html ($slct.archive_obj.name ? $slct.archive_obj.name : 'New Archive Group')}</span>
|
||||
|
||||
<span slot="body">
|
||||
|
||||
<Edit_archive_obj
|
||||
on:created__archive_obj={handle_created_archive_obj}
|
||||
on:updated__archive_obj={handle_updated_archive_obj}
|
||||
on:deleted__archive_obj={handle_deleted_archive_obj}
|
||||
/>
|
||||
|
||||
</span>
|
||||
</Element_modal_v3>
|
||||
{/if}
|
||||
|
||||
|
||||
<!-- {#if $ae_app.archives.show_view__archive_obj && $slct.archive_obj}
|
||||
<Element_modal_v3
|
||||
show = { true }
|
||||
modal_cover_body = { true }
|
||||
report_modal_dimensions = { true }
|
||||
on:close={ () => {
|
||||
|
||||
$slct.archive_id = null;
|
||||
$slct.archive_obj = {};
|
||||
|
||||
$ae_app.archives.show_main__options = true;
|
||||
$ae_app.archives.show_list__archive_obj_li = true;
|
||||
$ae_app.archives.show_view__archive_obj = false;
|
||||
$ae_app.archives.show_edit__archive_obj = false;
|
||||
$ae_app.iframe_height_modal_body = 0;
|
||||
|
||||
const url = new URL(location);
|
||||
url.searchParams.delete('archive_id');
|
||||
history.pushState({}, '', url);
|
||||
|
||||
let message = {'archive_id': null};
|
||||
window.parent.postMessage(message, "*");
|
||||
}}
|
||||
on:report__modal_dimensions={ (event) => {
|
||||
console.log('*** on:report__modal_dimensions ***');
|
||||
console.log(event.detail);
|
||||
|
||||
$ae_app.modal_dimensions = event.detail.modal_dimensions;
|
||||
}}
|
||||
>
|
||||
<span slot="header_title">{@html $slct.archive_obj.name}</span>
|
||||
|
||||
<span slot="body">
|
||||
|
||||
<View_archive_obj />
|
||||
|
||||
</span>
|
||||
</Element_modal_v3>
|
||||
{/if} -->
|
||||
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
@@ -1,239 +0,0 @@
|
||||
<script lang="ts">
|
||||
type key_val = {
|
||||
[key: string]: any;
|
||||
};
|
||||
|
||||
|
||||
// *** Import Svelte core
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
// *** Import Aether core variables and functions
|
||||
import { ae, api, Element_modal_v3 } from 'aether_npm_lib';
|
||||
|
||||
import { slct, slct_trigger, ae_app, ae_session, ae_local } from './stores';
|
||||
|
||||
export let ae_obj_type: string = 'example';
|
||||
export let ae_obj_id: string = 'abc123';
|
||||
|
||||
|
||||
// let data_store_obj_get_promise: Promise<any>;
|
||||
let data_store_obj_get_promises: key_val = {};
|
||||
let get_ds_hub_site_header_promise = handle_get_data_store_obj_w_code({code: 'hub_site_header'});
|
||||
let get_ds_hub_site_footer_promise = handle_get_data_store_obj_w_code({code: 'hub_site_footer'});
|
||||
|
||||
handle_build_site_nav_menu();
|
||||
|
||||
onMount(() => {
|
||||
console.log('** Component Mounted: ** OSIT - AE Hub: Main');
|
||||
$ae_session.test.hub = 'Hello World!';
|
||||
$ae_session.test.general = 'Hello world from The Hub!';
|
||||
console.log('ae_session:', $ae_session);
|
||||
});
|
||||
|
||||
|
||||
async function handle_get_data_store_obj_w_code({code, data_type='text'}) {
|
||||
console.log('*** handle_get_data_store_obj_w_code() ***');
|
||||
|
||||
let get_item_result = window.localStorage.getItem(code);
|
||||
if (get_item_result) {
|
||||
$ae_app.hub.ds[code] = get_item_result;
|
||||
} else {
|
||||
console.log('Get local storage item miss.');
|
||||
}
|
||||
|
||||
data_store_obj_get_promises[code] = api.get_data_store_obj_w_code({
|
||||
api_cfg: $ae_app.ae_api,
|
||||
data_store_code: code,
|
||||
data_type: data_type,
|
||||
log_lvl: 0
|
||||
})
|
||||
.then(function (get_data_store_result) {
|
||||
if (get_data_store_result) {
|
||||
|
||||
if (data_type == 'text') {
|
||||
// console.log(get_data_store_result.text);
|
||||
$ae_app.hub.ds[code] = get_data_store_result.text;
|
||||
} else if (data_type == 'json') {
|
||||
// console.log(get_data_store_result.json);
|
||||
$ae_app.hub.ds[code] = get_data_store_result.json;
|
||||
}
|
||||
|
||||
// console.log(`Code: ${$ae_app.hub.ds[code]}`);
|
||||
// console.log(`Code:`, $ae_app.hub.ds[code]);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log('No results returned or failed.', error);
|
||||
});
|
||||
}
|
||||
|
||||
// In most cases we are just inserting HTML into the DOM. The Svelte module apps can update the ID's of the elements within if needed.
|
||||
$: if ($ae_app.hub.ds['hub_site_header']) {
|
||||
console.log('Hub Site Header:', $ae_app.hub.ds['hub_site_header']);
|
||||
const site_header_element = document.getElementById('Site-Header');
|
||||
if (site_header_element) {
|
||||
site_header_element.innerHTML = $ae_app.hub.ds['hub_site_header'];
|
||||
}
|
||||
}
|
||||
|
||||
$: if ($ae_app.hub.ds['hub_site_footer']) {
|
||||
console.log('Hub Site Footer:', $ae_app.hub.ds['hub_site_footer']);
|
||||
const site_footer_element = document.getElementById('Site-Footer');
|
||||
if (site_footer_element) {
|
||||
site_footer_element.innerHTML = $ae_app.hub.ds['hub_site_footer'];
|
||||
}
|
||||
}
|
||||
|
||||
// $: if ($ae_app.hub.ds['hub_site_nav_menu']) {
|
||||
// console.log('Hub Site Nav Menu:', $ae_app.hub.ds['hub_site_nav_menu']);
|
||||
// const site_menu_element = document.getElementById('Site-Nav-Menu');
|
||||
// if (site_menu_element) {
|
||||
// /* Add the HTML to the site_menu_element DOM element */
|
||||
// // site_menu_element.innerHTML = $ae_app.hub.ds['hub_site_nav_menu'];
|
||||
// }
|
||||
// }
|
||||
|
||||
$: if ($ae_app.hub.ds['hub_notifications']) {
|
||||
console.log('Hub Notifications:', $ae_app.hub.ds['hub_notifications']);
|
||||
const site_notifications_element = document.getElementById('Notifications');
|
||||
if (site_notifications_element) {
|
||||
site_notifications_element.innerHTML = $ae_app.hub.ds['hub_notifications'];
|
||||
}
|
||||
}
|
||||
|
||||
// if $ae_app.hub.ds['hub_site_header'] {
|
||||
// console.log('Hub Site Header:', $ae_app.hub.ds['hub_site_header']);
|
||||
// document.getElementById('Site-Header').innerHTML = $ae_app.hub.ds['hub_site_header'];
|
||||
// }
|
||||
|
||||
function handle_build_site_nav_menu() {
|
||||
$ae_session.site_nav_menu = {};
|
||||
|
||||
// let menu_item_tmp = {};
|
||||
|
||||
|
||||
// Navigation button group
|
||||
// $ae_session.site_nav_menu['options'] = []; // group
|
||||
|
||||
$ae_session.site_nav_menu['home'] = {
|
||||
'access_level': 'all',
|
||||
'state': 'active', // active, inactive, disabled
|
||||
'text': '<span class="fas fa-home"></span> Home',
|
||||
'href': '/',
|
||||
'action': 'navigate', // navigate, modal, action
|
||||
'class_li': ['ae_btn', 'btn_outline_primary']
|
||||
};
|
||||
|
||||
$ae_session.site_nav_menu['reports_exports'] = {
|
||||
'access_level': 'trusted',
|
||||
'state': 'active', // active, inactive, disabled
|
||||
'text': 'Reports & Exports',
|
||||
'href': '/',
|
||||
'action': 'navigate', // navigate, modal, action
|
||||
'class_li': ['ae_btn', 'btn_outline_secondary']
|
||||
};
|
||||
|
||||
$ae_session.site_nav_menu['manage'] = {
|
||||
'access_level': 'administrator',
|
||||
'state': 'active', // active, inactive, disabled
|
||||
'text': 'Manage',
|
||||
'href': '/manage',
|
||||
'action': 'navigate', // navigate, modal, action
|
||||
'class_li': ['ae_btn', 'btn_outline_secondary']
|
||||
};
|
||||
|
||||
$ae_session.site_nav_menu['help'] = {
|
||||
'access_level': 'all',
|
||||
'state': 'active', // active, inactive, disabled
|
||||
'text': 'Help',
|
||||
'href': '/',
|
||||
'class_li': ['ae_btn', 'btn_outline_secondary']
|
||||
};
|
||||
|
||||
|
||||
// // Trusted button group
|
||||
// $ae_session.site_nav_menu['trusted'] = []; // group
|
||||
|
||||
// menu_item_tmp = $event_defaults.event_manage_btn;
|
||||
// menu_item_tmp['href'] = `/event/${$slct.event_id}/manage`;
|
||||
// menu_item_tmp['class_li'].push('btn_sm', 'btn_outline_warning');
|
||||
// $ae_session.site_nav_menu['trusted'].push(menu_item_tmp);
|
||||
|
||||
// menu_item_tmp = $event_defaults.event_location_view_li_btn;
|
||||
// menu_item_tmp['href'] = `/event/${$slct.event_id}/locations`;
|
||||
// menu_item_tmp['class_li'].push('btn_sm', 'btn_outline_secondary');
|
||||
// $ae_session.site_nav_menu['trusted'].push(menu_item_tmp);
|
||||
|
||||
// // Admin button group
|
||||
// $ae_session.site_nav_menu['admin'] = []; // group
|
||||
|
||||
// menu_item_tmp = $event_defaults.event_edit_btn;
|
||||
// menu_item_tmp['href'] = `/event/${$slct.event_id}/edit`;
|
||||
// menu_item_tmp['class_li'].push('btn_sm', 'btn_outline_warning');
|
||||
// $ae_session.site_nav_menu['admin'].push(menu_item_tmp);
|
||||
}
|
||||
</script>
|
||||
|
||||
<section class="ae_hub ae_debug">
|
||||
|
||||
The Hub!
|
||||
<button
|
||||
on:click={() => {
|
||||
$ae_session.site_nav_menu['home'].text = '<span class="fas fa-house-damage"></span> Home';
|
||||
// console.log('ae_session:', $ae_session);
|
||||
|
||||
$ae_local.testing = 'Hello World!';
|
||||
$ae_local.test = 'Hello World!';
|
||||
// $ae_local.set('Hello World!');
|
||||
console.log('ae_local:', $ae_local);
|
||||
}}
|
||||
>
|
||||
<span class="fas fa-biohazard"></span> Test
|
||||
</button>
|
||||
|
||||
{#if $ae_app.administrator_access}
|
||||
<span class="access_type administrator_access">Administrator</span>
|
||||
{:else if $ae_app.trusted_access}
|
||||
<span class="access_type trusted_access">Trusted</span>
|
||||
{/if}
|
||||
|
||||
<div>
|
||||
<!-- {$ae_session.test.example} -->
|
||||
<!-- {$ae_session.test.general} -->
|
||||
<!-- {$ae_session.test.hub} -->
|
||||
<!-- {$ae_session.test.sponsorships} -->
|
||||
</div>
|
||||
|
||||
{#await data_store_obj_get_promises['hub_site_header']}
|
||||
<p>Loading site header...</p>
|
||||
{:then}
|
||||
<p>Site header loaded.</p>
|
||||
<!-- <div class="">{@html $ae_app.hub.ds['hub_site_header']}</div> -->
|
||||
<!-- <pre>
|
||||
{$ae_app.hub.ds['hub_site_header']}
|
||||
</pre> -->
|
||||
{:catch error}
|
||||
<p style="color: red">{error.message}</p>
|
||||
{/await}
|
||||
|
||||
{#await data_store_obj_get_promises['hub_site_footer']}
|
||||
<p>Loading site footer...</p>
|
||||
{:then}
|
||||
<p>Site footer loaded.</p>
|
||||
<!-- <div class="">{@html $ae_app.hub.ds['hub_site_footer']}</div> -->
|
||||
<!-- <pre>
|
||||
{$ae_app.hub.ds['hub_site_footer']}
|
||||
</pre> -->
|
||||
{:catch error}
|
||||
<p style="color: red">{error.message}</p>
|
||||
{/await}
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<style>
|
||||
|
||||
/* .ae_hub.ae_debug {
|
||||
|
||||
} */
|
||||
</style>
|
||||
@@ -1,711 +0,0 @@
|
||||
<script lang="ts">
|
||||
type key_val = {
|
||||
[key: string]: any;
|
||||
};
|
||||
// *** Import Svelte core
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
// *** Import Aether core variables and functions
|
||||
import { ae, api, Element_modal_v3 } from 'aether_npm_lib';
|
||||
|
||||
import { slct, slct_trigger, ae_app } from './stores';
|
||||
|
||||
// *** Import Aether core components
|
||||
|
||||
// *** Import Aether module variables and functions
|
||||
|
||||
// *** Import Aether module components
|
||||
import Edit_post_obj from './10_edit__post_obj.svelte';
|
||||
import View_post_obj from './10_view__post_obj.svelte';
|
||||
|
||||
// *** Export/Exposed variables and functions for component
|
||||
export let account_id: string = $ae_app.account_id;
|
||||
export let post_id: string = $ae_app.posts.post_id;
|
||||
|
||||
export let novi_uuid: string = $ae_app.novi_uuid;
|
||||
export let novi_email: string = $ae_app.novi_email;
|
||||
export let novi_full_name: string = $ae_app.novi_full_name;
|
||||
export let novi_admin_li: string = $ae_app.novi_admin_li;
|
||||
export let novi_trusted_li: string = $ae_app.novi_trusted_li;
|
||||
|
||||
// *** Set initial variables
|
||||
$ae_app.novi_uuid = novi_uuid;
|
||||
$ae_app.novi_email = decodeURIComponent(novi_email);
|
||||
$ae_app.novi_full_name = decodeURIComponent(novi_full_name);
|
||||
$ae_app.novi_admin_li = novi_admin_li;
|
||||
$ae_app.novi_trusted_li = novi_trusted_li;
|
||||
|
||||
$ae_app.posts.show_main__options = true;
|
||||
$ae_app.posts.show_list__post_obj_li = true;
|
||||
|
||||
// NOTE: Check if the novi_uuid is in the novi_admin_li list
|
||||
if ($ae_app.novi_uuid && $ae_app.novi_admin_li) {
|
||||
if ($ae_app.novi_admin_li.includes($ae_app.novi_uuid)) {
|
||||
$ae_app.access_type = 'administrator';
|
||||
$ae_app.administrator_access = true;
|
||||
$ae_app.trusted_access = true;
|
||||
}
|
||||
}
|
||||
// NOTE: Check if the novi_uuid is in the novi_trusted_li list
|
||||
if ($ae_app.novi_uuid && $ae_app.novi_trusted_li) {
|
||||
if ($ae_app.novi_trusted_li.includes($ae_app.novi_uuid)) {
|
||||
$ae_app.access_type = 'trusted';
|
||||
$ae_app.trusted_access = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($ae_app.administrator_access) {
|
||||
$ae_app.posts.enabled = 'enabled';
|
||||
$ae_app.posts.hidden = 'not_hidden';
|
||||
$ae_app.events.limit = 150;
|
||||
} else if ($ae_app.trusted_access) {
|
||||
$ae_app.posts.enabled = 'enabled';
|
||||
$ae_app.posts.hidden = 'not_hidden';
|
||||
$ae_app.events.limit = 75;
|
||||
} else {
|
||||
$ae_app.posts.enabled = 'enabled';
|
||||
$ae_app.posts.hidden = 'not_hidden';
|
||||
$ae_app.events.limit = 50;
|
||||
}
|
||||
|
||||
let idaa_post_obj_li_get_promise;
|
||||
let idaa_post_obj_get_promise;
|
||||
let idaa_post_comment_obj_li_get_promise;
|
||||
|
||||
if (account_id) {
|
||||
$slct.account_id = account_id;
|
||||
handle_load_idaa_post_obj_li({account_id: $slct.account_id, try_cache: false});
|
||||
}
|
||||
|
||||
// NOTE: This if post_id is not fully ready yet -2023-09-08
|
||||
if (post_id) {
|
||||
console.log(`Selected Post ID: ${post_id}`);
|
||||
$slct.post_id = post_id;
|
||||
$slct_trigger = 'load__post_obj';
|
||||
$slct_trigger = 'load__post_comment_obj_li';
|
||||
// handle_load_post_id_obj({post_id: $slct.post_id, try_cache: false});
|
||||
// handle_load_post_comment_obj_li({post_id: $slct.post_id, try_cache: false});
|
||||
|
||||
// Auto show the selected Post ID
|
||||
// Is this pushState needed here?
|
||||
// Set the URL param "post_id" to the current Post ID. This is a just in case.
|
||||
// const url = new URL(location);
|
||||
// url.searchParams.set('post_id', $slct.post_id);
|
||||
// history.pushState({}, '', url);
|
||||
|
||||
$ae_app.events.show_main__options = true;
|
||||
$ae_app.posts.show_list__post_obj_li = true;
|
||||
$ae_app.posts.show_edit__post_id = false;
|
||||
$ae_app.posts.show_view__post_id = true;
|
||||
}
|
||||
|
||||
if (!$ae_app.client_content) {
|
||||
$ae_app.client_content = {};
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
console.log('** Component Mounted: ** IDAA Bulletin Board - AE Posts: Main');
|
||||
});
|
||||
|
||||
|
||||
$: if ($ae_app.iframe_height && $ae_app.iframe_height_modal_body) {
|
||||
console.log('getting new dimensions for iframe:', $ae_app.iframe_height, $ae_app.iframe_height_modal_body);
|
||||
|
||||
let iframe_height = 0;
|
||||
|
||||
if ($ae_app.iframe_height > $ae_app.iframe_height_modal_body) {
|
||||
iframe_height = $ae_app.iframe_height;
|
||||
} else {
|
||||
iframe_height = $ae_app.iframe_height_modal_body;
|
||||
|
||||
// console.log($ae_app.modal_dimensions);
|
||||
|
||||
if ($ae_app.modal_dimensions && $ae_app.modal_dimensions.header_height) {
|
||||
iframe_height = iframe_height + $ae_app.modal_dimensions.header_height;
|
||||
}
|
||||
if ($ae_app.modal_dimensions && $ae_app.modal_dimensions.footer_height) {
|
||||
iframe_height = iframe_height + $ae_app.modal_dimensions.footer_height;
|
||||
}
|
||||
// iframe_height = iframe_height + 50; // Just in case
|
||||
}
|
||||
|
||||
console.log(`Suggested new iframe_height: ${iframe_height}`);
|
||||
window.parent.postMessage({'iframe_height': iframe_height}, "*"); // This should be in pixels
|
||||
} else if ($ae_app.iframe_height) {
|
||||
console.log('setting new iframe_height:', $ae_app.iframe_height);
|
||||
|
||||
// let iframe_height = $ae_app.iframe_height;
|
||||
|
||||
window.parent.postMessage({'iframe_height': $ae_app.iframe_height}, "*"); // This should be in pixels
|
||||
}
|
||||
|
||||
|
||||
$: if ($slct_trigger == 'load__post_obj_li' && $slct.account_id) {
|
||||
$slct_trigger = null;
|
||||
|
||||
handle_load_idaa_post_obj_li({account_id: $slct.account_id, try_cache: false});
|
||||
}
|
||||
|
||||
async function handle_load_idaa_post_obj_li({account_id, try_cache=false}) {
|
||||
console.log('*** handle_load_idaa_post_obj_li() ***');
|
||||
|
||||
let enabled = $ae_app.posts.enabled;
|
||||
let hidden = $ae_app.posts.hidden;
|
||||
let limit = $ae_app.posts.limit;
|
||||
let offset = $ae_app.posts.offset;
|
||||
|
||||
let params = {};
|
||||
|
||||
// params['json_str'] = encodeURIComponent(JSON.stringify($ae_app.posts));
|
||||
// let json_test_obj = {
|
||||
// 'default_qry_str': 'Testing',
|
||||
// 'address_default_qry_str': 'New York',
|
||||
// 'contact_1_default_qry_str': 'Scott',
|
||||
// };
|
||||
|
||||
// let json_test_obj = {
|
||||
// 'name': {'comp': 'LIKE', 'val': '%test%'},
|
||||
// 'priority': {'comp': '>=', 'val': 0},
|
||||
// 'created_on': {'comp': '>=', 'val': '2021-01-01 00:00:00'},
|
||||
// };
|
||||
|
||||
idaa_post_obj_li_get_promise = api.get_ae_obj_li_for_obj_id_crud({
|
||||
api_cfg: $ae_app.ae_api,
|
||||
obj_type: 'post', // Post in this case is a person's bulletin board post.
|
||||
for_obj_type: 'account',
|
||||
for_obj_id: account_id,
|
||||
enabled: enabled,
|
||||
hidden: hidden,
|
||||
order_by_li: {'priority': 'DESC', 'sort': 'DESC', 'created_on': 'DESC', 'updated_on': 'DESC'},
|
||||
limit: limit,
|
||||
offset: offset,
|
||||
params_json: null,
|
||||
params: params,
|
||||
log_lvl: 2
|
||||
})
|
||||
.then(function (post_obj_li_get_result) {
|
||||
if (post_obj_li_get_result) {
|
||||
$slct.post_obj_li = post_obj_li_get_result;
|
||||
console.log(`Post list:`, $slct.post_obj_li);
|
||||
} else {
|
||||
$slct.post_obj_li = [];
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log('No results returned or failed.', error);
|
||||
});
|
||||
|
||||
return idaa_post_obj_li_get_promise;
|
||||
}
|
||||
|
||||
|
||||
$: if ($slct_trigger == 'load__post_obj' && $slct.post_id) {
|
||||
$slct_trigger = null;
|
||||
|
||||
handle_load_post_id_obj({post_id: $slct.post_id, try_cache: false});
|
||||
|
||||
// // Auto show the selected Event ID
|
||||
// // Set the URL param "post_id" to the current Event ID. This is a just in case.
|
||||
// const url = new URL(location);
|
||||
// url.searchParams.set('post_id', $slct.post_id);
|
||||
// history.pushState({}, '', url);
|
||||
|
||||
// let message = {'post_id': $slct.post_id};
|
||||
// window.parent.postMessage(message, "*");
|
||||
|
||||
// $ae_app.posts.show_main__options = false;
|
||||
// $ae_app.posts.show_list__post_li = false;
|
||||
// $ae_app.posts.show_view__post_id = true;
|
||||
// $ae_app.posts.show_edit__post_id = false;
|
||||
}
|
||||
|
||||
async function handle_load_post_id_obj({post_id, try_cache=false}) {
|
||||
console.log('*** handle_load_post_id_obj() ***');
|
||||
|
||||
// let enabled = $ae_app.posts.enabled;
|
||||
// let hidden = $ae_app.posts.hidden;
|
||||
// let limit = $ae_app.posts.limit;
|
||||
// let offset = $ae_app.posts.offset;
|
||||
|
||||
let params = {};
|
||||
|
||||
idaa_post_obj_get_promise = api.get_ae_obj_id_crud({
|
||||
api_cfg: $ae_app.ae_api,
|
||||
obj_type: 'post',
|
||||
obj_id: post_id,
|
||||
params: params,
|
||||
log_lvl: 0
|
||||
})
|
||||
.then(function (post_obj_get_result) {
|
||||
if (post_obj_get_result) {
|
||||
$slct.post_obj = post_obj_get_result;
|
||||
console.log(`Post object:`, $slct.post_obj);
|
||||
}
|
||||
|
||||
// Auto show the selected Post ID
|
||||
// Set the URL param "post_id" to the current Post ID.
|
||||
const url = new URL(location);
|
||||
url.searchParams.set('post_id', $slct.post_id);
|
||||
history.pushState({}, '', url);
|
||||
|
||||
let message = {'post_id': $slct.post_id};
|
||||
window.parent.postMessage(message, "*");
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log('No results returned or failed.', error);
|
||||
});
|
||||
|
||||
return idaa_post_obj_get_promise;
|
||||
}
|
||||
|
||||
|
||||
$: if ($slct_trigger == 'load__post_comment_obj_li' && $slct.post_id) {
|
||||
$slct_trigger = null;
|
||||
|
||||
handle_load_post_comment_obj_li({post_id: $slct.post_id, try_cache: false});
|
||||
}
|
||||
|
||||
async function handle_load_post_comment_obj_li({post_id, try_cache=false}) {
|
||||
console.log('*** handle_load_post_comment_obj_li() ***');
|
||||
|
||||
let enabled = $ae_app.posts.enabled;
|
||||
let hidden = $ae_app.posts.hidden;
|
||||
let limit = $ae_app.posts.limit;
|
||||
let offset = $ae_app.posts.offset;
|
||||
|
||||
let params = {};
|
||||
|
||||
idaa_post_comment_obj_li_get_promise = api.get_ae_obj_li_for_obj_id_crud({
|
||||
api_cfg: $ae_app.ae_api,
|
||||
obj_type: 'post_comment', // Post comment in this case is a person's bulletin board post comment.
|
||||
for_obj_type: 'post',
|
||||
for_obj_id: post_id,
|
||||
enabled: enabled,
|
||||
hidden: hidden,
|
||||
order_by_li: {'priority': 'DESC', 'sort': 'DESC', 'created_on': 'DESC', 'updated_on': 'DESC'},
|
||||
limit: limit,
|
||||
offset: offset,
|
||||
params_json: null,
|
||||
params: params,
|
||||
log_lvl: 0
|
||||
})
|
||||
.then(function (post_comment_obj_li_get_result) {
|
||||
if (post_comment_obj_li_get_result) {
|
||||
$slct.post_comment_obj_li = post_comment_obj_li_get_result;
|
||||
console.log(`Post Comment list:`, $slct.post_comment_obj_li);
|
||||
} else {
|
||||
$slct.post_comment_obj_li = [];
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log('No results returned or failed.', error);
|
||||
});
|
||||
|
||||
return idaa_post_comment_obj_li_get_promise;
|
||||
}
|
||||
|
||||
function handle_post_obj_created(event) {
|
||||
console.log('*** handle_post_obj_created() ***');
|
||||
console.log(event.detail);
|
||||
|
||||
// $slct.post_id = event.detail.post_id_random;
|
||||
// $slct.post_obj = event.detail;
|
||||
|
||||
$slct_trigger = 'load__post_obj_li';
|
||||
|
||||
$ae_app.posts.show_list__post_obj_li = true;
|
||||
$ae_app.posts.show_edit__post_id = false;
|
||||
$ae_app.posts.show_view__post_id = false;
|
||||
}
|
||||
|
||||
function handle_post_obj_updated(event) {
|
||||
console.log('*** handle_post_obj_updated() ***');
|
||||
console.log(event.detail);
|
||||
|
||||
// $slct.post_id = event.detail.post_id_random;
|
||||
// $slct.post_obj = event.detail;
|
||||
|
||||
$slct_trigger = 'load__post_obj_li';
|
||||
|
||||
$ae_app.posts.show_list__post_obj_li = true;
|
||||
$ae_app.posts.show_edit__post_id = false;
|
||||
$ae_app.posts.show_view__post_id = false;
|
||||
}
|
||||
|
||||
function handle_post_obj_deleted(event) {
|
||||
console.log('*** handle_post_obj_deleted() ***');
|
||||
console.log(event.detail);
|
||||
|
||||
// $slct.post_id = null;
|
||||
// $slct.post_obj = {};
|
||||
|
||||
$slct_trigger = 'load__post_obj_li';
|
||||
|
||||
$ae_app.posts.show_list__post_obj_li = true;
|
||||
$ae_app.posts.show_edit__post_id = false;
|
||||
$ae_app.posts.show_view__post_id = false;
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<section id="osit_idaa_bb" class="osit_posts ae_main c_idaa c_idaa_bb" bind:clientHeight={$ae_app.iframe_height}>
|
||||
<!-- <header>
|
||||
<h1>IDAA BB Posts</h1>
|
||||
</header> -->
|
||||
|
||||
<section class="ae_section ae_meta">
|
||||
<p>
|
||||
Novi: {$ae_app.novi_full_name}
|
||||
<span class="details">
|
||||
(
|
||||
{$ae_app.novi_email}
|
||||
{#if $ae_app.administrator_access}
|
||||
<span class="access_type administrator_access">Administrator</span>
|
||||
{:else if $ae_app.trusted_access}
|
||||
<span class="access_type trusted_access">Trusted</span>
|
||||
{/if}
|
||||
<span class="novi_uuid">UUID: {$ae_app.novi_uuid}</span>
|
||||
)
|
||||
</span>
|
||||
</p>
|
||||
<!-- <p>Page height: {window.innerHeight}</p> -->
|
||||
</section>
|
||||
|
||||
{#if $ae_app.posts.show_main__options}
|
||||
<section class="ae_section ae_options ae_row post_obj__options">
|
||||
|
||||
{#if $ae_app.trusted_access && $ae_app.posts.hidden == 'not_hidden'}
|
||||
<button
|
||||
on:click={() => {
|
||||
$ae_app.posts.hidden = 'all';
|
||||
$slct_trigger = 'load__post_obj_li';
|
||||
}}
|
||||
class="ae_btn ae_smallest btn btn-info"
|
||||
>
|
||||
<span class="fas fa-eye"></span> Show Hidden Posts
|
||||
</button>
|
||||
{:else}
|
||||
<button
|
||||
on:click={() => {
|
||||
$ae_app.posts.hidden = 'not_hidden';
|
||||
$slct_trigger = 'load__post_obj_li';
|
||||
}}
|
||||
class="ae_btn ae_smallest btn btn-info"
|
||||
>
|
||||
<span class="fas fa-eye-slash"></span> Hide Hidden Posts
|
||||
</button>
|
||||
{/if}
|
||||
|
||||
{#if $ae_app.administrator_access}
|
||||
{#if $ae_app.posts.enabled == 'enabled'}
|
||||
<button
|
||||
on:click={() => {
|
||||
$ae_app.posts.hidden = 'all';
|
||||
$ae_app.posts.enabled = 'all';
|
||||
$ae_app.posts.limit = 500;
|
||||
$slct_trigger = 'load__post_obj_li';
|
||||
}}
|
||||
class="ae_btn btn_xs ae_smallest btn btn-xs btn-warning"
|
||||
>
|
||||
<span class="fas fa-eye"></span> Show Disabled Posts
|
||||
</button>
|
||||
{:else}
|
||||
<button
|
||||
on:click={() => {
|
||||
$ae_app.posts.enabled = 'enabled';
|
||||
$slct_trigger = 'load__post_obj_li';
|
||||
}}
|
||||
class="ae_btn btn_xs ae_smallest btn btn-xs btn-warning"
|
||||
>
|
||||
<span class="fas fa-eye-slash"></span> Hide Disabled Posts
|
||||
</button>
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
<button
|
||||
on:click={() => {
|
||||
$slct.post_id = null;
|
||||
$slct.post_obj = {};
|
||||
$slct.post_comment_obj_li = [];
|
||||
|
||||
const url = new URL(location);
|
||||
url.searchParams.delete('post_id');
|
||||
history.pushState({}, '', url);
|
||||
|
||||
$ae_app.posts.show_main__options = true;
|
||||
$ae_app.posts.show_list__post_obj_li = true;
|
||||
$ae_app.posts.show_edit__post_id = true;
|
||||
$ae_app.posts.show_view__post_id = false;
|
||||
}}
|
||||
class="btn_new_bb_post btn btn-secondary"
|
||||
>
|
||||
<span class="fas fa-plus"></span> Create new BB post
|
||||
</button>
|
||||
|
||||
</section>
|
||||
{/if}
|
||||
|
||||
{#if $ae_app.posts.show_list__post_obj_li}
|
||||
<section class="bb_post_list">
|
||||
{#if $slct.post_obj_li}
|
||||
<!-- <ul> -->
|
||||
{#each $slct.post_obj_li as idaa_post_obj, index}
|
||||
<div
|
||||
id={`idaa_bb_post_id__${idaa_post_obj.post_id_random}`}
|
||||
class="container bb_post post_obj"
|
||||
class:post__hide={idaa_post_obj.hide}
|
||||
class:post__priority={idaa_post_obj.priority}
|
||||
class:post__group={idaa_post_obj.group}
|
||||
>
|
||||
<header class="ae_header post__header">
|
||||
<h3 class="post__title">
|
||||
{@html idaa_post_obj.title}
|
||||
{#if idaa_post_obj.topic_id}<span class="badge badge-info bg-info"><span class="fas fa-user-md"></span> {idaa_post_obj.topic_name}</span>{/if}
|
||||
</h3>
|
||||
</header>
|
||||
|
||||
{#if idaa_post_obj.content}<div class="post__content">{@html idaa_post_obj.content}</div>{/if}
|
||||
|
||||
<div class="ae_options post_obj__options">
|
||||
<button
|
||||
on:click={() => {
|
||||
$slct.post_id = idaa_post_obj.post_id_random;
|
||||
$slct.post_obj = idaa_post_obj;
|
||||
|
||||
handle_load_post_comment_obj_li({post_id: $slct.post_id, try_cache: false});
|
||||
|
||||
const url = new URL(location);
|
||||
url.searchParams.set('post_id', idaa_post_obj.post_id_random);
|
||||
history.pushState({}, '', url);
|
||||
|
||||
let message = {'post_id': idaa_post_obj.post_id_random};
|
||||
window.parent.postMessage(message, "*");
|
||||
|
||||
$ae_app.posts.show_main__options = true;
|
||||
$ae_app.posts.show_list__post_obj_li = true;
|
||||
// $ae_app.posts.show_edit__post_id = false;
|
||||
$ae_app.posts.show_view__post_id = true;
|
||||
}}
|
||||
class="btn btn-primary"
|
||||
title={`View: ${idaa_post_obj.title}`}
|
||||
>
|
||||
<span class="fas fa-envelope-open"></span> Open
|
||||
|
||||
{#if idaa_post_obj.post_comment_count}
|
||||
<span class="ae_badge ae_info post__post_comment_count">
|
||||
<span class="fas fa-comment"></span> {(idaa_post_obj.post_comment_count == 1 ? `${idaa_post_obj.post_comment_count} comment` : `${idaa_post_obj.post_comment_count} comments` )}
|
||||
</span>
|
||||
{/if}
|
||||
</button>
|
||||
|
||||
{#if $ae_app.trusted_access || idaa_post_obj.external_person_id === $ae_app.novi_uuid || idaa_post_obj.email === $ae_app.novi_email}
|
||||
<button
|
||||
on:click={() => {
|
||||
$slct.post_id = idaa_post_obj.post_id_random;
|
||||
$slct.post_obj = idaa_post_obj;
|
||||
$slct_trigger = 'load__post_obj';
|
||||
|
||||
$ae_app.posts.show_main__options = true;
|
||||
$ae_app.posts.show_list__post_obj_li = true;
|
||||
$ae_app.posts.show_edit__post_id = true;
|
||||
// $ae_app.posts.show_view__post_id = false;
|
||||
}}
|
||||
class="ae_btn ae_smallest btn btn-secondary"
|
||||
title={`Edit post: ${idaa_post_obj.title}`}
|
||||
>
|
||||
<span class="fas fa-edit"></span> Edit Post
|
||||
</button>
|
||||
{/if}
|
||||
|
||||
<!-- <button
|
||||
on:click={() => {
|
||||
$slct.post_id = idaa_post_obj.post_id_random;
|
||||
$slct.post_obj = idaa_post_obj;
|
||||
|
||||
$ae_app.posts.show_post_comment_crud = true;
|
||||
}}
|
||||
class="ae_btn btn_md btn_outline_warning"
|
||||
title={`New comment on: ${idaa_post_obj.title}`}
|
||||
>
|
||||
<span class="fas fa-plus"></span> New Comment
|
||||
</button> -->
|
||||
|
||||
</div>
|
||||
|
||||
<div class="ae_section ae_footer ae_meta post__meta">
|
||||
{#if (idaa_post_obj.anonymous)}
|
||||
<div class="post__posted_by">
|
||||
Posted by: <span class="fas fa-user-secret"></span> <span class="post__full_name">Anonymous</span>
|
||||
</div>
|
||||
{:else if (idaa_post_obj.full_name)}
|
||||
<div class="post__posted_by">
|
||||
Posted by: <span class="fas fa-user"></span> <span class="post__full_name">{idaa_post_obj.full_name}
|
||||
{#if $ae_app.trusted_access && idaa_post_obj.email}
|
||||
(<a href="mailto:{idaa_post_obj.email}?subject=IDAA BB Post">{idaa_post_obj.email}</a>)
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if idaa_post_obj.created_on}
|
||||
<div class="post__created_on_updated_on">
|
||||
{#if !idaa_post_obj.updated_on}
|
||||
<span
|
||||
class="post__created_on"
|
||||
>
|
||||
<span class="ae_label">Created on:</span>
|
||||
<span class="ae_value">{ae.util.iso_datetime_formatter(idaa_post_obj.created_on, 'datetime_iso_no_seconds')}</span>
|
||||
</span>
|
||||
{:else}
|
||||
<span
|
||||
class="post__updated_on"
|
||||
>
|
||||
<span class="ae_label">Updated on:</span>
|
||||
<span class="ae_value">{ae.util.iso_datetime_formatter(idaa_post_obj.updated_on, 'datetime_iso_no_seconds')}</span>
|
||||
</span>
|
||||
{/if}
|
||||
{#if idaa_post_obj.archive_on}
|
||||
<span class="post__archive_on">Archive on: {ae.util.iso_datetime_formatter(idaa_post_obj.archive_on, 'datetime_iso_no_seconds')}</span>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
<!-- <div style="font-size: smaller">json={encodeURIComponent(JSON.stringify({idaa_post_obj}))}</div> -->
|
||||
</div>
|
||||
|
||||
</div>
|
||||
{/each}
|
||||
<!-- </ul> -->
|
||||
{:else}
|
||||
No posts found at this time
|
||||
{/if}
|
||||
</section>
|
||||
{/if}
|
||||
|
||||
|
||||
{#if $ae_app.posts.show_edit__post_id}
|
||||
<Element_modal_v3
|
||||
show = { true }
|
||||
modal_cover_body = { false }
|
||||
report_client_dimensions = { true }
|
||||
on:close={ () => {
|
||||
$ae_app.posts.show_main__options = true;
|
||||
$ae_app.posts.show_list__post_obj_li = true;
|
||||
$ae_app.posts.show_edit__post_id = false;
|
||||
// $ae_app.posts.show_view__post_id = false;
|
||||
|
||||
const url = new URL(location);
|
||||
url.searchParams.delete('post_id');
|
||||
history.pushState({}, '', url);
|
||||
|
||||
let message = {'post_id': null};
|
||||
window.parent.postMessage(message, "*");
|
||||
}}
|
||||
on:report__modal_dimensions={ (event) => {
|
||||
console.log('*** on:report__modal_dimensions ***');
|
||||
console.log(event.detail);
|
||||
|
||||
$ae_app.modal_dimensions = event.detail.modal_dimensions;
|
||||
}}
|
||||
>
|
||||
<span slot="header_title">{@html ($slct.post_obj.title ? $slct.post_obj.title : 'New BB Post')}</span>
|
||||
|
||||
<span slot="body">
|
||||
<section class="post_obj_view">
|
||||
<Edit_post_obj on:created__post_obj={handle_post_obj_created} on:updated__post_obj={handle_post_obj_updated} on:deleted__post_obj={handle_post_obj_deleted} />
|
||||
</section>
|
||||
</span>
|
||||
</Element_modal_v3>
|
||||
{/if}
|
||||
|
||||
|
||||
{#if $ae_app.posts.show_view__post_id && $slct.post_obj}
|
||||
<Element_modal_v3
|
||||
show = { true }
|
||||
modal_cover_body = { false }
|
||||
report_client_dimensions = { true }
|
||||
on:close={ () => {
|
||||
$slct.post_comment_id = null; // NOTE: Reset in case the post comment was being edited.
|
||||
$slct.post_comment_obj = {}; // NOTE: Reset in case the post comment was being edited.
|
||||
$slct.post_comment_obj_li = [];
|
||||
|
||||
$ae_app.posts.show_main__options = true;
|
||||
$ae_app.posts.show_list__post_obj_li = true;
|
||||
// $ae_app.posts.show_edit__post_id = false;
|
||||
$ae_app.posts.show_view__post_id = false;
|
||||
$ae_app.posts.show_edit__post_comment = false;
|
||||
|
||||
const url = new URL(location);
|
||||
url.searchParams.delete('post_id');
|
||||
history.pushState({}, '', url);
|
||||
|
||||
let message = {'post_id': null};
|
||||
window.parent.postMessage(message, "*");
|
||||
}}
|
||||
on:report__modal_dimensions={ (event) => {
|
||||
console.log('*** on:report__modal_dimensions ***');
|
||||
console.log(event.detail);
|
||||
|
||||
$ae_app.modal_dimensions = event.detail.modal_dimensions;
|
||||
}}
|
||||
>
|
||||
<span slot="header_title">{$slct.post_obj.title}</span>
|
||||
|
||||
<span slot="body">
|
||||
|
||||
<View_post_obj />
|
||||
|
||||
</span>
|
||||
</Element_modal_v3>
|
||||
{/if}
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<style>
|
||||
.ae_header h3 {
|
||||
font-size: 1.2em;
|
||||
margin: 0;
|
||||
/* padding: 0; */
|
||||
}
|
||||
|
||||
.post_obj .ae_meta {
|
||||
font-size: smaller;
|
||||
color: hsla(0,0%,50%,1);
|
||||
}
|
||||
|
||||
.post_obj {
|
||||
border: solid thin hsla(0,0%,90%,1);
|
||||
margin: 1em .5em;
|
||||
padding: .5em .5em;
|
||||
}
|
||||
|
||||
.post__header {
|
||||
background-color: hsla(0,0%,90%,1);
|
||||
}
|
||||
|
||||
/* .ae_meta.post_obj {
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
} */
|
||||
|
||||
/* :global(.bb_post_crud .element_ae_modal) {
|
||||
border: dashed thin hsla(0,0%,70%,1);
|
||||
|
||||
margin: .5em .25em;
|
||||
padding: .5em .25em;
|
||||
|
||||
background-color: hsla(0,0%,90%,1);
|
||||
} */
|
||||
|
||||
/* :global(.bb_post_id_view .element_ae_modal) {
|
||||
border: dashed thin blue;
|
||||
} */
|
||||
|
||||
/* :global(.bb_post_comment_crud .element_ae_modal) {
|
||||
border: dashed thin hsla(0,0%,70%,1);
|
||||
|
||||
margin: .5em .25em;
|
||||
padding: .5em .25em;
|
||||
|
||||
background-color: hsla(0,0%,90%,1);
|
||||
} */
|
||||
</style>
|
||||
@@ -1,847 +0,0 @@
|
||||
<script lang="ts">
|
||||
type key_val = {
|
||||
[key: string]: any;
|
||||
};
|
||||
// *** Import Svelte core
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
// *** Import Aether core variables and functions
|
||||
import { ae, api, Element_modal_v3 } from 'aether_npm_lib';
|
||||
|
||||
import { slct, slct_trigger, ae_app, ae_local, ae_session } from './stores';
|
||||
|
||||
// *** Import Aether core components
|
||||
// import { get_data_store_obj_w_code } from '../data_store/stores_data_store_api.js';
|
||||
|
||||
// *** Import Aether module variables and functions
|
||||
|
||||
// *** Import Aether module components
|
||||
import Edit_sponsorship_obj from './10_edit__sponsorship_obj.svelte';
|
||||
import List_sponsorship_obj from './10_list__sponsorship_obj.svelte';
|
||||
import View_sponsorship_obj from './10_view__sponsorship_obj.svelte';
|
||||
|
||||
// *** Export/Exposed variables and functions for component
|
||||
// export let account_id: string = $page['page_for']['account_id'];
|
||||
export let account_id: string = $ae_app.account_id;
|
||||
export let sponsorship_id: string = $ae_app.sponsorships.sponsorship_id;
|
||||
|
||||
export let user: string = $ae_app.user;
|
||||
export let key: string = $ae_app.key;
|
||||
export let full_name: string = $ae_app.full_name;
|
||||
export let ae_admin_li: string = $ae_app.ae_admin_li;
|
||||
export let ae_trusted_li: string = $ae_app.ae_trusted_li;
|
||||
|
||||
// *** Set initial variables
|
||||
$ae_app.user = decodeURIComponent(user);
|
||||
$ae_app.key = decodeURIComponent(key);
|
||||
// $ae_app.ae_admin_li = ae_admin_li;
|
||||
// $ae_app.ae_trusted_li = ae_trusted_li;
|
||||
|
||||
$ae_app.current_timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
||||
if (!$ae_app.lu_country_subdivision_list) {
|
||||
$ae_app.lu_country_subdivision_list = [];
|
||||
}
|
||||
if (!$ae_app.lu_country_list ) {
|
||||
$ae_app.lu_country_list = [];
|
||||
}
|
||||
if (!$ae_app.lu_timezone_list) {
|
||||
$ae_app.lu_timezone_list = [];
|
||||
}
|
||||
|
||||
$ae_app.sponsorships.show_main__options = true; // Section for: search area, buttons for filtering sponsorships, create new sponsorship.
|
||||
$ae_app.sponsorships.show_list__sponsorship_obj_li = true;
|
||||
$ae_app.sponsorships.fulltext_search_qry_str = '';
|
||||
$ae_app.sponsorships.qry_virtual = false;
|
||||
$ae_app.sponsorships.qry_physical = false;
|
||||
$ae_app.sponsorships.qry_type = '';
|
||||
|
||||
// NOTE: Check if the ae_user is in the ae_admin_li list
|
||||
if ($ae_app.ae_user && $ae_app.ae_admin_li) {
|
||||
if ($ae_app.ae_admin_li.includes($ae_app.ae_user)) {
|
||||
$ae_app.access_type = 'administrator';
|
||||
$ae_app.administrator_access = true;
|
||||
$ae_app.trusted_access = true;
|
||||
}
|
||||
}
|
||||
// NOTE: Check if the ae_user is in the ae_trusted_li list
|
||||
if ($ae_app.ae_user && $ae_app.ae_trusted_li) {
|
||||
if ($ae_app.ae_trusted_li.includes($ae_app.ae_user)) {
|
||||
$ae_app.access_type = 'trusted';
|
||||
$ae_app.trusted_access = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($ae_app.administrator_access) {
|
||||
$ae_app.sponsorships.enabled = 'enabled';
|
||||
$ae_app.sponsorships.hidden = 'not_hidden';
|
||||
$ae_app.sponsorships.limit = 150;
|
||||
} else if ($ae_app.trusted_access) {
|
||||
$ae_app.sponsorships.enabled = 'enabled';
|
||||
$ae_app.sponsorships.hidden = 'not_hidden';
|
||||
$ae_app.sponsorships.limit = 75;
|
||||
} else {
|
||||
$ae_app.sponsorships.enabled = 'enabled';
|
||||
$ae_app.sponsorships.hidden = 'not_hidden';
|
||||
$ae_app.sponsorships.limit = 25;
|
||||
}
|
||||
|
||||
let ae_sponsorship_obj_li_get_promise;
|
||||
let ae_sponsorship_obj_get_promise;
|
||||
let data_store_obj_get_promise;
|
||||
let get_ds_sponsorships_info_promise = handle_get_data_store_obj_w_code({code: 'sponsorships_info'});
|
||||
let get_ds_sponsorships_options_promise = handle_get_data_store_obj_w_code({code: 'sponsorships_options'});
|
||||
|
||||
if (account_id) {
|
||||
$slct.account_id = account_id;
|
||||
handle_load_ae_sponsorship_obj_li({account_id: $slct.account_id, try_cache: false});
|
||||
}
|
||||
|
||||
// NOTE: This if sponsorship_id is not fully ready yet -2023-09-08
|
||||
if (sponsorship_id) {
|
||||
console.log(`Selected Sponsorship ID: ${sponsorship_id}`);
|
||||
$slct.sponsorship_id = sponsorship_id;
|
||||
$slct_trigger = 'load__sponsorship_obj';
|
||||
|
||||
// handle_load_sponsorship_id_obj({sponsorship_id: $slct.sponsorship_id, try_cache: false});
|
||||
|
||||
// // Auto show the selected Sponsorship ID
|
||||
// // Set the URL param "sponsorship_id" to the current Sponsorship ID. This is a just in case.
|
||||
// const url = new URL(location);
|
||||
// url.searchParams.set('sponsorship_id', $slct.sponsorship_id);
|
||||
// history.pushState({}, '', url);
|
||||
|
||||
// let message = {'sponsorship_id': $slct.sponsorship_id};
|
||||
// window.parent.postMessage(message, "*");
|
||||
|
||||
$ae_app.sponsorships.show_main__options = true;
|
||||
$ae_app.sponsorships.show_list__sponsorship_obj_li = true;
|
||||
$ae_app.sponsorships.show_view__sponsorship_obj = true;
|
||||
$ae_app.sponsorships.show_edit__sponsorship_obj = false;
|
||||
}
|
||||
|
||||
if (!$ae_app.client_content) {
|
||||
$ae_app.client_content = {};
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
console.log('** Component Mounted: ** OSIT - AE Sponsorships: Main');
|
||||
|
||||
document.getElementById('meeting_fulltext_search_qry_str').focus();
|
||||
|
||||
$ae_session.test.sponsorships = 'Hello World!';
|
||||
$ae_session.test.general = 'Hello world from Sponsorships!';
|
||||
console.log('ae_session:', $ae_session);
|
||||
});
|
||||
|
||||
|
||||
$: if ($ae_app.iframe_height && $ae_app.iframe_height_modal_body) {
|
||||
console.log('getting new dimensions for iframe:', $ae_app.iframe_height, $ae_app.iframe_height_modal_body);
|
||||
|
||||
let iframe_height = 0;
|
||||
|
||||
if ($ae_app.iframe_height > $ae_app.iframe_height_modal_body) {
|
||||
iframe_height = $ae_app.iframe_height;
|
||||
} else {
|
||||
iframe_height = $ae_app.iframe_height_modal_body;
|
||||
|
||||
// console.log($ae_app.modal_dimensions);
|
||||
|
||||
if ($ae_app.modal_dimensions && $ae_app.modal_dimensions.header_height) {
|
||||
iframe_height = iframe_height + $ae_app.modal_dimensions.header_height;
|
||||
}
|
||||
if ($ae_app.modal_dimensions && $ae_app.modal_dimensions.footer_height) {
|
||||
iframe_height = iframe_height + $ae_app.modal_dimensions.footer_height;
|
||||
}
|
||||
// iframe_height = iframe_height + 50; // Just in case
|
||||
}
|
||||
|
||||
console.log(`Suggested new iframe_height: ${iframe_height}`);
|
||||
window.parent.postMessage({'iframe_height': iframe_height}, "*"); // This should be in pixels
|
||||
} else if ($ae_app.iframe_height) {
|
||||
console.log('setting new iframe_height:', $ae_app.iframe_height);
|
||||
|
||||
// let iframe_height = $ae_app.iframe_height;
|
||||
|
||||
window.parent.postMessage({'iframe_height': $ae_app.iframe_height}, "*"); // This should be in pixels
|
||||
}
|
||||
|
||||
|
||||
$: if ($slct_trigger == 'load__sponsorship_obj_li' && $slct.account_id) {
|
||||
if ($ae_app.sponsorships.qry_status == 'loading') {
|
||||
console.log('*** $ae_app.sponsorships.qry_status == loading ***');
|
||||
|
||||
setTimeout(() => {
|
||||
console.log("Delayed for X second.");
|
||||
$slct_trigger = null;
|
||||
handle_load_ae_sponsorship_obj_li({account_id: $slct.account_id, try_cache: false});
|
||||
}, 250);
|
||||
} else {
|
||||
console.log('*** $ae_app.sponsorships.qry_status != loading ***');
|
||||
$slct_trigger = null;
|
||||
handle_load_ae_sponsorship_obj_li({account_id: $slct.account_id, try_cache: false});
|
||||
}
|
||||
}
|
||||
|
||||
async function handle_load_ae_sponsorship_obj_li({account_id, try_cache=true}) {
|
||||
console.log('*** handle_load_ae_sponsorship_obj_li() ***');
|
||||
console.log($ae_app.sponsorships);
|
||||
|
||||
let fulltext_search_qry_str = $ae_app.sponsorships.fulltext_search_qry_str;
|
||||
let qry_virtual = $ae_app.sponsorships.qry_virtual;
|
||||
let qry_physical = $ae_app.sponsorships.qry_physical;
|
||||
let qry_type = $ae_app.sponsorships.qry_type;
|
||||
|
||||
let enabled = $ae_app.sponsorships.enabled;
|
||||
let hidden = $ae_app.sponsorships.hidden;
|
||||
let limit = $ae_app.sponsorships.limit;
|
||||
let offset = $ae_app.sponsorships.offset;
|
||||
|
||||
let params = {};
|
||||
// params['archived'] = 'all';
|
||||
// params['conference'] = false;
|
||||
// params['inc_address'] = true;
|
||||
// params['inc_contact'] = true;
|
||||
|
||||
let params_json: key_val = {};
|
||||
// if (fulltext_search_qry_str && fulltext_search_qry_str.length > 2) {
|
||||
// params_json['ft_qry'] = {
|
||||
// 'default_qry_str': fulltext_search_qry_str,
|
||||
// 'location_address_json': fulltext_search_qry_str,
|
||||
// 'contact_li_json': fulltext_search_qry_str,
|
||||
// 'address_default_qry_str': fulltext_search_qry_str, // NOTE: Remove after going live with OSIT ae?
|
||||
// 'contact_1_default_qry_str': fulltext_search_qry_str, // NOTE: Remove after going live with OSIT ae?
|
||||
// };
|
||||
// }
|
||||
|
||||
// if (qry_virtual || qry_physical || qry_type) {
|
||||
// params_json['and_qry'] = {};
|
||||
// if (qry_virtual) params_json['and_qry']['virtual'] = true;
|
||||
// if (qry_physical) params_json['and_qry']['physical'] = true;
|
||||
// if (qry_type) params_json['and_qry']['type'] = qry_type;
|
||||
// }
|
||||
|
||||
// console.log('params_json:', params_json);
|
||||
// console.log(params_json);
|
||||
|
||||
// NOTE: I am not sure if this is actually needed. It may save a little space in the URL.
|
||||
// if (JSON.stringify(params_json) == JSON.stringify({})) {
|
||||
// params_json = null;
|
||||
// }
|
||||
$ae_app.sponsorships.qry_status = 'loading';
|
||||
ae_sponsorship_obj_li_get_promise = api.get_ae_obj_li_for_obj_id_crud({
|
||||
api_cfg: $ae_app.ae_api,
|
||||
obj_type: 'sponsorship',
|
||||
for_obj_type: 'account',
|
||||
for_obj_id: account_id,
|
||||
use_alt_table: false, // NOTE: This will use the table_name_alt value instead of the table_name value in the API config.
|
||||
use_alt_base: false, // NOTE: This will use the base_name_alt value instead of the base_name value in the API config.
|
||||
enabled: enabled,
|
||||
hidden: hidden,
|
||||
order_by_li: {'priority': 'DESC', 'sort': 'DESC', 'updated_on': 'DESC', 'created_on': 'DESC'},
|
||||
// order_by_li: {'priority': 'DESC', 'sort': 'DESC', 'created_on': 'DESC', 'updated_on': 'DESC'},
|
||||
limit: limit,
|
||||
offset: offset,
|
||||
params_json: params_json,
|
||||
params: params,
|
||||
log_lvl: 2
|
||||
})
|
||||
|
||||
.then(function (sponsorship_obj_li_get_result) {
|
||||
if (sponsorship_obj_li_get_result) {
|
||||
$slct.sponsorship_obj_li = sponsorship_obj_li_get_result;
|
||||
console.log(`Sponsorship list:`, $slct.sponsorship_obj_li);
|
||||
} else {
|
||||
$slct.sponsorship_obj_li = [];
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log('No results returned or failed.', error);
|
||||
})
|
||||
.finally(function () {
|
||||
$ae_app.sponsorships.qry_status = 'done';
|
||||
});
|
||||
|
||||
return ae_sponsorship_obj_li_get_promise;
|
||||
}
|
||||
|
||||
|
||||
$: if ($slct_trigger == 'load__sponsorship_obj' && $slct.sponsorship_id) {
|
||||
$slct_trigger = null;
|
||||
|
||||
handle_load_sponsorship_id_obj({sponsorship_id: $slct.sponsorship_id, try_cache: false});
|
||||
|
||||
// Auto show the selected Sponsorship ID
|
||||
// Is this pushState needed here?
|
||||
// Set the URL param "sponsorship_id" to the current Sponsorship ID. This is a just in case.
|
||||
// const url = new URL(location);
|
||||
// url.searchParams.set('sponsorship_id', $slct.sponsorship_id);
|
||||
// history.pushState({}, '', url);
|
||||
|
||||
// Is this postMessage needed here?
|
||||
// let message = {'sponsorship_id': $slct.sponsorship_id};
|
||||
// window.parent.postMessage(message, "*");
|
||||
|
||||
// $ae_app.sponsorships.show_main__options = false;
|
||||
// $ae_app.sponsorships.show_list__sponsorship_obj_li = false;
|
||||
// $ae_app.sponsorships.show_view__sponsorship_obj = true;
|
||||
// $ae_app.sponsorships.show_edit__sponsorship_obj = false;
|
||||
}
|
||||
|
||||
async function handle_load_sponsorship_id_obj({sponsorship_id, try_cache=false}) {
|
||||
console.log('*** handle_load_sponsorship_id_obj() ***');
|
||||
|
||||
// let enabled = $ae_app.sponsorships.enabled;
|
||||
// let hidden = $ae_app.sponsorships.hidden;
|
||||
// let limit = $ae_app.sponsorships.limit;
|
||||
// let offset = $ae_app.sponsorships.offset;
|
||||
|
||||
let params = {};
|
||||
|
||||
ae_sponsorship_obj_get_promise = api.get_ae_obj_id_crud({
|
||||
api_cfg: $ae_app.ae_api,
|
||||
obj_type: 'event',
|
||||
obj_id: sponsorship_id,
|
||||
use_alt_table: true, // NOTE: This will use the table_name_alt value instead of the table_name value in the API config.
|
||||
use_alt_base: true, // NOTE: This will use the base_name_alt value instead of the base_name value in the API config.
|
||||
params: params,
|
||||
log_lvl: 0
|
||||
})
|
||||
.then(function (sponsorship_obj_get_result) {
|
||||
if (sponsorship_obj_get_result) {
|
||||
$slct.sponsorship_obj = sponsorship_obj_get_result;
|
||||
console.log(`Sponsorship object:`, $slct.sponsorship_obj);
|
||||
}
|
||||
|
||||
// Auto show the selected Sponsorship ID
|
||||
// Is this pushState needed here?
|
||||
// Set the URL param "sponsorship_id" to the current Sponsorship ID.
|
||||
const url = new URL(location);
|
||||
url.searchParams.set('sponsorship_id', $slct.sponsorship_id);
|
||||
history.pushState({}, '', url);
|
||||
|
||||
// Is this postMessage needed here?
|
||||
let message = {'sponsorship_id': $slct.sponsorship_id};
|
||||
window.parent.postMessage(message, "*");
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log('No results returned or failed.', error);
|
||||
});
|
||||
|
||||
return ae_sponsorship_obj_get_promise;
|
||||
}
|
||||
|
||||
function handle_created_sponsorship_obj(event) {
|
||||
console.log('*** handle_created_sponsorship_obj() ***');
|
||||
console.log(event.detail);
|
||||
|
||||
handle_load_sponsorship_id_obj({sponsorship_id: $slct.sponsorship_id, try_cache: false});
|
||||
|
||||
const url = new URL(location);
|
||||
url.searchParams.set('sponsorship_id', $slct.sponsorship_id);
|
||||
history.pushState({}, '', url);
|
||||
|
||||
let message = {'sponsorship_id': $slct.sponsorship_id};
|
||||
window.parent.postMessage(message, "*");
|
||||
|
||||
// $slct_trigger = 'load__sponsorship_obj';
|
||||
$slct_trigger = 'load__sponsorship_obj_li';
|
||||
|
||||
$ae_app.sponsorships.show_main__options = false;
|
||||
$ae_app.sponsorships.show_list__sponsorship_obj_li = false;
|
||||
$ae_app.sponsorships.show_view__sponsorship_obj = true;
|
||||
$ae_app.sponsorships.show_edit__sponsorship_obj = false;
|
||||
}
|
||||
|
||||
function handle_updated_sponsorship_obj(event) {
|
||||
console.log('*** handle_updated_sponsorship_obj() ***');
|
||||
console.log(event.detail);
|
||||
|
||||
// $slct_trigger = 'load__sponsorship_obj';
|
||||
$slct_trigger = 'load__sponsorship_obj_li';
|
||||
|
||||
$ae_app.sponsorships.show_main__options = false;
|
||||
$ae_app.sponsorships.show_list__sponsorship_obj_li = false;
|
||||
$ae_app.sponsorships.show_view__sponsorship_obj = true;
|
||||
$ae_app.sponsorships.show_edit__sponsorship_obj = false;
|
||||
}
|
||||
|
||||
function handle_deleted_sponsorship_obj(event) {
|
||||
console.log('*** handle_deleted_sponsorship_obj() ***');
|
||||
console.log(event.detail);
|
||||
|
||||
const url = new URL(location);
|
||||
url.searchParams.delete('sponsorship_id');
|
||||
history.pushState({}, '', url);
|
||||
|
||||
let message = {'sponsorship_id': null};
|
||||
window.parent.postMessage(message, "*");
|
||||
|
||||
$slct_trigger = 'load__sponsorship_obj_li';
|
||||
|
||||
$ae_app.sponsorships.show_main__options = true;
|
||||
$ae_app.sponsorships.show_list__sponsorship_obj_li = true;
|
||||
$ae_app.sponsorships.show_view__sponsorship_obj = false;
|
||||
$ae_app.sponsorships.show_edit__sponsorship_obj = false;
|
||||
}
|
||||
|
||||
|
||||
function handle_submit_form(event) {
|
||||
console.log('*** handle_submit_form() ***');
|
||||
console.log(event);
|
||||
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
return false;
|
||||
}
|
||||
function handle_cancel_form(event) {
|
||||
console.log('*** handle_cancel_form() ***');
|
||||
console.log(event);
|
||||
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function handle_oninput_fulltext_search_qry_str(event) {
|
||||
console.log('*** handle_oninput_fulltext_search_qry_str() ***');
|
||||
console.log(event);
|
||||
|
||||
// Check if this variable is a promise. The last query may still be being processed.
|
||||
// if (!ae_sponsorship_obj_li_get_promise.promise) {
|
||||
// console.log('*** handle_oninput_fulltext_search_qry_str() ***');
|
||||
// console.log('*** Promise is still processing. ***');
|
||||
// console.log(ae_sponsorship_obj_li_get_promise);
|
||||
// ae_sponsorship_obj_li_get_promise.promise.finally(() => { ae_sponsorship_obj_li_get_promise.promise.done = true; });
|
||||
// } else {
|
||||
// $slct_trigger = 'load__sponsorship_obj_li';
|
||||
// }
|
||||
// if (ae_sponsorship_obj_li_get_promise && ae_sponsorship_obj_li_get_promise.then) {
|
||||
// console.log('*** handle_oninput_fulltext_search_qry_str() ***');
|
||||
// console.log('*** Promise is still processing. ***');
|
||||
// console.log(ae_sponsorship_obj_li_get_promise);
|
||||
// $slct_trigger = 'load__sponsorship_obj_li';
|
||||
// return;
|
||||
// }
|
||||
|
||||
// fulltext_search_qry_str = event.target.value;
|
||||
|
||||
// if ($ae_app.sponsorships.fulltext_search_qry_str.length > 2) {
|
||||
// } else {
|
||||
// $ae_app.sponsorships.fulltext_search_qry_str = '';
|
||||
// }
|
||||
$slct_trigger = 'load__sponsorship_obj_li';
|
||||
}
|
||||
|
||||
async function handle_get_data_store_obj_w_code({code, data_type='text'}) {
|
||||
console.log('*** handle_get_data_store_obj_w_code() ***');
|
||||
|
||||
let get_item_result = window.localStorage.getItem(code);
|
||||
if (get_item_result) {
|
||||
$ae_app.sponsorships.ds[code] = get_item_result;
|
||||
} else {
|
||||
console.log('Get local storage item miss.');
|
||||
}
|
||||
|
||||
data_store_obj_get_promise = api.get_data_store_obj_w_code({
|
||||
api_cfg: $ae_app.ae_api,
|
||||
data_store_code: code,
|
||||
data_type: data_type,
|
||||
log_lvl: 1
|
||||
})
|
||||
.then(function (get_data_store_result) {
|
||||
if (get_data_store_result) {
|
||||
|
||||
if (data_type == 'text') {
|
||||
// console.log(get_data_store_result.text);
|
||||
$ae_app.sponsorships.ds[code] = get_data_store_result.text;
|
||||
} else if (data_type == 'json') {
|
||||
// console.log(get_data_store_result.json);
|
||||
$ae_app.sponsorships.ds[code] = get_data_store_result.json;
|
||||
}
|
||||
|
||||
// console.log(`Code: ${$ae_app.sponsorships.ds[code]}`);
|
||||
// console.log(`Code:`, $ae_app.sponsorships.ds[code]);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log('No results returned or failed.', error);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- <svelte:window
|
||||
bind:outerHeight={ae_iframe_height}
|
||||
/> -->
|
||||
|
||||
|
||||
<section id="osit_ae_sponsorships" class="osit_sponsorships ae_main c_ae c_ae_sponsorships ae_main" bind:clientHeight={$ae_app.iframe_height}>
|
||||
<header>
|
||||
<h1>Sponsorships for One Sky IT Demo</h1>
|
||||
</header>
|
||||
|
||||
<section class="ae_section ae_meta">
|
||||
<p>
|
||||
ae: {($ae_app.ae_full_name ? $ae_app.ae_full_name : 'Name not set')}
|
||||
<span class="details">
|
||||
(
|
||||
{($ae_app.ae_email ? $ae_app.ae_email : 'Email not set')}
|
||||
{#if $ae_app.administrator_access}
|
||||
<span class="access_type administrator_access">Administrator</span>
|
||||
{:else if $ae_app.trusted_access}
|
||||
<span class="access_type trusted_access">Trusted</span>
|
||||
{/if}
|
||||
<span class="ae_user">{$ae_app.ae_user ? $ae_app.ae_user : 'User not set'}</span>
|
||||
)
|
||||
</span>
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<div class="ae_overview">
|
||||
<div class="ae_info ds__sponsorships_info ">
|
||||
{@html $ae_app.sponsorships.ds.sponsorships_info}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{#if $ae_app.sponsorships.show_main__options}
|
||||
<section class="ae_section ae_options ae_column sponsorship_obj__options">
|
||||
<div class="ae_note ds__sponsorships_options ">
|
||||
{@html $ae_app.sponsorships.ds.sponsorships_options}
|
||||
</div>
|
||||
|
||||
<div class="filters_and_search">
|
||||
|
||||
|
||||
|
||||
<form on:submit|preventDefault={handle_submit_form} on:keydown={e => e.key === 'Escape' && handle_cancel_form} class="search_form">
|
||||
<div class="ae_group">
|
||||
<input
|
||||
type="search"
|
||||
placeholder="Search (name, description, etc.)"
|
||||
id="meeting_fulltext_search_qry_str"
|
||||
name="fulltext_search_qry_str"
|
||||
bind:value={$ae_app.sponsorships.fulltext_search_qry_str}
|
||||
style="width: 50%;"
|
||||
class="bs-input"
|
||||
>
|
||||
<button
|
||||
on:click={handle_oninput_fulltext_search_qry_str}
|
||||
>
|
||||
<span class="fas fa-search"></span> Search
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<fieldset>
|
||||
<legend>Filter on?</legend>
|
||||
<div class="ae_row ae_flex_justify_around ae_width_md">
|
||||
<label>Paid
|
||||
<input
|
||||
name="qry_paid"
|
||||
type="checkbox"
|
||||
bind:checked={$ae_app.sponsorships.qry_paid}
|
||||
on:change={() => {$slct_trigger = 'load__sponsorship_obj_li';}}
|
||||
>
|
||||
</label>
|
||||
<label>Guests
|
||||
<input
|
||||
name="qry_guest_li"
|
||||
type="checkbox"
|
||||
bind:checked={$ae_app.sponsorships.qry_guest_li}
|
||||
on:change={() => {$slct_trigger = 'load__sponsorship_obj_li';}}
|
||||
>
|
||||
</label>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
<legend>Select level?</legend>
|
||||
<div class="ae_row ae_flex_justify_around ae_width_100">
|
||||
<label>All
|
||||
<input
|
||||
name="qry_type"
|
||||
type="radio"
|
||||
value=""
|
||||
bind:group={$ae_app.sponsorships.qry_type}
|
||||
on:change={() => {$slct_trigger = 'load__sponsorship_obj_li';}}
|
||||
title="Show all meeting types"
|
||||
>
|
||||
</label>
|
||||
<label>Friend ($5,000)
|
||||
<input
|
||||
name="qry_type"
|
||||
type="radio"
|
||||
value="Friend"
|
||||
bind:group={$ae_app.sponsorships.qry_type}
|
||||
on:change={() => {$slct_trigger = 'load__sponsorship_obj_li';}}
|
||||
title="Friend ($5,000)"
|
||||
>
|
||||
</label>
|
||||
<label>Supporter ($7,500)
|
||||
<input
|
||||
name="qry_type"
|
||||
type="radio"
|
||||
value="Supporter"
|
||||
bind:group={$ae_app.sponsorships.qry_type}
|
||||
on:change={() => {$slct_trigger = 'load__sponsorship_obj_li';}}
|
||||
title="Supporter ($7,500)"
|
||||
>
|
||||
</label>
|
||||
<label>Champion ($12,500)
|
||||
<input
|
||||
name="qry_type"
|
||||
type="radio"
|
||||
value="Champion"
|
||||
bind:group={$ae_app.sponsorships.qry_type}
|
||||
on:change={() => {$slct_trigger = 'load__sponsorship_obj_li';}}
|
||||
title="Champion ($12,500)"
|
||||
>
|
||||
</label>
|
||||
<label>Advocate ($20,000)
|
||||
<input
|
||||
name="qry_type"
|
||||
type="radio"
|
||||
value="Advocate"
|
||||
bind:group={$ae_app.sponsorships.qry_type}
|
||||
on:change={() => {$slct_trigger = 'load__sponsorship_obj_li';}}
|
||||
title="Advocate ($20,000)"
|
||||
>
|
||||
</label>
|
||||
<label>Presenting Partner ($30,000)
|
||||
<input
|
||||
name="qry_type"
|
||||
type="radio"
|
||||
value="Presenting Partner"
|
||||
bind:group={$ae_app.sponsorships.qry_type}
|
||||
on:change={() => {$slct_trigger = 'load__sponsorship_obj_li';}}
|
||||
title="Presenting Partner ($30,000)"
|
||||
>
|
||||
</label>
|
||||
<label>Signature Partner ($50,000)
|
||||
<input
|
||||
name="qry_type"
|
||||
type="radio"
|
||||
value="Signature Partner"
|
||||
bind:group={$ae_app.sponsorships.qry_type}
|
||||
on:change={() => {$slct_trigger = 'load__sponsorship_obj_li';}}
|
||||
title="Signature Partner ($50,000)"
|
||||
>
|
||||
</label>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
</form>
|
||||
|
||||
{#await ae_sponsorship_obj_li_get_promise}
|
||||
<div><span class="fas fa-spinner"></span>
|
||||
Loading sponsorships...</div>
|
||||
{:then ae_sponsorship_obj_li_get_result}
|
||||
<!-- <p>Sponsorship list: {ae_sponsorship_obj_li_get_result}</p> -->
|
||||
{:catch error}
|
||||
<div>Error: {error.message}</div>
|
||||
{/await}
|
||||
|
||||
<div class="ae_group ae_row">
|
||||
|
||||
{#if $ae_app.trusted_access && $ae_app.sponsorships.hidden == 'not_hidden'}
|
||||
<button
|
||||
on:click={() => {
|
||||
$ae_app.sponsorships.hidden = 'all';
|
||||
$ae_app.sponsorships.limit = 150;
|
||||
$slct_trigger = 'load__sponsorship_obj_li';
|
||||
}}
|
||||
class="btn_show_bb_post ae_btn btn btn-info"
|
||||
>
|
||||
<span class="fas fa-eye"></span> Show Hidden Sponsorships
|
||||
</button>
|
||||
{:else if $ae_app.trusted_access && $ae_app.sponsorships.hidden == 'all'}
|
||||
<button
|
||||
on:click={() => {
|
||||
$ae_app.sponsorships.hidden = 'not_hidden';
|
||||
$slct_trigger = 'load__sponsorship_obj_li';
|
||||
}}
|
||||
class="btn_hide_bb_post ae_btn btn btn-info"
|
||||
>
|
||||
<span class="fas fa-eye-slash"></span> Hide Hidden Sponsorships
|
||||
</button>
|
||||
{/if}
|
||||
|
||||
{#if $ae_app.administrator_access && $ae_app.sponsorships.enabled == 'enabled'}
|
||||
<button
|
||||
on:click={() => {
|
||||
$ae_app.sponsorships.hidden = 'all';
|
||||
$ae_app.sponsorships.enabled = 'all';
|
||||
$ae_app.sponsorships.limit = 500;
|
||||
$slct_trigger = 'load__sponsorship_obj_li';
|
||||
}}
|
||||
class="btn_show_bb_post ae_btn btn btn-warning"
|
||||
>
|
||||
<span class="fas fa-eye"></span> Show Disabled Sponsorships
|
||||
</button>
|
||||
{:else if $ae_app.administrator_access && $ae_app.sponsorships.enabled == 'all'}
|
||||
<button
|
||||
on:click={() => {
|
||||
$ae_app.sponsorships.enabled = 'enabled';
|
||||
$slct_trigger = 'load__sponsorship_obj_li';
|
||||
}}
|
||||
class="btn_hide_bb_post ae_btn btn btn-warning"
|
||||
>
|
||||
<span class="fas fa-eye-slash"></span> Hide Disabled Sponsorships
|
||||
</button>
|
||||
{/if}
|
||||
|
||||
<button
|
||||
on:click={() => {
|
||||
$slct.sponsorship_id = null;
|
||||
$slct.sponsorship_obj = {};
|
||||
|
||||
const url = new URL(location);
|
||||
url.searchParams.delete('sponsorship_id');
|
||||
history.pushState({}, '', url);
|
||||
|
||||
$ae_app.sponsorships.show_main__options = false;
|
||||
$ae_app.sponsorships.show_list__sponsorship_obj_li = false;
|
||||
$ae_app.sponsorships.show_view__sponsorship_obj = false;
|
||||
$ae_app.sponsorships.show_edit__sponsorship_obj = true;
|
||||
|
||||
$ae_session.test.sponsorships = 'Hello World! Create new Sponsorship was clicked!';
|
||||
$ae_session.test_xyz.sponsorships = 'Hello World! Create new Sponsorship was clicked!';
|
||||
}}
|
||||
class="btn_new_recovery_meeting ae_btn btn btn-secondary"
|
||||
>
|
||||
<span class="fas fa-plus"></span> Create new Sponsorship
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</div> <!-- END: div filters_and_search -->
|
||||
|
||||
</section>
|
||||
{/if}
|
||||
|
||||
|
||||
{#if $slct.sponsorship_obj_li && $ae_app.sponsorships.show_list__sponsorship_obj_li}
|
||||
<List_sponsorship_obj />
|
||||
{/if}
|
||||
|
||||
|
||||
{#if $ae_app.sponsorships.show_edit__sponsorship_obj}
|
||||
<!-- <section class="ae_edit sponsorship_obj sponsorship_id ae_sponsorship_id_edit"> -->
|
||||
<Element_modal_v3
|
||||
show = { true }
|
||||
modal_cover_body = { false }
|
||||
report_client_dimensions = { true }
|
||||
on:close={ () => {
|
||||
$ae_app.sponsorships.show_main__options = true;
|
||||
$ae_app.sponsorships.show_list__sponsorship_obj_li = true;
|
||||
$ae_app.sponsorships.show_edit__sponsorship_obj = false;
|
||||
$ae_app.sponsorships.show_view__sponsorship_obj = false;
|
||||
|
||||
const url = new URL(location);
|
||||
url.searchParams.delete('sponsorship_id');
|
||||
history.pushState({}, '', url);
|
||||
|
||||
let message = {'sponsorship_id': null};
|
||||
window.parent.postMessage(message, "*");
|
||||
}}
|
||||
on:report__modal_dimensions={ (event) => {
|
||||
console.log('*** on:report__modal_dimensions ***');
|
||||
console.log(event.detail);
|
||||
|
||||
$ae_app.modal_dimensions = event.detail.modal_dimensions;
|
||||
}}
|
||||
>
|
||||
<span slot="header_title">{@html ($slct.sponsorship_obj.name ? $slct.sponsorship_obj.name : 'New Sponsorship')}</span>
|
||||
|
||||
<span slot="body">
|
||||
|
||||
<Edit_sponsorship_obj
|
||||
on:created__meeting_obj={handle_created_sponsorship_obj}
|
||||
on:updated__meeting_obj={handle_updated_sponsorship_obj}
|
||||
on:deleted__meeting_obj={handle_deleted_sponsorship_obj}
|
||||
/>
|
||||
|
||||
</span>
|
||||
</Element_modal_v3>
|
||||
<!-- </section> -->
|
||||
{/if}
|
||||
|
||||
|
||||
{#if $ae_app.sponsorships.show_view__sponsorship_obj && $slct.sponsorship_obj}
|
||||
<!-- <section class="ae_view sponsorship_obj sponsorship_id ae_sponsorship_id_view"> -->
|
||||
<Element_modal_v3
|
||||
show = { true }
|
||||
modal_cover_body = { false }
|
||||
report_client_dimensions = { true }
|
||||
on:close={ () => {
|
||||
$slct.sponsorship_id = null;
|
||||
$slct.sponsorship_obj = {};
|
||||
|
||||
$ae_app.sponsorships.show_main__options = true;
|
||||
$ae_app.sponsorships.show_list__sponsorship_obj_li = true;
|
||||
$ae_app.sponsorships.show_view__sponsorship_obj = false;
|
||||
$ae_app.sponsorships.show_edit__sponsorship_obj = false;
|
||||
|
||||
const url = new URL(location);
|
||||
url.searchParams.delete('sponsorship_id');
|
||||
history.pushState({}, '', url);
|
||||
|
||||
let message = {'sponsorship_id': null};
|
||||
window.parent.postMessage(message, "*");
|
||||
}}
|
||||
on:report__modal_dimensions={ (event) => {
|
||||
console.log('*** on:report__modal_dimensions ***');
|
||||
console.log(event.detail);
|
||||
|
||||
$ae_app.modal_dimensions = event.detail.modal_dimensions;
|
||||
}}
|
||||
>
|
||||
<span slot="header_title">{@html $slct.sponsorship_obj.name}</span>
|
||||
|
||||
<span slot="body">
|
||||
|
||||
<View_sponsorship_obj />
|
||||
|
||||
</span>
|
||||
</Element_modal_v3>
|
||||
<!-- </section> -->
|
||||
{/if}
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<style>
|
||||
|
||||
|
||||
/* .ae_meta {
|
||||
font-size: smaller;
|
||||
color: hsla(0,0%,50%,1);
|
||||
} */
|
||||
|
||||
/* .ae_edit.sponsorship_obj {
|
||||
border: dashed thin hsla(0,0%,70%,1);
|
||||
|
||||
margin: .5em .25em;
|
||||
padding: .5em .25em;
|
||||
|
||||
background-color: hsla(0,0%,90%,1);
|
||||
} */
|
||||
|
||||
/* .ae_view.sponsorship_obj {
|
||||
border: dashed thin hsla(0,0%,70%,1);
|
||||
|
||||
margin: .5em .25em;
|
||||
padding: .5em .25em;
|
||||
|
||||
background-color: hsla(0,0%,90%,1);
|
||||
} */
|
||||
|
||||
/* :global(.ae_edit.sponsorship_id .element_ae_modal) {
|
||||
border: dashed thin hsla(0,0%,70%,1);
|
||||
|
||||
margin: .5em .25em;
|
||||
padding: .5em .25em;
|
||||
|
||||
background-color: hsla(0,0%,90%,1);
|
||||
} */
|
||||
|
||||
</style>
|
||||
@@ -1,706 +0,0 @@
|
||||
<script lang="ts">
|
||||
import { createEventDispatcher, onDestroy, onMount } from 'svelte';
|
||||
import { fade } from 'svelte/transition';
|
||||
|
||||
import { ae, api, Element_input, Element_input_file_hashing } from 'aether_npm_lib';
|
||||
import { slct, ae_app } from './stores';
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
type key_val = {
|
||||
[key: string]: any;
|
||||
};
|
||||
|
||||
$ae_app.archives.input_file_list = []
|
||||
|
||||
let create_archive_content_obj_promise: any;
|
||||
let delete_archive_content_obj_promise: any;
|
||||
let update_archive_content_obj_promise: any;
|
||||
let upload__hosted_file_obj_promise: any;
|
||||
|
||||
let disable_submit_btn = true;
|
||||
|
||||
if ($slct.archive_content_id) {
|
||||
console.log(`Archive Content ID selected: ${$slct.archive_content_id}`);
|
||||
console.log(`Archive Content Object selected: ${$slct.archive_content_obj}`)
|
||||
} else {
|
||||
$slct.archive_content_id = null;
|
||||
$slct.archive_content_obj = {
|
||||
archive_id_random: null,
|
||||
// archive_content_id_random: null,
|
||||
archive_content_type: null,
|
||||
name: null,
|
||||
description: null,
|
||||
content_html: null,
|
||||
// hosted_file_id_random: null,
|
||||
file_path: null,
|
||||
filename: null,
|
||||
file_extension: null,
|
||||
original_datetime: null,
|
||||
original_timezone: null,
|
||||
original_location: null,
|
||||
original_url: null,
|
||||
original_url_text: null,
|
||||
access_key: null, // or passcode?
|
||||
|
||||
enable: true,
|
||||
hide: false,
|
||||
priority: null,
|
||||
sort: null,
|
||||
notes: null,
|
||||
};
|
||||
console.log(`Archive Content Object started: ${$slct.archive_content_obj}`)
|
||||
}
|
||||
|
||||
|
||||
if ($slct.archive_content_obj) {
|
||||
|
||||
} else {
|
||||
console.log(`Archive Content Object started: ${$slct.archive_content_obj}`)
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
console.log('** Component Mounted: ** Edit - Archive Content Obj');
|
||||
|
||||
tinymce_remove(); // This seems to fix rendering issues
|
||||
tinymce_init();
|
||||
});
|
||||
|
||||
onDestroy(() => {
|
||||
console.log('** Component Destroyed: ** Edit - Event Obj');
|
||||
tinymce_remove(); // This seems like the right thing to do
|
||||
});
|
||||
|
||||
|
||||
// let ae_iframe_height = window.outerHeight;
|
||||
let ae_iframe_height = window.innerHeight;
|
||||
console.log(`ae_iframe_height: ${ae_iframe_height}`);
|
||||
$: if (ae_iframe_height) {
|
||||
console.log('ae_iframe_height changed:', ae_iframe_height);
|
||||
|
||||
let iframe_height = ae_iframe_height; // TESTING!!!
|
||||
|
||||
// window.parent.postMessage({'iframe_height': `${iframe_height}px`}, "*");
|
||||
window.parent.postMessage({'iframe_height': iframe_height}, "*");
|
||||
}
|
||||
|
||||
|
||||
$: if ($slct.archive_content_obj) {
|
||||
console.log('Selected archive_content object changed?');
|
||||
console.log($slct.archive_content_obj);
|
||||
|
||||
if ($slct.archive_content_obj == null) {
|
||||
$slct.archive_content_obj = {title: null, content: null, name: null, description: null, notes: null, created_on: null, updated_on: null};
|
||||
} else {
|
||||
disable_submit_btn = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async function handle_submit_form(event) {
|
||||
console.log('*** handle_submit_form() ***');
|
||||
|
||||
disable_submit_btn = true;
|
||||
|
||||
let form_data = new FormData(event.target);
|
||||
console.log(form_data);
|
||||
|
||||
let form_archive_content_data = ae.util.extract_prefixed_form_data({prefix: null, form_data: form_data, trim_values: true, bool_tf_str: true, log_lvl: 0});
|
||||
console.log(form_archive_content_data);
|
||||
|
||||
let archive_content_data: key_val = {};
|
||||
|
||||
if (!$slct.archive_content_id) {
|
||||
archive_content_data['account_id_random'] = $ae_app.account_id;
|
||||
archive_content_data['archive_id_random'] = $slct.archive_id;
|
||||
// archive_content_data['enable'] = true;
|
||||
}
|
||||
|
||||
archive_content_data['name'] = form_archive_content_data.name;
|
||||
if (tinyMCE.get('description')) {
|
||||
archive_content_data['description'] = tinyMCE.get('description').getContent();
|
||||
} else {
|
||||
archive_content_data['description'] = form_archive_content_data.description;
|
||||
}
|
||||
|
||||
if (tinyMCE.get('content_html')) {
|
||||
archive_content_data['content_html'] = tinyMCE.get('content_html').getContent();
|
||||
} else {
|
||||
archive_content_data['content_html'] = form_archive_content_data.content_html;
|
||||
}
|
||||
|
||||
if (form_archive_content_data.archive_content_type) {
|
||||
archive_content_data['archive_content_type'] = form_archive_content_data.archive_content_type;
|
||||
} else {
|
||||
archive_content_data['archive_content_type'] = null;
|
||||
}
|
||||
|
||||
archive_content_data['enable_for_public'] = !!!form_archive_content_data.enable_for_public;
|
||||
|
||||
archive_content_data['file_path'] = form_archive_content_data.file_path;
|
||||
archive_content_data['filename'] = form_archive_content_data.filename.trim();
|
||||
archive_content_data['file_extension'] = form_archive_content_data.file_extension.trim();
|
||||
|
||||
let date_time_str = null;
|
||||
let date_part = form_archive_content_data.original_datetime_date.trim();
|
||||
let time_part = form_archive_content_data.original_datetime_time.trim();
|
||||
if (date_part && time_part) {
|
||||
date_time_str = `${date_part} ${time_part}`;
|
||||
} else if (date_part) {
|
||||
date_time_str = `${date_part}T00:00:00`;
|
||||
} else if (time_part) {
|
||||
// date_time_str = `${time_part}`;
|
||||
date_time_str = false;
|
||||
}
|
||||
archive_content_data['original_datetime'] = date_time_str;
|
||||
|
||||
archive_content_data['original_timezone'] = form_archive_content_data.original_timezone;
|
||||
|
||||
archive_content_data['original_location'] = form_archive_content_data.original_location;
|
||||
|
||||
archive_content_data['hide'] = !!form_archive_content_data.hide;
|
||||
archive_content_data['priority'] = !!form_archive_content_data.priority;
|
||||
if (form_archive_content_data.sort) {
|
||||
// Change this to a number type
|
||||
archive_content_data['sort'] = Number(form_archive_content_data.sort);
|
||||
} else {
|
||||
archive_content_data['sort'] = null;
|
||||
}
|
||||
if (form_archive_content_data.group) {
|
||||
archive_content_data['group'] = form_archive_content_data.group;
|
||||
} else {
|
||||
archive_content_data['group'] = null;
|
||||
}
|
||||
if (archive_content_data['enable']) {
|
||||
archive_content_data['enable'] = !!form_archive_content_data.enable;
|
||||
}
|
||||
|
||||
if (tinyMCE.get('notes')) {
|
||||
archive_content_data['notes'] = tinyMCE.get('notes').getContent();
|
||||
} else {
|
||||
archive_content_data['notes'] = form_archive_content_data.notes;
|
||||
}
|
||||
|
||||
console.log(archive_content_data);
|
||||
|
||||
if (!$slct.archive_content_id) {
|
||||
create_archive_content_obj_promise = api.create_ae_obj_crud({
|
||||
api_cfg: $ae_app.ae_api,
|
||||
obj_type: 'archive_content',
|
||||
fields: archive_content_data,
|
||||
key: $ae_app.ae_api.api_crud_super_key,
|
||||
log_lvl: 1
|
||||
})
|
||||
.then(async function (archive_content_obj_create_result) {
|
||||
if (!archive_content_obj_create_result) {
|
||||
console.log('The result was null or false.');
|
||||
return false;
|
||||
}
|
||||
|
||||
$slct.archive_content_id = archive_content_obj_create_result.obj_id_random;
|
||||
|
||||
// Get ready to upload the file now that we have a new archive_content_id.
|
||||
const form_data = new FormData();
|
||||
|
||||
form_data.append('account_id', $ae_app.account_id);
|
||||
form_data.append('link_to_type', 'archive_content');
|
||||
form_data.append('link_to_id', $slct.archive_content_id);
|
||||
|
||||
for (let i = 0; i < event.target.file_list.files.length; i++) {
|
||||
form_data.append(`file_list`, event.target.archive_content_file_upload_list.files[i]);
|
||||
}
|
||||
|
||||
let params = null;
|
||||
|
||||
let endpoint = '/hosted_file/upload_files';
|
||||
|
||||
console.log(form_data);
|
||||
|
||||
params = null;
|
||||
|
||||
// Uncomment and the post_promise is not seen by the "await" below
|
||||
// post_promise = await api.post_object({api_cfg: $cfg.api, endpoint: endpoint, params: params, data:form_data});
|
||||
// Uncomment so that the post_promise is not seen by the "await" below
|
||||
upload__hosted_file_obj_promise = await api.post_object({api_cfg: $ae_app.ae_api, endpoint: endpoint, params: params, form_data: form_data});
|
||||
console.log(upload__hosted_file_obj_promise);
|
||||
let hosted_file_id = upload__hosted_file_obj_promise[0].hosted_file_id_random;
|
||||
|
||||
archive_content_data = {};
|
||||
archive_content_data['hosted_file_id_random'] = hosted_file_id;
|
||||
archive_content_data['file_path'] = `/hosted_file/download/${hosted_file_id}?filename=${form_archive_content_data.filename.trim()}`;
|
||||
archive_content_data['archive_content_type'] = 'hosted_file';
|
||||
|
||||
update_archive_content_obj_promise = await api.update_ae_obj_id_crud({
|
||||
api_cfg: $ae_app.ae_api,
|
||||
obj_type: 'archive_content',
|
||||
obj_id: $slct.archive_content_id,
|
||||
fields: archive_content_data,
|
||||
key: $ae_app.ae_api.api_crud_super_key,
|
||||
log_lvl: 1
|
||||
})
|
||||
.then(function (archive_content_obj_update_result) {
|
||||
if (!archive_content_obj_update_result) {
|
||||
console.log('The result was null or false.');
|
||||
return false;
|
||||
}
|
||||
return archive_content_obj_update_result;
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log('Something went wrong.');
|
||||
console.log(error);
|
||||
return false;
|
||||
});
|
||||
|
||||
// update_archive_content_obj_promise = await update_archive_content_obj({archive_content_id: $slct.archive_content_id, data: archive_content_data})
|
||||
// console.log(update_archive_content_obj_promise);
|
||||
return update_archive_content_obj_promise
|
||||
})
|
||||
.then(function (archive_content_obj_create_result) {
|
||||
|
||||
dispatch(
|
||||
'created__archive_content_obj',
|
||||
{
|
||||
archive_content_id: $slct.archive_content_id,
|
||||
}
|
||||
);
|
||||
|
||||
return archive_content_obj_create_result;
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log('Something went wrong.');
|
||||
console.log(error);
|
||||
return false;
|
||||
});
|
||||
|
||||
return create_archive_content_obj_promise;
|
||||
|
||||
} else {
|
||||
update_archive_content_obj_promise = api.update_ae_obj_id_crud({
|
||||
api_cfg: $ae_app.ae_api,
|
||||
obj_type: 'archive_content',
|
||||
obj_id: $slct.archive_content_id,
|
||||
fields: archive_content_data,
|
||||
key: $ae_app.ae_api.api_crud_super_key,
|
||||
log_lvl: 1
|
||||
})
|
||||
.then(function (archive_content_obj_update_result) {
|
||||
if (!archive_content_obj_update_result) {
|
||||
console.log('The result was null or false.');
|
||||
return false;
|
||||
}
|
||||
|
||||
dispatch(
|
||||
'updated__archive_content_obj',
|
||||
{
|
||||
archive_content_id: $slct.archive_content_id,
|
||||
}
|
||||
);
|
||||
|
||||
return archive_content_obj_update_result;
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log('Something went wrong.');
|
||||
console.log(error);
|
||||
return false;
|
||||
});
|
||||
|
||||
return update_archive_content_obj_promise;
|
||||
}
|
||||
}
|
||||
|
||||
function handle_input_file_list_updated(event) {
|
||||
console.log(event.detail.element_id);
|
||||
console.log(event.detail.input_file_list);
|
||||
console.log(event.detail.input_file_list_processed);
|
||||
|
||||
// This now needs be reviewed and possibly updated with additional information. Check if any files have already been uploaded in the past and ignore.
|
||||
let new_upload_list = event.detail.input_file_list_processed;
|
||||
$ae_app.archives.input_file_list = new_upload_list;
|
||||
// Setting the first file as the default. For now other files are ignored?
|
||||
if (new_upload_list.length) {
|
||||
$ae_app.archives.input_filename = new_upload_list[0].filename;
|
||||
$ae_app.archives.input_file_extension = new_upload_list[0].guessed_extension;
|
||||
} else {
|
||||
$ae_app.archives.input_filename = '';
|
||||
$ae_app.archives.input_file_extension = '';
|
||||
}
|
||||
|
||||
// for (let file_upload_item of new_upload_list) {
|
||||
// console.log(file_upload_item);
|
||||
|
||||
// filename = file_upload_item.filename;
|
||||
// file_extension = file_upload_item.guessed_extension;
|
||||
// }
|
||||
}
|
||||
|
||||
$ae_app.archives.form_file_upload_list = [];
|
||||
|
||||
async function handle_delete_archive_content_obj({archive_content_id, hosted_file_id=null, method='delete'}) {
|
||||
console.log('*** handle_delete_archive_content_obj() ***');
|
||||
|
||||
if (hosted_file_id) {
|
||||
let delete_hosted_file_obj_promise = api.delete_hosted_file({
|
||||
api_cfg: $ae_app.ae_api,
|
||||
hosted_file_id: hosted_file_id,
|
||||
link_to_type: 'archive_content',
|
||||
link_to_id: archive_content_id,
|
||||
rm_orphan: true,
|
||||
// params: params,
|
||||
key: $ae_app.ae_api.api_crud_super_key,
|
||||
log_lvl: 2
|
||||
})
|
||||
.then(function (hosted_file_obj_delete_result) {
|
||||
if (hosted_file_obj_delete_result) {
|
||||
// console.log(`Result:`, hosted_file_obj_delete_result);
|
||||
|
||||
dispatch(
|
||||
'deleted__hosted_file_obj',
|
||||
{
|
||||
hosted_file_id: hosted_file_id,
|
||||
}
|
||||
);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log('The result was null or false when trying to delete.', error);
|
||||
});
|
||||
}
|
||||
|
||||
delete_archive_content_obj_promise = api.delete_ae_obj_id_crud({
|
||||
api_cfg: $ae_app.ae_api,
|
||||
obj_type: 'archive_content',
|
||||
obj_id: archive_content_id,
|
||||
method: method,
|
||||
// params: params,
|
||||
key: $ae_app.ae_api.api_crud_super_key,
|
||||
log_lvl: 0
|
||||
})
|
||||
.then(function (archive_content_obj_delete_result) {
|
||||
if (archive_content_obj_delete_result) {
|
||||
// console.log(`Result:`, archive_content_obj_delete_result);
|
||||
|
||||
dispatch(
|
||||
'deleted__archive_content_obj',
|
||||
{
|
||||
archive_content_id: archive_content_id,
|
||||
}
|
||||
);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log('The result was null or false when trying to delete.', error);
|
||||
});
|
||||
|
||||
return delete_archive_content_obj_promise;
|
||||
}
|
||||
|
||||
function tinymce_init() {
|
||||
// REFERENCE: https://www.tiny.cloud/docs/tinymce/6/basic-setup/
|
||||
// plugins: [
|
||||
// 'advlist', 'autolink', 'link', 'image', 'lists', 'charmap', 'preview', 'anchor', 'pagebreak',
|
||||
// 'searchreplace', 'wordcount', 'visualblocks', 'visualchars', 'code', 'fullscreen', 'insertdatetime',
|
||||
// 'media', 'table', 'emoticons', 'template', 'help'
|
||||
// ],
|
||||
// 'undo redo | styles | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent'
|
||||
|
||||
// NOTE: Regular version of the TinyMCE editor
|
||||
tinymce.init({
|
||||
selector: '.tinymce_editor.editor_regular',
|
||||
// width: 600,
|
||||
height: 400,
|
||||
plugins: [ 'advlist', 'autolink', 'link', 'lists', 'anchor', 'code', 'help' ],
|
||||
menubar: false,
|
||||
toolbar: 'undo redo | styles | bold italic | alignleft aligncenter alignright | bullist numlist outdent indent | link | code | help',
|
||||
});
|
||||
|
||||
// NOTE: Basic version of the TinyMCE editor
|
||||
tinymce.init({
|
||||
selector: '.tinymce_editor.editor_basic',
|
||||
// width: 600,
|
||||
height: 400,
|
||||
plugins: [ 'lists', 'code', 'help' ],
|
||||
menubar: false,
|
||||
toolbar: 'undo redo | styles | bold italic | alignleft aligncenter | bullist numlist outdent indent | code | help',
|
||||
});
|
||||
|
||||
// NOTE: Minimal version of the TinyMCE editor
|
||||
tinymce.init({
|
||||
selector: '.tinymce_editor.editor_basic_200',
|
||||
// width: 600,
|
||||
height: 200,
|
||||
plugins: [ 'lists', 'code', 'help' ],
|
||||
menubar: false,
|
||||
toolbar: 'undo redo | styles | bold italic | alignleft aligncenter | bullist numlist outdent indent | code | help',
|
||||
});
|
||||
|
||||
// NOTE: Less is more version of the TinyMCE editor
|
||||
tinymce.init({
|
||||
selector: '.tinymce_editor.editor_less_100',
|
||||
// width: 600,
|
||||
height: 100,
|
||||
// plugins: [ 'lists', 'code', 'help' ],
|
||||
menubar: false,
|
||||
toolbar: false,
|
||||
statusbar: false,
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function tinymce_remove() {
|
||||
tinymce.remove('.tinymce_editor.editor_regular');
|
||||
tinymce.remove('.tinymce_editor.editor_basic');
|
||||
tinymce.remove('.tinymce_editor.editor_basic_200');
|
||||
tinymce.remove('.tinymce_editor.editor_less_100');
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<section
|
||||
class="svelte_component ae_edit archive_content_obj"
|
||||
class:ae_create={!$slct.archive_content_id}
|
||||
>
|
||||
<!-- bind:clientHeight={ae_iframe_height} -->
|
||||
|
||||
<form on:submit|preventDefault={handle_submit_form} class="">
|
||||
|
||||
{#await update_archive_content_obj_promise}
|
||||
<div class="awaiting alert_msg_pulse" out:fade={{ duration: 2000 }}>Saving...</div>
|
||||
{:then}
|
||||
{#if update_archive_content_obj_promise}
|
||||
<div class="awaiting" out:fade={{ duration: 2000 }}>Finished saving</div>
|
||||
{:else}
|
||||
<!-- <div class="awaiting" out:fade={{ duration: 2000 }}>Nothing here yet</div> -->
|
||||
{/if}
|
||||
{/await}
|
||||
|
||||
<h3>Archive Content</h3>
|
||||
|
||||
<label for="title">Name of Content
|
||||
<input type="text" id="name" name="name" required max="200" value={$slct.archive_content_obj.name ? $slct.archive_content_obj.name : '' } placeholder="Content name">
|
||||
</label>
|
||||
|
||||
<label for="description">Description
|
||||
<textarea id="description" name="description" rows="6" cols="80" value={$slct.archive_content_obj.description ? $slct.archive_content_obj.description : ''} class="ae_value archive_content__description tinymce_editor editor_basic_200"></textarea>
|
||||
</label>
|
||||
|
||||
<label for="content_html">Content (HTML)
|
||||
<textarea id="content_html" name="content_html" rows="6" cols="80" value={$slct.archive_content_obj.content_html ? $slct.archive_content_obj.content_html : ''} class="ae_value archive_content__content_html tinymce_editor editor_regular"></textarea>
|
||||
</label>
|
||||
|
||||
<label for="archive_content_type">Type
|
||||
<select id="archive_content_type" name="archive_content_type" value={$slct.archive_content_obj.archive_content_type}>
|
||||
<option value="">-- None --</option>
|
||||
<option value="hosted_file">Hosted File in Æ</option>
|
||||
<option value="html">Hosted HTML in Æ</option>
|
||||
<option value="json">Hosted JSON in Æ</option>
|
||||
<option value="url">External URL</option>
|
||||
<option value="other">Other</option>
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<fieldset class="">
|
||||
<legend class="">Public Access with Rotating Access Key/Passcode</legend>
|
||||
<label for="enable_for_public_no" class="">No, disable public access
|
||||
<input
|
||||
type="radio"
|
||||
class=""
|
||||
id="enable_for_public_no"
|
||||
name="enable_for_public"
|
||||
value={false}
|
||||
bind:group={$slct.archive_content_obj.enable_for_public}
|
||||
>
|
||||
<!-- <input type="radio" class="" id="enable_for_public_no" name="enable_for_public" value="0" checked={(!$slct.archive_content_obj.enable_for_public)} required> -->
|
||||
</label>
|
||||
<label for="enable_for_public_yes" class="">Yes, allow public access
|
||||
<input
|
||||
type="radio"
|
||||
class=""
|
||||
id="enable_for_public_yes"
|
||||
name="enable_for_public"
|
||||
value={true}
|
||||
bind:group={$slct.archive_content_obj.enable_for_public}
|
||||
>
|
||||
<!-- <input type="radio" class="" id="enable_for_public_yes" name="enable_for_public" value="1" checked={($slct.archive_content_obj.enable_for_public)} required > -->
|
||||
</label>
|
||||
</fieldset>
|
||||
|
||||
|
||||
<h3>File?</h3>
|
||||
{#if !$slct.archive_content_id}
|
||||
<Element_input_file_hashing
|
||||
multiple = {false}
|
||||
required = {true}
|
||||
accept = {''}
|
||||
element_id = {'archive_content_file_upload_list'}
|
||||
|
||||
on:input_file_list_updated = {handle_input_file_list_updated}
|
||||
use_selected_file_table={true}
|
||||
/>
|
||||
<!-- bind:input_file_list = {$ae_app.archives.form_file_upload_list} -->
|
||||
{/if}
|
||||
|
||||
<label for="file_path">File Path
|
||||
{#if !$ae_app.administrator_access}
|
||||
<span class="fas fa-lock" title="Field is locked"></span>
|
||||
{:else}
|
||||
<span class="fas fa-unlock" title="Field is unlocked"></span>
|
||||
{/if}
|
||||
<input
|
||||
type="text"
|
||||
id="file_path"
|
||||
name="file_path"
|
||||
value={($slct.archive_content_obj.file_path ? $slct.archive_content_obj.file_path : '')}
|
||||
readonly={!$ae_app.administrator_access}
|
||||
>
|
||||
</label>
|
||||
|
||||
<label for="filename">Filename
|
||||
<input type="text" id="filename" name="filename" value={($slct.archive_content_obj.filename ? $slct.archive_content_obj.filename : $ae_app.archives.input_filename)}>
|
||||
</label>
|
||||
|
||||
<label for="file_extension">File Extension
|
||||
{#if !$ae_app.administrator_access}
|
||||
<span class="fas fa-lock" title="Field is locked"></span>
|
||||
{:else}
|
||||
<span class="fas fa-unlock" title="Field is unlocked"></span>
|
||||
{/if}
|
||||
<input
|
||||
type="text"
|
||||
id="file_extension"
|
||||
name="file_extension"
|
||||
value={($slct.archive_content_obj.file_extension ? $slct.archive_content_obj.file_extension : $ae_app.archives.input_file_extension)}
|
||||
readonly={!$ae_app.administrator_access}
|
||||
>
|
||||
</label>
|
||||
|
||||
<h3>Original</h3>
|
||||
<label for="original_datetime">Original Date/Time
|
||||
<input type="date" id="original_datetime_date" name="original_datetime_date" value={($slct.archive_content_obj.original_datetime ? ae.util.iso_datetime_formatter($slct.archive_content_obj.original_datetime,'date_iso') : '')} placeholder="YYYY-MM-DD">
|
||||
<input type="time" id="original_datetime_time" name="original_datetime_time" value={($slct.archive_content_obj.original_datetime ? ae.util.iso_datetime_formatter($slct.archive_content_obj.original_datetime,'time_iso') : '')} placeholder="HH:MM AM/PM">
|
||||
</label>
|
||||
|
||||
<fieldset class="flex_row flex_gap_md flex_justify_around">
|
||||
<label for="original_timezone">Original Timezone
|
||||
{#if $ae_app.lu_time_zone_list}
|
||||
<select name="original_timezone" id="original_timezone" required>
|
||||
{#each $ae_app.lu_time_zone_list as lu_timezone}
|
||||
<option value="{lu_timezone.name}" selected={((($slct.archive_content_obj.original_timezone && lu_timezone.name == $slct.archive_content_obj.original_timezone) || lu_timezone.name == $ae_app.current_timezone) ? 'selected' : '')}>{lu_timezone.name}</option>
|
||||
{/each}
|
||||
</select>
|
||||
{:else}
|
||||
<input type="text" name="timezone" value={($slct.archive_content_obj.original_timezone ? $slct.archive_content_obj.original_timezone : $ae_app.current_timezone)} />
|
||||
{/if}
|
||||
</label>
|
||||
</fieldset>
|
||||
|
||||
<!-- <label for="original_timezone">Original Timezone
|
||||
<input type="text" id="original_timezone" name="original_timezone" value={$slct.archive_content_obj.original_timezone} list="timezones">
|
||||
<datalist id="timezones">
|
||||
<option value="UTC">UTC</option>
|
||||
<option value="America/New_York">America/New York</option>
|
||||
<option value="America/Chicago">America/Chicago</option>
|
||||
<option value="America/Denver">America/Denver</option>
|
||||
<option value="America/Phoenix">America/Phoenix</option>
|
||||
<option value="America/Los_Angeles">America/Los Angeles</option>
|
||||
<option value="America/Anchorage">America/Anchorage</option>
|
||||
<option value="America/Adak">America/Adak</option>
|
||||
<option value="Pacific/Honolulu">Pacific/Honolulu</option>
|
||||
<option value="Pacific/Midway">Pacific/Midway</option>
|
||||
<option value="US/Eastern">US/Eastern</option>
|
||||
<option value="US/Central">US/Central</option>
|
||||
<option value="US/Mountain">US/Mountain</option>
|
||||
<option value="US/Pacific">US/Pacific</option>
|
||||
<option value="US/Alaska">US/Alaska</option>
|
||||
<option value="US/Hawaii">US/Hawaii</option>
|
||||
<option value="US/Samoa">US/Samoa</option>
|
||||
<option value="US/Aleutian">US/Aleutian</option>
|
||||
<option value="US/Arizona">US/Arizona</option>
|
||||
<option value="US/Michigan">US/Michigan</option>
|
||||
</datalist>
|
||||
</label> -->
|
||||
|
||||
<label for="original_location">Original Location
|
||||
<input type="text" id="original_location" name="original_location" value={$slct.archive_content_obj.original_location}>
|
||||
</label>
|
||||
|
||||
|
||||
{#if $ae_app.trusted_access}
|
||||
<section class="ae_section archive_content__admin_options"> <!-- BEGIN: section archive_content__admin_options -->
|
||||
|
||||
<h3>
|
||||
Admin Options
|
||||
<button type="button" class="ae_btn ae_smallest ae_d_none_toggle ae_float_right btn btn-xs btn-info" on:click={() => {document.querySelector('.ae_d_none_content').classList.toggle('ae_d_none');}}><span class="fas fa-eye"></span> Show/Hide Admin</button>
|
||||
</h3>
|
||||
|
||||
<span class="ae_d_none_content ae_d_none">
|
||||
<label>Hide
|
||||
<input
|
||||
type="checkbox"
|
||||
name="hide"
|
||||
id="hide"
|
||||
bind:checked={$slct.archive_content_obj.hide}
|
||||
>
|
||||
<!-- <input type="checkbox" name="hide" value={$slct.archive_content_obj.hide} /> -->
|
||||
</label>
|
||||
|
||||
<label>Priority
|
||||
<input
|
||||
type="checkbox"
|
||||
name="priority"
|
||||
id="priority"
|
||||
bind:checked={$slct.archive_content_obj.priority}
|
||||
>
|
||||
<!-- <input type="checkbox" name="priority" value={$slct.archive_content_obj.priority} /> -->
|
||||
</label>
|
||||
|
||||
<label>Sort <input type="number" name="sort" value={$slct.archive_content_obj.sort} /></label>
|
||||
|
||||
<label>Group <input type="text" name="group" value={$slct.archive_content_obj.group} max="100" /></label>
|
||||
|
||||
{#if $ae_app.administrator_access}
|
||||
<label>Enable
|
||||
<input
|
||||
type="checkbox"
|
||||
name="enable"
|
||||
id="enable"
|
||||
bind:checked={$slct.archive_content_obj.enable}
|
||||
>
|
||||
<!-- <input type="checkbox" name="enable" value={$slct.archive_content_obj.enable} checked={$slct.archive_content_obj.enable} /> -->
|
||||
</label>
|
||||
{/if}
|
||||
|
||||
<label>Internal Staff Notes
|
||||
<textarea id="notes" name="notes" class="ae_value archive_content__notes tinymce_editor editor_basic_200" rows="2" cols="70" value={$slct.archive_content_obj.notes}></textarea>
|
||||
</label>
|
||||
|
||||
</span> <!-- END: span ae_show_hide_content -->
|
||||
|
||||
</section> <!-- END: section archive_content__admin_options -->
|
||||
{/if}
|
||||
|
||||
|
||||
<section class="ae_section ae_options ae_row">
|
||||
<button type="submit" class="ae_btn btn btn-primary"><span class="fas fa-check"></span> Save Archive Content</button>
|
||||
|
||||
{#if $slct.archive_content_id}
|
||||
<button
|
||||
on:click={() => {
|
||||
if (!confirm('Are you sure you want to delete this archive content?')) {return false;}
|
||||
handle_delete_archive_content_obj({archive_content_id: $slct.archive_content_id, hosted_file_id: $slct.archive_content_obj.hosted_file_id_random});
|
||||
|
||||
$slct.archive_content_id = null;
|
||||
$slct.archive_content_obj = {};
|
||||
}}
|
||||
class="ae_btn ae_smallest btn btn-danger" type="button">
|
||||
<span class="fas fa-minus"></span> Delete
|
||||
</button>
|
||||
{/if}
|
||||
</section>
|
||||
|
||||
</form>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<style>
|
||||
</style>
|
||||
@@ -1,588 +0,0 @@
|
||||
<script lang="ts">
|
||||
import { createEventDispatcher, onDestroy, onMount } from 'svelte';
|
||||
import { fade } from 'svelte/transition';
|
||||
|
||||
import { ae, api, Element_input } from 'aether_npm_lib';
|
||||
import { slct, ae_app } from './stores';
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
type key_val = {
|
||||
[key: string]: any;
|
||||
};
|
||||
|
||||
let create_archive_obj_promise: any;
|
||||
let delete_archive_obj_promise: any;
|
||||
let update_archive_obj_promise: any;
|
||||
|
||||
let disable_submit_btn = true;
|
||||
|
||||
if ($slct.archive_id) {
|
||||
console.log(`Archive ID selected: ${$slct.archive_id}`);
|
||||
console.log(`Archive Object selected: ${$slct.archive_obj}`)
|
||||
} else {
|
||||
$slct.archive_id = null;
|
||||
$slct.archive_obj = {
|
||||
title: null,
|
||||
content: null,
|
||||
topic_id: null,
|
||||
anonymous: false,
|
||||
external_person_id: $ae_app.novi_uuid,
|
||||
full_name: $ae_app.novi_full_name,
|
||||
email: $ae_app.novi_email,
|
||||
|
||||
sort: null,
|
||||
notes: null,
|
||||
};
|
||||
console.log(`Archive Object started: ${$slct.archive_obj}`)
|
||||
}
|
||||
|
||||
|
||||
if ($slct.archive_obj) {
|
||||
|
||||
} else {
|
||||
// $slct.archive_obj = {name: 'null', description: 'null'};
|
||||
console.log(`Archive Object started: ${$slct.archive_obj}`)
|
||||
}
|
||||
|
||||
if ($ae_app.lu_time_zone_list && $ae_app.lu_time_zone_list.length > 0) {
|
||||
// console.log('Already have time zone list!', $ae_app.lu_time_zone_list);
|
||||
} else {
|
||||
console.log('No time zone list');
|
||||
|
||||
let lu_time_zone_li_get_promise = api.get_ae_obj_li_for_obj_id_crud({
|
||||
api_cfg: $ae_app.ae_api,
|
||||
obj_type: 'lu', // "lu" = a lookup table
|
||||
for_obj_type: 'time_zone',
|
||||
enabled: null,
|
||||
hidden: null,
|
||||
// order_by_li: {'name': 'ASC'},
|
||||
log_lvl: 1
|
||||
})
|
||||
|
||||
.then(function (lu_time_zone_li_get_result) {
|
||||
if (lu_time_zone_li_get_result) {
|
||||
$ae_app.lu_time_zone_list = lu_time_zone_li_get_result;
|
||||
console.log(`Time zone list:`, $ae_app.lu_time_zone_list);
|
||||
console.log($ae_app.lu_time_zone_list[0]);
|
||||
console.log($ae_app.lu_time_zone_list[10]);
|
||||
} else {
|
||||
console.log(`No time zones returned!`);
|
||||
$ae_app.lu_time_zone_list = [];
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log('No results returned or failed.', error);
|
||||
});
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
console.log('** Component Mounted: ** Edit - Event Obj');
|
||||
|
||||
tinymce_remove(); // This seems to fix rendering issues
|
||||
tinymce_init();
|
||||
});
|
||||
|
||||
onDestroy(() => {
|
||||
console.log('** Component Destroyed: ** Edit - Event Obj');
|
||||
tinymce_remove(); // This seems like the right thing to do
|
||||
});
|
||||
|
||||
|
||||
// let ae_iframe_height = window.outerHeight;
|
||||
let ae_iframe_height = window.innerHeight;
|
||||
console.log(`ae_iframe_height: ${ae_iframe_height}`);
|
||||
$: if (ae_iframe_height) {
|
||||
console.log('ae_iframe_height changed:', ae_iframe_height);
|
||||
|
||||
let iframe_height = ae_iframe_height; // TESTING!!!
|
||||
|
||||
// window.parent.postMessage({'iframe_height': `${iframe_height}px`}, "*");
|
||||
window.parent.postMessage({'iframe_height': iframe_height}, "*");
|
||||
}
|
||||
|
||||
|
||||
$: if ($slct.archive_obj) {
|
||||
console.log('Selected archive object changed?');
|
||||
console.log($slct.archive_obj);
|
||||
|
||||
if ($slct.archive_obj == null) {
|
||||
$slct.archive_obj = {title: null, content: null, name: null, description: null, notes: null, created_on: null, updated_on: null};
|
||||
} else {
|
||||
disable_submit_btn = false;
|
||||
}
|
||||
|
||||
// ae.input_template['event']['timezone'] = 'EDT';
|
||||
}
|
||||
|
||||
|
||||
async function handle_submit_form(event) {
|
||||
console.log('*** handle_submit_form() ***');
|
||||
|
||||
disable_submit_btn = true;
|
||||
|
||||
let form_data = new FormData(event.target);
|
||||
console.log(form_data);
|
||||
|
||||
let form_archive_data = ae.util.extract_prefixed_form_data({prefix: null, form_data: form_data, trim_values: true, bool_tf_str: true, log_lvl: 0});
|
||||
console.log(form_archive_data);
|
||||
|
||||
let archive_data: key_val = {};
|
||||
|
||||
if (!$slct.archive_id) {
|
||||
archive_data['account_id_random'] = $ae_app.account_id;
|
||||
archive_data['enable'] = true;
|
||||
}
|
||||
|
||||
archive_data['name'] = form_archive_data.name;
|
||||
if (tinyMCE.get('description')) {
|
||||
archive_data['description'] = tinyMCE.get('description').getContent();
|
||||
} else {
|
||||
archive_data['description'] = form_archive_data.description;
|
||||
}
|
||||
|
||||
if (tinyMCE.get('content_html')) {
|
||||
archive_data['content_html'] = tinyMCE.get('content_html').getContent();
|
||||
} else {
|
||||
archive_data['content_html'] = form_archive_data.content_html;
|
||||
}
|
||||
|
||||
let date_time_str = null;
|
||||
let date_part = form_archive_data.original_datetime_date.trim();
|
||||
let time_part = form_archive_data.original_datetime_time.trim();
|
||||
if (date_part && time_part) {
|
||||
date_time_str = `${date_part} ${time_part}`;
|
||||
} else if (date_part) {
|
||||
date_time_str = `${date_part}T00:00:00`;
|
||||
} else if (time_part) {
|
||||
// date_time_str = `${time_part}`;
|
||||
date_time_str = false;
|
||||
}
|
||||
archive_data['original_datetime'] = date_time_str;
|
||||
|
||||
archive_data['original_timezone'] = form_archive_data.original_timezone;
|
||||
|
||||
archive_data['original_location'] = form_archive_data.original_location;
|
||||
|
||||
archive_data['original_url'] = form_archive_data.original_url;
|
||||
archive_data['original_url_text'] = form_archive_data.original_url_text;
|
||||
|
||||
archive_data['hide'] = !!form_archive_data.hide;
|
||||
archive_data['priority'] = !!form_archive_data.priority;
|
||||
if (form_archive_data.sort) {
|
||||
archive_data['sort'] = Number(form_archive_data.sort);
|
||||
} else {
|
||||
archive_data['sort'] = null;
|
||||
}
|
||||
if (form_archive_data.group) {
|
||||
archive_data['group'] = form_archive_data.group;
|
||||
} else {
|
||||
archive_data['group'] = null;
|
||||
}
|
||||
|
||||
if (form_archive_data.enable) {
|
||||
archive_data['enable'] = !!form_archive_data.enable;
|
||||
}
|
||||
|
||||
if (tinyMCE.get('notes')) {
|
||||
archive_data['notes'] = tinyMCE.get('notes').getContent();
|
||||
} else {
|
||||
archive_data['notes'] = form_archive_data.notes;
|
||||
}
|
||||
|
||||
console.log(archive_data);
|
||||
|
||||
if (!$slct.archive_id) {
|
||||
create_archive_obj_promise = api.create_ae_obj_crud({
|
||||
api_cfg: $ae_app.ae_api,
|
||||
obj_type: 'archive',
|
||||
fields: archive_data,
|
||||
key: $ae_app.ae_api.api_crud_super_key,
|
||||
log_lvl: 1
|
||||
})
|
||||
.then(function (archive_obj_create_result) {
|
||||
if (!archive_obj_create_result) {
|
||||
console.log('The result was null or false.');
|
||||
return false;
|
||||
}
|
||||
|
||||
$slct.archive_id = archive_obj_create_result.obj_id_random;
|
||||
|
||||
dispatch(
|
||||
'created__archive_obj',
|
||||
{
|
||||
archive_id: $slct.archive_id,
|
||||
}
|
||||
);
|
||||
|
||||
return archive_obj_create_result;
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log('Something went wrong.');
|
||||
console.log(error);
|
||||
return false;
|
||||
});
|
||||
|
||||
return create_archive_obj_promise;
|
||||
|
||||
} else {
|
||||
update_archive_obj_promise = api.update_ae_obj_id_crud({
|
||||
api_cfg: $ae_app.ae_api,
|
||||
obj_type: 'archive',
|
||||
obj_id: $slct.archive_id,
|
||||
fields: archive_data,
|
||||
key: $ae_app.ae_api.api_crud_super_key,
|
||||
log_lvl: 1
|
||||
})
|
||||
.then(function (archive_obj_update_result) {
|
||||
if (!archive_obj_update_result) {
|
||||
console.log('The result was null or false.');
|
||||
return false;
|
||||
}
|
||||
|
||||
dispatch(
|
||||
'updated__archive_obj',
|
||||
{
|
||||
archive_id: $slct.archive_id,
|
||||
}
|
||||
);
|
||||
|
||||
return archive_obj_update_result;
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log('Something went wrong.');
|
||||
console.log(error);
|
||||
return false;
|
||||
});
|
||||
|
||||
return update_archive_obj_promise;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async function handle_delete_archive_obj({archive_id, method='delete'}) {
|
||||
console.log('*** handle_delete_archive_obj() ***');
|
||||
|
||||
delete_archive_obj_promise = api.delete_ae_obj_id_crud({
|
||||
api_cfg: $ae_app.ae_api,
|
||||
obj_type: 'archive',
|
||||
obj_id: archive_id,
|
||||
method: method,
|
||||
// params: params,
|
||||
key: $ae_app.ae_api.api_crud_super_key,
|
||||
log_lvl: 0
|
||||
})
|
||||
.then(function (archive_obj_delete_result) {
|
||||
if (archive_obj_delete_result) {
|
||||
// console.log(`Result:`, archive_obj_delete_result);
|
||||
|
||||
dispatch(
|
||||
'deleted__archive_obj',
|
||||
{
|
||||
archive_id: archive_id,
|
||||
}
|
||||
);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log('The result was null or false when trying to delete.', error);
|
||||
});
|
||||
|
||||
return delete_archive_obj_promise;
|
||||
}
|
||||
|
||||
function tinymce_init() {
|
||||
// REFERENCE: https://www.tiny.cloud/docs/tinymce/6/basic-setup/
|
||||
// plugins: [
|
||||
// 'advlist', 'autolink', 'link', 'image', 'lists', 'charmap', 'preview', 'anchor', 'pagebreak',
|
||||
// 'searchreplace', 'wordcount', 'visualblocks', 'visualchars', 'code', 'fullscreen', 'insertdatetime',
|
||||
// 'media', 'table', 'emoticons', 'template', 'help'
|
||||
// ],
|
||||
// 'undo redo | styles | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent'
|
||||
|
||||
// NOTE: Regular version of the TinyMCE editor
|
||||
tinymce.init({
|
||||
selector: '.tinymce_editor.editor_regular',
|
||||
// width: 600,
|
||||
height: 400,
|
||||
plugins: [ 'advlist', 'autolink', 'link', 'lists', 'anchor', 'code', 'help' ],
|
||||
menubar: false,
|
||||
toolbar: 'undo redo | styles | bold italic | alignleft aligncenter alignright | bullist numlist outdent indent | link | code | help',
|
||||
});
|
||||
|
||||
// NOTE: Basic version of the TinyMCE editor
|
||||
tinymce.init({
|
||||
selector: '.tinymce_editor.editor_basic',
|
||||
// width: 600,
|
||||
height: 400,
|
||||
plugins: [ 'lists', 'code', 'help' ],
|
||||
menubar: false,
|
||||
toolbar: 'undo redo | styles | bold italic | alignleft aligncenter | bullist numlist outdent indent | code | help',
|
||||
});
|
||||
|
||||
// NOTE: Minimal version of the TinyMCE editor
|
||||
tinymce.init({
|
||||
selector: '.tinymce_editor.editor_basic_200',
|
||||
// width: 600,
|
||||
height: 200,
|
||||
plugins: [ 'lists', 'code', 'help' ],
|
||||
menubar: false,
|
||||
toolbar: 'undo redo | styles | bold italic | alignleft aligncenter | bullist numlist outdent indent | code | help',
|
||||
});
|
||||
|
||||
// NOTE: Less is more version of the TinyMCE editor
|
||||
tinymce.init({
|
||||
selector: '.tinymce_editor.editor_less_100',
|
||||
// width: 600,
|
||||
height: 100,
|
||||
// plugins: [ 'lists', 'code', 'help' ],
|
||||
menubar: false,
|
||||
toolbar: false,
|
||||
statusbar: false,
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function tinymce_remove() {
|
||||
tinymce.remove('.tinymce_editor.editor_regular');
|
||||
tinymce.remove('.tinymce_editor.editor_basic');
|
||||
tinymce.remove('.tinymce_editor.editor_basic_200');
|
||||
tinymce.remove('.tinymce_editor.editor_less_100');
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<section
|
||||
class="svelte_component ae_edit archive_obj"
|
||||
class:ae_create={!$slct.archive_id}
|
||||
bind:clientHeight={$ae_app.iframe_height_modal_body}
|
||||
>
|
||||
|
||||
<form on:submit|preventDefault={handle_submit_form} class="">
|
||||
|
||||
{#await update_archive_obj_promise}
|
||||
<div class="awaiting alert_msg_pulse" out:fade={{ duration: 2000 }}>Saving...</div>
|
||||
{:then}
|
||||
{#if update_archive_obj_promise}
|
||||
<div class="awaiting" out:fade={{ duration: 2000 }}>Finished saving</div>
|
||||
{:else}
|
||||
<!-- <div class="awaiting" out:fade={{ duration: 2000 }}>Nothing here yet</div> -->
|
||||
{/if}
|
||||
{/await}
|
||||
|
||||
<h3>Archive</h3>
|
||||
|
||||
<label for="name">Name of Archive
|
||||
<input type="text" id="name" name="name" required max="20" value={$slct.archive_obj.name ? $slct.archive_obj.name : 'Testing!' } placeholder="Name of Archive">
|
||||
</label>
|
||||
|
||||
<label for="description">Description
|
||||
<textarea id="description" name="description" rows="6" cols="80" value={$slct.archive_obj.description ? $slct.archive_obj.description : ''} class="ae_value archive__description tinymce_editor editor_basic_200"></textarea>
|
||||
</label>
|
||||
|
||||
<label for="content_html">Content (HTML)
|
||||
<textarea id="content_html" name="content_html" rows="6" cols="80" value={$slct.archive_obj.content_html ? $slct.archive_obj.content_html : ''} class="ae_value archive__content_html tinymce_editor editor_regular"></textarea>
|
||||
</label>
|
||||
|
||||
<h3>Original</h3>
|
||||
<label for="original_datetime">Original Date/Time
|
||||
<input type="date" id="original_datetime_date" name="original_datetime_date" value={($slct.archive_obj.original_datetime ? ae.util.iso_datetime_formatter($slct.archive_obj.original_datetime,'date_iso') : '')} placeholder="YYYY-MM-DD">
|
||||
<input type="time" id="original_datetime_time" name="original_datetime_time" value={($slct.archive_obj.original_datetime ? ae.util.iso_datetime_formatter($slct.archive_obj.original_datetime,'time_iso') : '')} placeholder="HH:MM AM/PM">
|
||||
</label>
|
||||
|
||||
<fieldset class="flex_row flex_gap_md flex_justify_around">
|
||||
<label for="original_timezone">Original Timezone
|
||||
{#if $ae_app.lu_time_zone_list}
|
||||
<select name="original_timezone" id="original_timezone" required>
|
||||
{#each $ae_app.lu_time_zone_list as lu_timezone}
|
||||
<option value="{lu_timezone.name}" selected={((($slct.archive_obj.original_timezone && lu_timezone.name == $slct.archive_obj.original_timezone) || lu_timezone.name == $ae_app.current_timezone) ? 'selected' : '')}>{lu_timezone.name}</option>
|
||||
{/each}
|
||||
</select>
|
||||
{:else}
|
||||
<input type="text" name="timezone" value={($slct.archive_obj.original_timezone ? $slct.archive_obj.original_timezone : $ae_app.current_timezone)} />
|
||||
{/if}
|
||||
</label>
|
||||
</fieldset>
|
||||
|
||||
<!-- <label for="original_timezone">Original Timezone
|
||||
<input type="text" id="original_timezone" name="original_timezone" value={($slct.archive_obj.original_timezone ? $slct.archive_obj.original_timezone : $ae_app.current_timezone)} placeholder="Timezone" list="timezones">
|
||||
<datalist id="timezones">
|
||||
<option value="UTC">UTC</option>
|
||||
<option value="America/New_York">America/New York</option>
|
||||
<option value="America/Chicago">America/Chicago</option>
|
||||
<option value="America/Denver">America/Denver</option>
|
||||
<option value="America/Phoenix">America/Phoenix</option>
|
||||
<option value="America/Los_Angeles">America/Los Angeles</option>
|
||||
<option value="America/Anchorage">America/Anchorage</option>
|
||||
<option value="America/Adak">America/Adak</option>
|
||||
<option value="Pacific/Honolulu">Pacific/Honolulu</option>
|
||||
<option value="Pacific/Midway">Pacific/Midway</option>
|
||||
<option value="US/Eastern">US/Eastern</option>
|
||||
<option value="US/Central">US/Central</option>
|
||||
<option value="US/Mountain">US/Mountain</option>
|
||||
<option value="US/Pacific">US/Pacific</option>
|
||||
<option value="US/Alaska">US/Alaska</option>
|
||||
<option value="US/Hawaii">US/Hawaii</option>
|
||||
<option value="US/Samoa">US/Samoa</option>
|
||||
<option value="US/Aleutian">US/Aleutian</option>
|
||||
<option value="US/Arizona">US/Arizona</option>
|
||||
<option value="US/Michigan">US/Michigan</option>
|
||||
</datalist>
|
||||
</label> -->
|
||||
|
||||
<label for="original_location">Original Location
|
||||
<input type="text" id="original_location" name="original_location" value={($slct.archive_obj.original_location ? $slct.archive_obj.original_location : '')} placeholder="Location">
|
||||
</label>
|
||||
|
||||
<label for="original_url">Original URL
|
||||
<input type="text" id="original_url" name="original_url" max="255" value={$slct.archive_obj.original_url ? $slct.archive_obj.original_url : '' } placeholder="URL">
|
||||
</label>
|
||||
|
||||
<label for="original_url_text">Original URL Text/Title
|
||||
<input type="text" id="original_url_text" name="original_url_text" max="255" value={$slct.archive_obj.original_url_text ? $slct.archive_obj.original_url_text : '' } placeholder="URL text or title">
|
||||
</label>
|
||||
|
||||
|
||||
<!-- <label for="topic_id">BB post topic
|
||||
<select id="topic_id" name="topic_id">
|
||||
<option value="">-- None --</option>
|
||||
<option value="16">Licensing/ monitoring/ credentialing issues</option>
|
||||
<option value="17">Return to practice</option>
|
||||
<option value="18">Contacts/ sponsorship in my area</option>
|
||||
<option value="19">Professional positions</option>
|
||||
<option value="21">Announcement</option>
|
||||
</select>
|
||||
</label> -->
|
||||
|
||||
<!-- <h3>Archiveer's Information</h3>
|
||||
<fieldset class="">
|
||||
<legend class="">Archive as Anonymous</legend>
|
||||
<div class="">
|
||||
<input type="radio" class="" id="anonymous_no" name="anonymous" value="0" checked={(!$slct.archive_obj.anonymous)} required>
|
||||
<label for="anonymous_no" class="">No, include my name and email address</label>
|
||||
</div>
|
||||
<div class="">
|
||||
<input type="radio" class="" id="anonymous_yes" name="anonymous" value="1" checked={($slct.archive_obj.anonymous)} required >
|
||||
<label for="anonymous_yes" class="">Yes, the post will be listed as Anonymous</label>
|
||||
</div>
|
||||
</fieldset> -->
|
||||
|
||||
<!-- <label for="external_person_id">Your ID
|
||||
<input type="text" id="external_person_id" name="external_person_id" value={$slct.archive_obj.external_person_id} readonly>
|
||||
</label>
|
||||
|
||||
<label for="full_name">Your name
|
||||
<input type="text" id="full_name" name="full_name" value={$slct.archive_obj.full_name}>
|
||||
</label>
|
||||
|
||||
<label for="email">Your email
|
||||
<input type="text" name="email" value={$slct.archive_obj.email} readonly>
|
||||
</label> -->
|
||||
|
||||
<!-- <h3>Archiveer's Options</h3> -->
|
||||
|
||||
<!-- <fieldset class="">
|
||||
<legend class="">Official or Member Archive</legend>
|
||||
<div class="">
|
||||
<input type="radio" class="" id="group_official" name="group" value="official">
|
||||
<label for="group_official" class="">Archive as Official/Leadership</label>
|
||||
</div>
|
||||
<div class="">
|
||||
<input type="radio" class="" id="group_member" name="group" value="member" checked="">
|
||||
<label for="group_member" class="">Archive as Member</label>
|
||||
</div>
|
||||
</fieldset> -->
|
||||
|
||||
<!-- <fieldset class="">
|
||||
<legend class="">Enable Comments</legend>
|
||||
<div class="">
|
||||
<input type="radio" class="" id="enable_comments_no" name="enable_comments" value="0">
|
||||
<label for="enable_comments_no" class="">No, do not allow comments</label>
|
||||
</div>
|
||||
<div class="">
|
||||
<input type="radio" class="" id="enable_comments_yes" name="enable_comments" value="1" checked>
|
||||
<label for="enable_comments_yes" class="">Yes, allow comments</label>
|
||||
</div>
|
||||
</fieldset> -->
|
||||
|
||||
|
||||
{#if $ae_app.trusted_access}
|
||||
<section class="ae_section archive__admin_options"> <!-- BEGIN: section archive__admin_options -->
|
||||
|
||||
<h3>
|
||||
Admin Options
|
||||
<button type="button" class="ae_btn ae_d_none_toggle ae_float_right ae_smallest btn btn-xs btn-info" on:click={() => {document.querySelector('.ae_d_none_content').classList.toggle('ae_fade_out'); document.querySelector('.ae_d_none_content').classList.toggle('ae_fade_in');}}><span class="fas fa-eye"></span> Show/Hide Admin</button>
|
||||
</h3>
|
||||
|
||||
<span class="ae_d_none_content ae_fade_out">
|
||||
<label>Hide
|
||||
<input
|
||||
type="checkbox"
|
||||
name="hide"
|
||||
id="hide"
|
||||
bind:checked={$slct.archive_obj.hide}
|
||||
>
|
||||
<!-- <input type="checkbox" name="hide" value={$slct.archive_obj.hide} /> -->
|
||||
</label>
|
||||
|
||||
<label>Priority
|
||||
<input
|
||||
type="checkbox"
|
||||
name="priority"
|
||||
id="priority"
|
||||
bind:checked={$slct.archive_obj.priority}
|
||||
>
|
||||
<!-- <input type="checkbox" name="priority" value={$slct.archive_obj.priority} /> -->
|
||||
</label>
|
||||
|
||||
<label>Sort <input type="number" name="sort" value={$slct.archive_obj.sort} /></label>
|
||||
|
||||
<label>Group <input type="text" name="group" value={$slct.archive_obj.group} max="100" /></label>
|
||||
|
||||
{#if $ae_app.administrator_access}
|
||||
<label>Enable
|
||||
<input
|
||||
type="checkbox"
|
||||
name="enable"
|
||||
id="enable"
|
||||
bind:checked={$slct.archive_obj.enable}
|
||||
>
|
||||
<!-- <input type="checkbox" name="enable" value={$slct.archive_obj.enable} checked={$slct.archive_obj.enable} /> -->
|
||||
</label>
|
||||
{/if}
|
||||
|
||||
<label>Internal Staff Notes
|
||||
<textarea id="notes" name="notes" class="ae_value archive__notes tinymce_editor editor_basic_200" rows="2" cols="70" value={$slct.archive_obj.notes}></textarea>
|
||||
</label>
|
||||
|
||||
</span> <!-- END: span ae_show_hide_content -->
|
||||
|
||||
</section> <!-- END: section archive__admin_options -->
|
||||
{/if}
|
||||
|
||||
|
||||
<section class="ae_section ae_options ae_row">
|
||||
<button type="submit" class="ae_btn btn btn-primary"><span class="fas fa-check"></span> Save Archive</button>
|
||||
|
||||
{#if $slct.archive_id}
|
||||
<button
|
||||
on:click={() => {
|
||||
if (!confirm('Are you sure you want to delete this archive?')) {return false;}
|
||||
handle_delete_archive_obj({archive_id: $slct.archive_id});
|
||||
|
||||
$slct.archive_id = null;
|
||||
$slct.archive_obj = {};
|
||||
}}
|
||||
class="ae_btn ae_smallest btn btn-danger" type="button">
|
||||
<span class="fas fa-minus"></span> Delete
|
||||
</button>
|
||||
{/if}
|
||||
</section>
|
||||
|
||||
</form>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<style>
|
||||
</style>
|
||||
@@ -1,384 +0,0 @@
|
||||
<script lang="ts">
|
||||
import { createEventDispatcher, onMount } from 'svelte';
|
||||
import { fade } from 'svelte/transition';
|
||||
|
||||
import { ae, api, Element_input } from 'aether_npm_lib';
|
||||
import { slct, ae_app } from './stores';
|
||||
|
||||
export let container_class_li = [];
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
let create_post_comment_obj_promise: any;
|
||||
let delete_post_comment_obj_promise: any;
|
||||
let update_post_comment_obj_promise: any;
|
||||
|
||||
let disable_submit_btn = true;
|
||||
|
||||
if ($slct.post_comment_id) {
|
||||
console.log(`Post Comment ID selected: ${$slct.post_comment_id}`);
|
||||
console.log(`Post Comment Object selected: ${$slct.post_comment_obj}`);
|
||||
} else {
|
||||
$slct.post_comment_id = null;
|
||||
$slct.post_comment_obj = {
|
||||
title: null,
|
||||
content: null,
|
||||
anonymous: false,
|
||||
external_person_id: $ae_app.novi_uuid,
|
||||
full_name: $ae_app.novi_full_name,
|
||||
email: $ae_app.novi_email,
|
||||
|
||||
sort: null,
|
||||
// notes: null,
|
||||
};
|
||||
console.log(`Post Comment Object started: ${$slct.post_comment_obj}`);
|
||||
}
|
||||
|
||||
|
||||
if ($slct.post_comment_obj) {
|
||||
|
||||
} else {
|
||||
// $slct.post_comment_obj = {name: 'null', description: 'null'};
|
||||
console.log(`Post Comment Object started: ${$slct.post_comment_obj}`)
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
console.log('** Component Mounted: ** Edit - Posts Comment Obj');
|
||||
});
|
||||
|
||||
|
||||
$: if ($slct.post_comment_obj) {
|
||||
console.log('Selected post comment object changed?');
|
||||
console.log($slct.post_comment_obj);
|
||||
|
||||
if ($slct.post_comment_obj == null) {
|
||||
$slct.post_comment_obj = {title: null, content: null, name: null, description: null, notes: null, created_on: null, updated_on: null};
|
||||
} else {
|
||||
disable_submit_btn = false;
|
||||
}
|
||||
|
||||
// ae.input_template['event']['timezone'] = 'EDT';
|
||||
}
|
||||
|
||||
|
||||
async function handle_submit_form(event) {
|
||||
console.log('*** handle_submit_form() ***');
|
||||
|
||||
disable_submit_btn = true;
|
||||
|
||||
let form_data = new FormData(event.target);
|
||||
console.log(form_data);
|
||||
|
||||
let post_comment_data = ae.util.extract_prefixed_form_data({prefix: null, form_data: form_data, trim_values: true, bool_tf_str: true, log_lvl: 0});
|
||||
|
||||
if (!$slct.post_comment_id) {
|
||||
post_comment_data['post_id_random'] = $slct.post_id;
|
||||
post_comment_data['enable'] = true;
|
||||
}
|
||||
|
||||
console.log(post_comment_data);
|
||||
|
||||
if (!$slct.post_comment_id) {
|
||||
create_post_comment_obj_promise = api.create_ae_obj_crud({
|
||||
api_cfg: $ae_app.ae_api,
|
||||
obj_type: 'post_comment',
|
||||
fields: post_comment_data,
|
||||
key: $ae_app.ae_api.api_crud_super_key,
|
||||
log_lvl: 1
|
||||
})
|
||||
.then(function (post_comment_obj_create_result) {
|
||||
if (!post_comment_obj_create_result) {
|
||||
console.log('The result was null or false.');
|
||||
return false;
|
||||
}
|
||||
|
||||
$slct.post_comment_id = post_comment_obj_create_result;
|
||||
|
||||
dispatch(
|
||||
'post_comment_obj_created',
|
||||
{
|
||||
post_comment_id: $slct.post_comment_id,
|
||||
}
|
||||
);
|
||||
|
||||
return post_comment_obj_create_result;
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log('Something went wrong.');
|
||||
console.log(error);
|
||||
return false;
|
||||
});
|
||||
|
||||
return create_post_comment_obj_promise;
|
||||
|
||||
} else {
|
||||
update_post_comment_obj_promise = api.update_ae_obj_id_crud({
|
||||
api_cfg: $ae_app.ae_api,
|
||||
obj_type: 'post_comment',
|
||||
obj_id: $slct.post_comment_id,
|
||||
fields: post_comment_data,
|
||||
key: $ae_app.ae_api.api_crud_super_key,
|
||||
log_lvl: 1
|
||||
})
|
||||
.then(function (post_comment_obj_update_result) {
|
||||
if (!post_comment_obj_update_result) {
|
||||
console.log('The result was null or false.');
|
||||
return false;
|
||||
}
|
||||
|
||||
dispatch(
|
||||
'post_comment_obj_updated',
|
||||
{
|
||||
post_comment_id: $slct.post_comment_id,
|
||||
}
|
||||
);
|
||||
|
||||
return post_comment_obj_update_result;
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log('Something went wrong.');
|
||||
console.log(error);
|
||||
return false;
|
||||
});
|
||||
|
||||
return update_post_comment_obj_promise;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async function handle_delete_post_comment_obj({post_comment_id, method='disable'}) {
|
||||
console.log('*** handle_delete_post_comment_obj() ***');
|
||||
|
||||
delete_post_comment_obj_promise = api.delete_ae_obj_id_crud({
|
||||
api_cfg: $ae_app.ae_api,
|
||||
obj_type: 'post_comment',
|
||||
obj_id: post_comment_id,
|
||||
method: method,
|
||||
// params: params,
|
||||
key: $ae_app.ae_api.api_crud_super_key,
|
||||
log_lvl: 0
|
||||
})
|
||||
.then(function (post_comment_obj_delete_result) {
|
||||
if (post_comment_obj_delete_result) {
|
||||
// console.log(`Result:`, post_comment_obj_delete_result);
|
||||
|
||||
dispatch(
|
||||
'post_comment_obj_deleted',
|
||||
{
|
||||
post_comment_id: post_comment_id,
|
||||
}
|
||||
);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log('The result was null or false when trying to delete.', error);
|
||||
});
|
||||
|
||||
return delete_post_comment_obj_promise;
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<section class="svelte_component ae_edit post_comment_obj {container_class_li.join(' ')}">
|
||||
|
||||
<form on:submit|preventDefault={handle_submit_form} class="">
|
||||
|
||||
{#await update_post_comment_obj_promise}
|
||||
<div class="awaiting alert_msg_pulse" out:fade={{ duration: 2000 }}>Saving...</div>
|
||||
{:then}
|
||||
{#if update_post_comment_obj_promise}
|
||||
<div class="awaiting" out:fade={{ duration: 2000 }}>Finished saving</div>
|
||||
{:else}
|
||||
<!-- <div class="awaiting" out:fade={{ duration: 2000 }}>Nothing here yet</div> -->
|
||||
{/if}
|
||||
{/await}
|
||||
|
||||
<h3>Post Comment</h3>
|
||||
|
||||
<!-- <label for="title">Title of BB post
|
||||
<input type="text" id="title" name="title" required max="20" value={$slct.post_comment_obj.title ? $slct.post_comment_obj.title : '' } placeholder="BB post title">
|
||||
</label> -->
|
||||
|
||||
<label for="content">Content (post comment body)
|
||||
<textarea id="content" name="content" required rows="6" cols="70" value={$slct.post_comment_obj.content ? $slct.post_comment_obj.content : ''} class="ae__post_comment__content"></textarea>
|
||||
</label>
|
||||
|
||||
<h3>Poster's Information</h3>
|
||||
<fieldset class="">
|
||||
<legend class="">Post as Anonymous</legend>
|
||||
<div class="">
|
||||
<input type="radio" class="" id="anonymous_no" name="anonymous" value="0" checked={(!$slct.post_comment_obj.anonymous)} required>
|
||||
<label for="anonymous_no" class="">No, include my name and email address</label>
|
||||
</div>
|
||||
<div class="">
|
||||
<input type="radio" class="" id="anonymous_yes" name="anonymous" value="1" checked={($slct.post_comment_obj.anonymous)} required >
|
||||
<label for="anonymous_yes" class="">Yes, the post will be listed as Anonymous</label>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
{#if $ae_app.trusted_access}
|
||||
<label for="external_person_id">Your ID
|
||||
{#if !$ae_app.trusted_access}
|
||||
<span class="fas fa-lock" title="Field is locked"></span>
|
||||
{:else}
|
||||
<span class="fas fa-unlock" title="Field is unlocked"></span>
|
||||
{/if}
|
||||
<input
|
||||
type="text"
|
||||
id="external_person_id"
|
||||
name="external_person_id"
|
||||
value={($slct.post_comment_obj.external_person_id ? $slct.post_comment_obj.external_person_id : $ae_app.novi_uuid)}
|
||||
readonly={!$ae_app.trusted_access}
|
||||
>
|
||||
<span class="ae_highlight">Primary link using the Novi API UUID</span>
|
||||
</label>
|
||||
{/if}
|
||||
|
||||
<label for="full_name">Your name
|
||||
{#if !$ae_app.trusted_access}
|
||||
<span class="fas fa-lock" title="Field is locked"></span>
|
||||
{:else}
|
||||
<span class="fas fa-unlock" title="Field is unlocked"></span>
|
||||
{/if}
|
||||
<input
|
||||
type="text"
|
||||
id="full_name"
|
||||
name="full_name"
|
||||
value={($slct.post_comment_obj.full_name ? $slct.post_comment_obj.full_name : $ae_app.novi_full_name)}
|
||||
>
|
||||
</label>
|
||||
|
||||
{#if $ae_app.trusted_access}
|
||||
<label for="email">Your email
|
||||
{#if !$ae_app.trusted_access}
|
||||
<span class="fas fa-lock" title="Field is locked"></span>
|
||||
{:else}
|
||||
<span class="fas fa-unlock" title="Field is unlocked"></span>
|
||||
{/if}
|
||||
<input
|
||||
type="text"
|
||||
name="email"
|
||||
value={($slct.post_comment_obj.email ? $slct.post_comment_obj.email : $ae_app.novi_email)}
|
||||
readonly={!$ae_app.trusted_access}
|
||||
>
|
||||
<span class="ae_highlight">Secondary link using the Novi email address</span>
|
||||
</label>
|
||||
{/if}
|
||||
|
||||
|
||||
{#if $ae_app.trusted_access}
|
||||
<section class="ae_section post_comment__admin_options"> <!-- BEGIN: section post_comment__admin_options -->
|
||||
|
||||
<h3>
|
||||
Admin Options
|
||||
<button type="button" class="ae_btn ae_d_none_toggle ae_float_right ae_smallest btn btn-xs btn-info" on:click={() => {document.querySelector('.ae_d_none_content').classList.toggle('ae_fade_out'); document.querySelector('.ae_d_none_content').classList.toggle('ae_fade_in');}}><span class="fas fa-eye"></span> Show/Hide Admin</button>
|
||||
</h3>
|
||||
|
||||
<span class="ae_d_none_content ae_fade_out">
|
||||
<label>Hide
|
||||
<input
|
||||
type="checkbox"
|
||||
name="hide"
|
||||
id="hide"
|
||||
bind:checked={$slct.post_comment_obj.hide}
|
||||
>
|
||||
</label>
|
||||
|
||||
<!-- <label>Priority
|
||||
<input
|
||||
type="checkbox"
|
||||
name="priority"
|
||||
id="priority"
|
||||
bind:checked={$slct.post_comment_obj.priority}
|
||||
>
|
||||
</label> -->
|
||||
|
||||
<!-- <label>Sort <input type="number" name="sort" value={$slct.post_comment_obj.sort} /></label> -->
|
||||
|
||||
<!-- <label>Group <input type="text" name="group" value={$slct.post_comment_obj.group} max="100" /></label> -->
|
||||
|
||||
{#if $ae_app.administrator_access}
|
||||
<label>Enable
|
||||
<input
|
||||
type="checkbox"
|
||||
name="enable"
|
||||
id="enable"
|
||||
bind:checked={$slct.post_comment_obj.enable}
|
||||
>
|
||||
</label>
|
||||
{/if}
|
||||
|
||||
<!-- {#if $ae_app.trusted_access}
|
||||
<label>Internal Staff Notes
|
||||
<textarea id="notes" name="notes" class="ae_value post__notes tinymce_editor editor_basic_200" rows="2" cols="70" value={$slct.post_comment_obj.notes}></textarea>
|
||||
</label>
|
||||
{/if} -->
|
||||
|
||||
</span> <!-- END: span ae_show_hide_content -->
|
||||
|
||||
</section> <!-- END: section post_comment__admin_options -->
|
||||
{/if}
|
||||
|
||||
|
||||
<section class="ae_section ae_options ae_row">
|
||||
<button type="submit" class="ae_btn btn btn-primary"><span class="fas fa-check"></span> Save Post Comment</button>
|
||||
|
||||
{#if $slct.post_comment_id}
|
||||
{#if $ae_app.administrator_access}
|
||||
<button
|
||||
on:click={() => {
|
||||
if (!confirm('Are you sure you want to delete this post comment?')) {return false;}
|
||||
handle_delete_post_comment_obj({post_comment_id: $slct.post_comment_id, method: 'delete'});
|
||||
|
||||
$slct.post_comment_id = null;
|
||||
$slct.post_comment_obj = {};
|
||||
}}
|
||||
class="ae_btn ae_smallest btn btn-danger" type="button"
|
||||
title="Delete record permanently"
|
||||
>
|
||||
<span class="fas fa-minus"></span> Delete
|
||||
</button>
|
||||
{:else if $ae_app.trusted_access}
|
||||
<button
|
||||
on:click={() => {
|
||||
if (!confirm('Are you sure you want to disable this post comment?')) {return false;}
|
||||
handle_delete_post_comment_obj({post_comment_id: $slct.post_comment_id, method: 'disable'});
|
||||
|
||||
$slct.post_comment_id = null;
|
||||
$slct.post_comment_obj = {};
|
||||
}}
|
||||
class="ae_btn ae_smallest btn btn-danger" type="button"
|
||||
title="Disable record to delete"
|
||||
>
|
||||
<span class="fas fa-minus"></span> Delete
|
||||
</button>
|
||||
{:else}
|
||||
<button
|
||||
on:click={() => {
|
||||
if (!confirm('Are you sure you want to hide this post comment?')) {return false;}
|
||||
handle_delete_post_comment_obj({post_comment_id: $slct.post_comment_id, method: 'hide'});
|
||||
|
||||
$slct.post_comment_id = null;
|
||||
$slct.post_comment_obj = {};
|
||||
}}
|
||||
class="ae_btn ae_smallest btn btn-danger" type="button"
|
||||
title="Hide record to delete"
|
||||
>
|
||||
<span class="fas fa-comment-slash"></span> Delete
|
||||
</button>
|
||||
{/if}
|
||||
{/if}
|
||||
</section>
|
||||
|
||||
</form>
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<style>
|
||||
.svelte_component.ae_edit {
|
||||
/* outline: dashed thin pink; */
|
||||
}
|
||||
</style>
|
||||
@@ -1,536 +0,0 @@
|
||||
<script lang="ts">
|
||||
import { createEventDispatcher, onMount } from 'svelte';
|
||||
import { fade } from 'svelte/transition';
|
||||
|
||||
import { ae, api, Element_input } from 'aether_npm_lib';
|
||||
import { slct, ae_app } from './stores';
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
type key_val = {
|
||||
[key: string]: any;
|
||||
};
|
||||
|
||||
let create_post_obj_promise: any;
|
||||
let delete_post_obj_promise: any;
|
||||
let update_post_obj_promise: any;
|
||||
|
||||
let disable_submit_btn = true;
|
||||
|
||||
if ($slct.post_id) {
|
||||
console.log(`Post ID selected: ${$slct.post_id}`);
|
||||
console.log(`Post Object selected: ${$slct.post_obj}`);
|
||||
|
||||
if ($slct.post_obj) {
|
||||
// if (!$slct.post_obj.external_person_id) {
|
||||
// $slct.post_obj['external_person_id'] = $ae_app.novi_uuid;
|
||||
// }
|
||||
// if (!$slct.post_obj.full_name) {
|
||||
// $slct.post_obj['full_name'] = $ae_app.novi_full_name;
|
||||
// }
|
||||
// if (!$slct.post_obj.email) {
|
||||
// $slct.post_obj['email'] = $ae_app.novi_email;
|
||||
// }
|
||||
}
|
||||
} else {
|
||||
$slct.post_id = null;
|
||||
$slct.post_obj = {
|
||||
title: null,
|
||||
content: null,
|
||||
topic_id: null,
|
||||
anonymous: false,
|
||||
external_person_id: $ae_app.novi_uuid,
|
||||
full_name: $ae_app.novi_full_name,
|
||||
email: $ae_app.novi_email,
|
||||
|
||||
sort: null,
|
||||
notes: null,
|
||||
};
|
||||
console.log(`Post Object started: ${$slct.post_obj}`);
|
||||
}
|
||||
|
||||
|
||||
if ($slct.post_obj) {
|
||||
|
||||
} else {
|
||||
// $slct.post_obj = {name: 'null', description: 'null'};
|
||||
console.log(`Post Object started: ${$slct.post_obj}`)
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
console.log('** Component Mounted: ** Edit - Post Obj');
|
||||
|
||||
// NOTE: Minimal version of the TinyMCE editor
|
||||
tinymce.init({
|
||||
selector: '.tinymce_editor.editor_basic_200',
|
||||
// width: 600,
|
||||
height: 200,
|
||||
plugins: [ 'lists', 'code', 'help' ],
|
||||
menubar: false,
|
||||
toolbar: 'undo redo | styles | bold italic | alignleft aligncenter | bullist numlist outdent indent | code | help',
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
// let ae_iframe_height = window.outerHeight;
|
||||
let ae_iframe_height = window.innerHeight;
|
||||
console.log(`ae_iframe_height: ${ae_iframe_height}`);
|
||||
$: if (ae_iframe_height) {
|
||||
console.log('ae_iframe_height changed:', ae_iframe_height);
|
||||
|
||||
let iframe_height = ae_iframe_height; // TESTING!!!
|
||||
|
||||
// window.parent.postMessage({'iframe_height': `${iframe_height}px`}, "*");
|
||||
window.parent.postMessage({'iframe_height': iframe_height}, "*");
|
||||
}
|
||||
|
||||
|
||||
$: if ($slct.post_obj) {
|
||||
console.log('Selected post object changed?');
|
||||
console.log($slct.post_obj);
|
||||
|
||||
if ($slct.post_obj == null) {
|
||||
$slct.post_obj = {title: null, content: null, name: null, description: null, notes: null, created_on: null, updated_on: null};
|
||||
} else {
|
||||
disable_submit_btn = false;
|
||||
}
|
||||
|
||||
// ae.input_template['event']['timezone'] = 'EDT';
|
||||
}
|
||||
|
||||
|
||||
async function handle_submit_form(event) {
|
||||
console.log('*** handle_submit_form() ***');
|
||||
// console.log(event.target);
|
||||
|
||||
disable_submit_btn = true;
|
||||
|
||||
let form_data = new FormData(event.target);
|
||||
// console.log(form_data);
|
||||
|
||||
let form_post_data = ae.util.extract_prefixed_form_data({prefix: null, form_data: form_data, trim_values: true, bool_tf_str: true, log_lvl: 2});
|
||||
// console.log(form_post_data);
|
||||
|
||||
let post_data: key_val = {};
|
||||
|
||||
if (!$slct.post_id) {
|
||||
post_data['account_id_random'] = $ae_app.account_id;
|
||||
post_data['enable'] = true;
|
||||
}
|
||||
|
||||
post_data['title'] = form_post_data.title;
|
||||
if (tinyMCE.get('content')) {
|
||||
post_data['content'] = tinyMCE.get('content').getContent();
|
||||
} else {
|
||||
post_data['content'] = form_post_data.content;
|
||||
}
|
||||
|
||||
if (form_post_data.topic_id) {
|
||||
post_data['topic_id'] = Number(form_post_data.topic_id);
|
||||
// post_data['topic_id'] = form_post_data.topic_id;
|
||||
} else {
|
||||
post_data['topic_id'] = null;
|
||||
}
|
||||
|
||||
console.log(form_post_data.anonymous);
|
||||
console.log(typeof form_post_data.anonymous);
|
||||
|
||||
// console.log(Boolean(form_post_data.anonymous));
|
||||
// console.log(Number((form_post_data.anonymous)));
|
||||
// console.log(Boolean(Number((form_post_data.anonymous))));
|
||||
// let anonymous_test = Boolean(form_post_data.anonymous)
|
||||
|
||||
// console.log(!anonymous_test);
|
||||
// console.log(!!anonymous_test);
|
||||
// console.log(!!!anonymous_test);
|
||||
|
||||
post_data['anonymous'] = form_post_data.anonymous;
|
||||
|
||||
post_data['external_person_id'] = form_post_data.external_person_id;
|
||||
post_data['full_name'] = form_post_data.full_name;
|
||||
post_data['email'] = form_post_data.email;
|
||||
|
||||
post_data['hide'] = !!form_post_data.hide;
|
||||
post_data['priority'] = !!form_post_data.priority;
|
||||
if (form_post_data.sort) {
|
||||
post_data['sort'] = Number(form_post_data.sort);
|
||||
} else {
|
||||
post_data['sort'] = null;
|
||||
}
|
||||
if (form_post_data.group) {
|
||||
post_data['group'] = form_post_data.group;
|
||||
} else {
|
||||
post_data['group'] = null;
|
||||
}
|
||||
|
||||
if (form_post_data.enable) {
|
||||
post_data['enable'] = !!form_post_data.enable;
|
||||
}
|
||||
|
||||
if (tinyMCE.get('notes')) {
|
||||
post_data['notes'] = tinyMCE.get('notes').getContent();
|
||||
} else {
|
||||
post_data['notes'] = form_post_data.notes;
|
||||
}
|
||||
|
||||
console.log(post_data);
|
||||
|
||||
if (!$slct.post_id) {
|
||||
create_post_obj_promise = api.create_ae_obj_crud({
|
||||
api_cfg: $ae_app.ae_api,
|
||||
obj_type: 'post',
|
||||
fields: post_data,
|
||||
key: $ae_app.ae_api.api_crud_super_key,
|
||||
log_lvl: 1
|
||||
})
|
||||
.then(function (post_obj_create_result) {
|
||||
if (!post_obj_create_result) {
|
||||
console.log('The result was null or false.');
|
||||
return false;
|
||||
}
|
||||
|
||||
$slct.post_id = post_obj_create_result.obj_id_random;
|
||||
|
||||
dispatch(
|
||||
'created__post_obj',
|
||||
{
|
||||
post_id: $slct.post_id,
|
||||
}
|
||||
);
|
||||
|
||||
return post_obj_create_result;
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log('Something went wrong.');
|
||||
console.log(error);
|
||||
return false;
|
||||
});
|
||||
|
||||
return create_post_obj_promise;
|
||||
|
||||
} else {
|
||||
update_post_obj_promise = api.update_ae_obj_id_crud({
|
||||
api_cfg: $ae_app.ae_api,
|
||||
obj_type: 'post',
|
||||
obj_id: $slct.post_id,
|
||||
fields: post_data,
|
||||
key: $ae_app.ae_api.api_crud_super_key,
|
||||
log_lvl: 1
|
||||
})
|
||||
.then(function (post_obj_update_result) {
|
||||
if (!post_obj_update_result) {
|
||||
console.log('The result was null or false.');
|
||||
return false;
|
||||
}
|
||||
|
||||
dispatch(
|
||||
'updated__post_obj',
|
||||
{
|
||||
post_id: $slct.post_id,
|
||||
}
|
||||
);
|
||||
|
||||
return post_obj_update_result;
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log('Something went wrong.');
|
||||
console.log(error);
|
||||
return false;
|
||||
});
|
||||
|
||||
return update_post_obj_promise;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async function handle_delete_post_obj({post_id, method='disable'}) {
|
||||
console.log('*** handle_delete_post_obj() ***');
|
||||
|
||||
delete_post_obj_promise = api.delete_ae_obj_id_crud({
|
||||
api_cfg: $ae_app.ae_api,
|
||||
obj_type: 'post',
|
||||
obj_id: post_id,
|
||||
method: method,
|
||||
// params: params,
|
||||
key: $ae_app.ae_api.api_crud_super_key,
|
||||
log_lvl: 0
|
||||
})
|
||||
.then(function (post_obj_delete_result) {
|
||||
if (post_obj_delete_result) {
|
||||
// console.log(`Result:`, post_obj_delete_result);
|
||||
|
||||
dispatch(
|
||||
'deleted__post_obj',
|
||||
{
|
||||
post_id: post_id,
|
||||
}
|
||||
);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log('The result was null or false when trying to delete.', error);
|
||||
});
|
||||
|
||||
return delete_post_obj_promise;
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<section
|
||||
class="svelte_component ae_edit post_obj"
|
||||
class:ae_create={!$slct.post_id}
|
||||
bind:clientHeight={$ae_app.iframe_height_modal_body}
|
||||
>
|
||||
|
||||
<form on:submit|preventDefault={handle_submit_form} class="">
|
||||
|
||||
{#await update_post_obj_promise}
|
||||
<div class="awaiting alert_msg_pulse" out:fade={{ duration: 2000 }}>Saving...</div>
|
||||
{:then}
|
||||
{#if update_post_obj_promise}
|
||||
<div class="awaiting" out:fade={{ duration: 2000 }}>Finished saving</div>
|
||||
{:else}
|
||||
<!-- <div class="awaiting" out:fade={{ duration: 2000 }}>Nothing here yet</div> -->
|
||||
{/if}
|
||||
{/await}
|
||||
|
||||
<h3>Post</h3>
|
||||
|
||||
<label for="title">Title of BB post
|
||||
<input type="text" id="title" name="title" required max="20" value={$slct.post_obj.title ? $slct.post_obj.title : '' } placeholder="BB post title">
|
||||
</label>
|
||||
|
||||
<label for="content">Content (post body)
|
||||
<textarea id="content" name="content" required rows="6" cols="80" value={$slct.post_obj.content ? $slct.post_obj.content : ''} class="ae_value post__content tinymce_editor editor_basic_200"></textarea>
|
||||
</label>
|
||||
|
||||
<label for="topic_id">BB post topic
|
||||
<select id="topic_id" name="topic_id" value={$slct.post_obj.topic_id}>
|
||||
<option value="">-- None --</option>
|
||||
<option value={16}>Licensing/ monitoring/ credentialing issues</option>
|
||||
<option value={17}>Return to practice</option>
|
||||
<option value={18}>Contacts/ sponsorship in my area</option>
|
||||
<option value={19}>Professional positions</option>
|
||||
<option value={21}
|
||||
disabled={!$ae_app.trusted_access}
|
||||
>
|
||||
Announcement
|
||||
</option>
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<h3>Poster's Information</h3>
|
||||
<fieldset class="">
|
||||
<legend class="">Post as Anonymous</legend>
|
||||
<div class="">
|
||||
<input
|
||||
type="radio"
|
||||
id="anonymous_no"
|
||||
name="anonymous"
|
||||
value={false}
|
||||
bind:group={$slct.post_obj.anonymous}
|
||||
|
||||
>
|
||||
<label for="anonymous_no">No, include my name and email address</label>
|
||||
</div>
|
||||
<div class="">
|
||||
<input
|
||||
type="radio"
|
||||
id="anonymous_yes"
|
||||
name="anonymous"
|
||||
value={true}
|
||||
bind:group={$slct.post_obj.anonymous}
|
||||
|
||||
>
|
||||
<label for="anonymous_yes">Yes, the post will be listed as Anonymous</label>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
{#if $ae_app.trusted_access}
|
||||
<label for="external_person_id">Your ID
|
||||
{#if !$ae_app.trusted_access}
|
||||
<span class="fas fa-lock" title="Field is locked"></span>
|
||||
{:else}
|
||||
<span class="fas fa-unlock" title="Field is unlocked"></span>
|
||||
{/if}
|
||||
<input
|
||||
type="text"
|
||||
id="external_person_id"
|
||||
name="external_person_id"
|
||||
value={($slct.post_obj.external_person_id ? $slct.post_obj.external_person_id : $ae_app.novi_uuid)}
|
||||
readonly={!$ae_app.trusted_access}
|
||||
>
|
||||
<span class="ae_highlight">Primary link using the Novi API UUID</span>
|
||||
</label>
|
||||
{/if}
|
||||
|
||||
<label for="full_name">Your name
|
||||
{#if !$ae_app.trusted_access}
|
||||
<span class="fas fa-lock" title="Field is locked"></span>
|
||||
{:else}
|
||||
<span class="fas fa-unlock" title="Field is unlocked"></span>
|
||||
{/if}
|
||||
<input
|
||||
type="text"
|
||||
id="full_name"
|
||||
name="full_name"
|
||||
value={($slct.post_obj.full_name ? $slct.post_obj.full_name : $ae_app.novi_full_name)}
|
||||
readonly={!$ae_app.trusted_access}
|
||||
>
|
||||
</label>
|
||||
|
||||
{#if $ae_app.trusted_access}
|
||||
<label for="email">Your email
|
||||
{#if !$ae_app.trusted_access}
|
||||
<span class="fas fa-lock" title="Field is locked"></span>
|
||||
{:else}
|
||||
<span class="fas fa-unlock" title="Field is unlocked"></span>
|
||||
{/if}
|
||||
<input
|
||||
type="text"
|
||||
name="email"
|
||||
value={($slct.post_obj.email ? $slct.post_obj.email : $ae_app.novi_email)}
|
||||
readonly={!$ae_app.trusted_access}
|
||||
>
|
||||
<span class="ae_highlight">Secondary link using the Novi email address</span>
|
||||
</label>
|
||||
{/if}
|
||||
|
||||
<!-- <h3>Poster's Options</h3> -->
|
||||
|
||||
<!-- <fieldset class="">
|
||||
<legend class="">Official or Member Post</legend>
|
||||
<div class="">
|
||||
<input type="radio" class="" id="group_official" name="group" value="official">
|
||||
<label for="group_official" class="">Post as Official/Leadership</label>
|
||||
</div>
|
||||
<div class="">
|
||||
<input type="radio" class="" id="group_member" name="group" value="member" checked="">
|
||||
<label for="group_member" class="">Post as Member</label>
|
||||
</div>
|
||||
</fieldset> -->
|
||||
|
||||
<!-- <fieldset class="">
|
||||
<legend class="">Enable Comments</legend>
|
||||
<div class="">
|
||||
<input type="radio" class="" id="enable_comments_no" name="enable_comments" value="0">
|
||||
<label for="enable_comments_no" class="">No, do not allow comments</label>
|
||||
</div>
|
||||
<div class="">
|
||||
<input type="radio" class="" id="enable_comments_yes" name="enable_comments" value="1" checked>
|
||||
<label for="enable_comments_yes" class="">Yes, allow comments</label>
|
||||
</div>
|
||||
</fieldset> -->
|
||||
|
||||
|
||||
{#if $ae_app.trusted_access}
|
||||
<section class="ae_section post__admin_options"> <!-- BEGIN: section post__admin_options -->
|
||||
|
||||
<h3>
|
||||
Admin Options
|
||||
<button type="button" class="ae_btn ae_d_none_toggle ae_float_right ae_smallest btn btn-xs btn-info" on:click={() => {document.querySelector('.ae_d_none_content').classList.toggle('ae_fade_out'); document.querySelector('.ae_d_none_content').classList.toggle('ae_fade_in');}}><span class="fas fa-eye"></span> Show/Hide Admin</button>
|
||||
</h3>
|
||||
|
||||
<span class="ae_d_none_content ae_fade_out">
|
||||
<label>Hide
|
||||
<input
|
||||
type="checkbox"
|
||||
name="hide"
|
||||
id="hide"
|
||||
bind:checked={$slct.post_obj.hide}
|
||||
>
|
||||
</label>
|
||||
|
||||
<label>Priority
|
||||
<input
|
||||
type="checkbox"
|
||||
name="priority"
|
||||
id="priority"
|
||||
bind:checked={$slct.post_obj.priority}
|
||||
>
|
||||
</label>
|
||||
|
||||
<label>Sort <input type="number" name="sort" value={$slct.post_obj.sort} /></label>
|
||||
|
||||
<label>Group <input type="text" name="group" value={$slct.post_obj.group} max="100" /></label>
|
||||
|
||||
{#if $ae_app.administrator_access}
|
||||
<label>Enable
|
||||
<input
|
||||
type="checkbox"
|
||||
name="enable"
|
||||
id="enable"
|
||||
bind:checked={$slct.post_obj.enable}
|
||||
>
|
||||
</label>
|
||||
{/if}
|
||||
|
||||
{#if $ae_app.trusted_access}
|
||||
<label>Internal Staff Notes
|
||||
<textarea id="notes" name="notes" class="ae_value post__notes tinymce_editor editor_basic_200" rows="2" cols="70" value={$slct.post_obj.notes}></textarea>
|
||||
</label>
|
||||
{/if}
|
||||
|
||||
</span> <!-- END: span ae_show_hide_content -->
|
||||
|
||||
</section> <!-- END: section post__admin_options -->
|
||||
{/if}
|
||||
|
||||
|
||||
<section class="ae_section ae_options ae_row">
|
||||
<button type="submit" class="ae_btn btn btn-primary"><span class="fas fa-check"></span> Save Post</button>
|
||||
|
||||
{#if $slct.post_id}
|
||||
{#if $ae_app.administrator_access}
|
||||
<button
|
||||
on:click={() => {
|
||||
if (!confirm('Are you sure you want to delete this post?')) {return false;}
|
||||
handle_delete_post_obj({post_id: $slct.post_id, method: 'delete'});
|
||||
|
||||
$slct.post_id = null;
|
||||
$slct.post_obj = {};
|
||||
}}
|
||||
class="ae_btn ae_smallest btn btn-danger" type="button"
|
||||
title="Delete record permanently"
|
||||
>
|
||||
<span class="fas fa-minus"></span> Delete
|
||||
</button>
|
||||
{:else if $ae_app.trusted_access}
|
||||
<button
|
||||
on:click={() => {
|
||||
if (!confirm('Are you sure you want to disable this post?')) {return false;}
|
||||
handle_delete_post_obj({post_id: $slct.post_id, method: 'disable'});
|
||||
|
||||
$slct.post_id = null;
|
||||
$slct.post_obj = {};
|
||||
}}
|
||||
class="ae_btn ae_smallest btn btn-danger" type="button"
|
||||
title="Disable record to delete"
|
||||
>
|
||||
<span class="fas fa-minus"></span> Disable
|
||||
</button>
|
||||
{:else}
|
||||
<button
|
||||
on:click={() => {
|
||||
if (!confirm('Are you sure you want to hide this post?')) {return false;}
|
||||
handle_delete_post_obj({post_id: $slct.post_id, method: 'hide'});
|
||||
|
||||
$slct.post_id = null;
|
||||
$slct.post_obj = {};
|
||||
}}
|
||||
class="ae_btn ae_smallest btn btn-danger" type="button"
|
||||
title="Hide record to delete"
|
||||
>
|
||||
<span class="fas fa-comment-slash"></span> Delete
|
||||
</button>
|
||||
{/if}
|
||||
{/if}
|
||||
</section>
|
||||
|
||||
</form>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<style>
|
||||
</style>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,63 +0,0 @@
|
||||
<script lang="ts">
|
||||
|
||||
// *** Import Svelte core
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
import { slct, slct_trigger, ae_app, ae_session } from './stores';
|
||||
|
||||
|
||||
onMount(() => {
|
||||
console.log('** Component Mounted: ** OSIT - AE Hub: Site Menu');
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<nav>
|
||||
{#if $ae_session.site_nav_menu}
|
||||
<ul>
|
||||
{#each Object.entries($ae_session.site_nav_menu) as [name, menu_item]}
|
||||
<li>
|
||||
<a href={menu_item.href} class={menu_item.class_li}>{@html menu_item.text}</a>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
{/if}
|
||||
</nav>
|
||||
|
||||
|
||||
<style>
|
||||
nav {
|
||||
/* outline: dashed thick red; */
|
||||
/* background-color: hsla(0, 0%, 100%, 0.85); */
|
||||
/* padding: .5em 1em; */
|
||||
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
nav ul {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
|
||||
width: 100%;
|
||||
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
}
|
||||
nav ul li {
|
||||
/* display: inline; */
|
||||
/* margin-right: 1em; */
|
||||
}
|
||||
nav ul li a {
|
||||
text-decoration: none;
|
||||
}
|
||||
nav ul li a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
nav ul li a.active {
|
||||
font-weight: bold;
|
||||
}
|
||||
nav ul li a.active:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
@@ -1,489 +0,0 @@
|
||||
<script lang="ts">
|
||||
// *** Import Svelte core
|
||||
import { onMount } from 'svelte';
|
||||
import { fade } from 'svelte/transition';
|
||||
|
||||
// *** Import Aether core variables and functions
|
||||
import { ae, api, Element_modal_v3 } from 'aether_npm_lib';
|
||||
import { slct, ae_app, slct_trigger } from './stores';
|
||||
|
||||
import Edit_archive_content_obj from './10_edit__archive_content_obj.svelte';
|
||||
import Player_archive_content_obj from './10_player__archive_content_obj.svelte';
|
||||
|
||||
let idaa_archive_content_obj_li_get_promise: Promise<any>;
|
||||
let idaa_archive_content_obj_get_promise: Promise<any>;
|
||||
|
||||
let file_icons:any = {}
|
||||
file_icons['ac3'] = 'file-audio';
|
||||
file_icons['aac'] = 'file-audio';
|
||||
file_icons['csv'] = 'file-csv';
|
||||
file_icons['doc'] = 'file-word';
|
||||
file_icons['docx'] = 'file-word';
|
||||
file_icons['gif'] = 'file-image';
|
||||
file_icons['htm'] = 'file-code';
|
||||
file_icons['html'] = 'file-code';
|
||||
file_icons['jpeg'] = 'file-image';
|
||||
file_icons['jpg'] = 'file-image';
|
||||
file_icons['key'] = 'file-powerpoint';
|
||||
file_icons['mkv'] = 'file-video';
|
||||
file_icons['mov'] = 'file-video';
|
||||
file_icons['mp3'] = 'file-audio';
|
||||
file_icons['mp4'] = 'file-video';
|
||||
file_icons['pdf'] = 'file-pdf';
|
||||
file_icons['png'] = 'file-image';
|
||||
file_icons['ppt'] = 'file-powerpoint';
|
||||
file_icons['pptx'] = 'file-powerpoint';
|
||||
file_icons['txt'] = 'file-alt';
|
||||
file_icons['wav'] = 'file-audio';
|
||||
file_icons['webp'] = 'file-image';
|
||||
file_icons['xls'] = 'file-excel';
|
||||
file_icons['xlsx'] = 'file-excel';
|
||||
file_icons['zip'] = 'file-archive';
|
||||
|
||||
let media_play_extension_li = ['m4a', 'mp4', 'mp3'];
|
||||
|
||||
onMount(() => {
|
||||
console.log('** Component Mounted: ** List - Archive Content Obj Li');
|
||||
});
|
||||
|
||||
$: if ($slct_trigger == 'load__archive_content_obj_li' && $slct.archive_id) {
|
||||
$slct_trigger = null;
|
||||
|
||||
handle_load_archive_content_obj_li({archive_id: $slct.archive_id, try_cache: false});
|
||||
}
|
||||
|
||||
async function handle_load_archive_content_obj_li({archive_id, try_cache=false}) {
|
||||
console.log('*** handle_load_archive_content_obj_li() ***');
|
||||
|
||||
let enabled = $ae_app.archives.enabled;
|
||||
let hidden = $ae_app.archives.hidden;
|
||||
let limit = $ae_app.archives.limit;
|
||||
let offset = $ae_app.archives.offset;
|
||||
// $ae_app.archives.content_group_sort = 'DESC'; // 'ASC' or 'DESC'
|
||||
let group_sort = $ae_app.archives.content_group_sort; // 'ASC' or 'DESC'
|
||||
|
||||
let params = {};
|
||||
|
||||
idaa_archive_content_obj_li_get_promise = api.get_ae_obj_li_for_obj_id_crud({
|
||||
api_cfg: $ae_app.ae_api,
|
||||
obj_type: 'archive_content',
|
||||
for_obj_type: 'archive',
|
||||
for_obj_id: archive_id,
|
||||
enabled: enabled,
|
||||
hidden: hidden,
|
||||
order_by_li: {'group': group_sort, 'priority': 'DESC', 'sort': 'DESC', 'name': 'ASC', 'created_on': 'DESC', 'updated_on': 'DESC'},
|
||||
limit: limit,
|
||||
offset: offset,
|
||||
params_json: null,
|
||||
params: params,
|
||||
log_lvl: 0
|
||||
})
|
||||
.then(function (archive_content_obj_li_get_result) {
|
||||
if (archive_content_obj_li_get_result) {
|
||||
$slct.archive_content_obj_li = archive_content_obj_li_get_result;
|
||||
console.log(`Archive Content list:`, $slct.archive_content_obj_li);
|
||||
|
||||
// console.log(ae.dynamic_sort());
|
||||
// $slct.archive_content_obj_li.sort(ae.util.dynamic_sort_multiple('group ASC', 'created_on DESC', 'updated_on DESC'));
|
||||
} else {
|
||||
$slct.archive_content_obj_li = [];
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log('No results returned or failed.', error);
|
||||
});
|
||||
|
||||
return idaa_archive_content_obj_li_get_promise;
|
||||
}
|
||||
|
||||
|
||||
$: if ($slct_trigger == 'load__archive_content_obj' && $slct.archive_content_id) {
|
||||
$slct_trigger = null;
|
||||
|
||||
handle_load_archive_content_obj({archive_content_id: $slct.archive_content_id, try_cache: false});
|
||||
}
|
||||
|
||||
|
||||
async function handle_load_archive_content_obj({archive_content_id, try_cache=false}) {
|
||||
console.log('*** handle_load_archive_content_obj() ***');
|
||||
|
||||
let params = {};
|
||||
|
||||
idaa_archive_content_obj_get_promise = api.get_ae_obj_id_crud({
|
||||
api_cfg: $ae_app.ae_api,
|
||||
obj_type: 'archive_content',
|
||||
obj_id: archive_content_id,
|
||||
use_alt_table: false, // NOTE: This will use the table_name_alt value instead of the table_name value in the API config.
|
||||
use_alt_base: false, // NOTE: This will use the base_name_alt value instead of the base_name value in the API config.
|
||||
params: params,
|
||||
log_lvl: 0
|
||||
})
|
||||
.then(function (archive_content_obj_get_result) {
|
||||
if (archive_content_obj_get_result) {
|
||||
$slct.archive_content_obj = archive_content_obj_get_result;
|
||||
console.log(`Archive object:`, $slct.archive_content_obj);
|
||||
}
|
||||
|
||||
// handle_resize_document();
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log('No results returned or failed.', error);
|
||||
});
|
||||
|
||||
return idaa_archive_content_obj_get_promise;
|
||||
}
|
||||
|
||||
function handle_created_archive_content_obj(event) {
|
||||
console.log('*** handle_created_archive_content_obj() ***');
|
||||
console.log(event.detail);
|
||||
|
||||
$slct_trigger = 'load__archive_content_obj_li';
|
||||
|
||||
$ae_app.archives.show_list__event_obj_li = true;
|
||||
$ae_app.archives.show_edit__archive_content_id = false;
|
||||
$ae_app.archives.show_view__archive_content_id = false;
|
||||
}
|
||||
|
||||
function handle_updated_archive_content_obj(event) {
|
||||
console.log('*** handle_updated_archive_content_obj() ***');
|
||||
console.log(event.detail);
|
||||
|
||||
$slct_trigger = 'load__archive_content_obj_li';
|
||||
|
||||
$ae_app.archives.show_list__event_obj_li = true;
|
||||
$ae_app.archives.show_edit__archive_content_id = false;
|
||||
$ae_app.archives.show_view__archive_content_id = false;
|
||||
}
|
||||
|
||||
function handle_deleted_archive_content_obj(event) {
|
||||
console.log('*** handle_deleted_archive_content_obj() ***');
|
||||
console.log(event.detail);
|
||||
|
||||
$slct_trigger = 'load__archive_content_obj_li';
|
||||
|
||||
$ae_app.archives.show_list__event_obj_li = true;
|
||||
$ae_app.archives.show_edit__archive_content_id = false;
|
||||
$ae_app.archives.show_view__archive_content_id = false;
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<section class="svelte_component ae_section ae_list archive_content_obj_li list__archive_content_obj">
|
||||
{#if $slct.archive_content_obj_li}
|
||||
|
||||
{#each $slct.archive_content_obj_li as idaa_archive_content_obj, index}
|
||||
<!-- {#each $slct.archive_content_obj_li.sort(ae.util.dynamic_sort_multiple('group ASC', 'priority DESC')) as idaa_archive_content_obj, index} -->
|
||||
{#if idaa_archive_content_obj.group && idaa_archive_content_obj.group != $slct.archive_content_obj_li[index - 1]?.group}
|
||||
<div class="ae_row archive_content__group">
|
||||
<button
|
||||
class="ae_btn btn btn-info ae_margin_sm"
|
||||
on:click={() => {
|
||||
if ($ae_app.archives.show_list__archive_content_li_group == idaa_archive_content_obj.group) {
|
||||
$ae_app.archives.show_list__archive_content_li_group = null;
|
||||
} else {
|
||||
$ae_app.archives.show_list__archive_content_li_group = idaa_archive_content_obj.group;
|
||||
}
|
||||
}}
|
||||
>
|
||||
{#if $ae_app.archives.show_list__archive_content_li_group == idaa_archive_content_obj.group}
|
||||
<span class="fas fa-caret-down" in:fade={{ duration: 250 }}
|
||||
out:fade={{ duration: 0 }}></span>
|
||||
<!-- <span class="fas fa-minus"></span> -->
|
||||
<span class="ae_label">Hide:</span>
|
||||
{:else}
|
||||
<span class="fas fa-caret-right" in:fade={{ duration: 250 }}
|
||||
out:fade={{ duration: 0 }}></span>
|
||||
<!-- <span class="fas fa-plus"></span> -->
|
||||
<span class="ae_label">Show:</span>
|
||||
{/if}
|
||||
<!-- <span class="fas fa-caret-down"></span> -->
|
||||
<!-- <span class="ae_label">Show:</span> -->
|
||||
<span class="ae_value">{idaa_archive_content_obj.group}</span>
|
||||
</button>
|
||||
</div>
|
||||
{/if}
|
||||
{#if $ae_app.archives.show_list__archive_content_li_group == idaa_archive_content_obj.group}
|
||||
<!-- class:ae_d_none={$ae_app.archives.show_list__archive_content_li_group != idaa_archive_content_obj.group} -->
|
||||
<div
|
||||
id={`idaa_archive_content_id__${idaa_archive_content_obj.archive_content_id_random}`}
|
||||
class="container archive_content ae_object archive_content_obj"
|
||||
class:archive__content_type={idaa_archive_content_obj.type}
|
||||
|
||||
in:fade={{ duration: 125 }}
|
||||
out:fade={{ duration: 250 }}
|
||||
>
|
||||
|
||||
<header class="ae_header archive_content__header">
|
||||
<h3>
|
||||
<span class="archive_content__name">{idaa_archive_content_obj.name}</span>
|
||||
|
||||
{#if idaa_archive_content_obj.type}<span class="badge badge-info bg-info"><span class="fas fa-user-md"></span> {idaa_archive_content_obj.type}</span>{/if}
|
||||
|
||||
{#if $ae_app.trusted_access && idaa_archive_content_obj.hide}<span class="badge badge-warning"><span class="fas fa-exclamation-triangle"></span> Hidden</span>{/if}
|
||||
{#if $ae_app.administrator_access && !idaa_archive_content_obj.enable}<span class="badge badge-warning"><span class="fas fa-exclamation-triangle"></span> Not enabled</span>{/if}
|
||||
</h3>
|
||||
</header>
|
||||
|
||||
<section class="ae_options archive_content_obj__options">
|
||||
{#if idaa_archive_content_obj.archive_content_id_random != $ae_app.archives.show_view__archive_content_media}
|
||||
<button
|
||||
on:click={ () => {
|
||||
$slct.archive_content_id = idaa_archive_content_obj.archive_content_id_random;
|
||||
$slct.archive_content_obj = idaa_archive_content_obj;
|
||||
$ae_app.archives.show_view__archive_content_media = $slct.archive_content_id;
|
||||
// idaa_archive_content_obj.show_view__archive_content_media = true;
|
||||
}}
|
||||
class="ae_btn btn_md btn btn-md btn-primary"
|
||||
title="Open this file">
|
||||
{#if media_play_extension_li.includes( idaa_archive_content_obj.file_extension)}
|
||||
<span class="fas fa-play"></span>
|
||||
Play <!-- This really should check the file type: view, show, play, listen, watch -->
|
||||
{:else}
|
||||
<span class="fas fa-eye"></span>
|
||||
View
|
||||
{/if}
|
||||
<span class="badge">
|
||||
{#if file_icons[idaa_archive_content_obj.file_extension]}
|
||||
<span class="fas fa-{file_icons[idaa_archive_content_obj.file_extension]}"></span>
|
||||
{:else}
|
||||
<span class="fas fa-file"></span>
|
||||
{/if}
|
||||
.{idaa_archive_content_obj.file_extension}</span>
|
||||
</button>
|
||||
{:else}
|
||||
<button
|
||||
on:click={ () => {
|
||||
$slct.archive_content_id = idaa_archive_content_obj.archive_content_id_random;
|
||||
$slct.archive_content_obj = idaa_archive_content_obj;
|
||||
|
||||
$ae_app.archives.show_view__archive_content_media = false;
|
||||
// idaa_archive_content_obj.show_view__archive_content_media = false;
|
||||
}}
|
||||
class="ae_btn btn_md btn btn-md btn-secondary"
|
||||
title="Hide this file">
|
||||
<span class="fas fa-play"></span>
|
||||
Hide <!-- This really should check the file type: view, show, play, listen, watch -->
|
||||
<span class="badge">
|
||||
{#if file_icons[idaa_archive_content_obj.file_extension]}
|
||||
<span class="fas fa-{file_icons[idaa_archive_content_obj.file_extension]}"></span>
|
||||
{:else}
|
||||
<span class="fas fa-file"></span>
|
||||
{/if}
|
||||
.{idaa_archive_content_obj.file_extension}</span>
|
||||
</button>
|
||||
{/if}
|
||||
|
||||
{#if $ae_app.trusted_access}
|
||||
<a href="{$ae_app.app.base_url}{idaa_archive_content_obj.hosted_file_path}" class="ae_btn btn_md btn btn-md btn-secondary" title="Download this file">
|
||||
<span class="fas fa-download"></span>
|
||||
Download <!-- This really should check the file type: view, show, play, listen, watch -->
|
||||
<span class="badge">
|
||||
{#if file_icons[idaa_archive_content_obj.file_extension]}
|
||||
<span class="fas fa-{file_icons[idaa_archive_content_obj.file_extension]}"></span>
|
||||
{:else}
|
||||
<span class="fas fa-file"></span>
|
||||
{/if}
|
||||
.{idaa_archive_content_obj.file_extension}</span>
|
||||
</a>
|
||||
{/if}
|
||||
|
||||
{#if $ae_app.trusted_access}
|
||||
<button
|
||||
on:click={() => {
|
||||
$slct.archive_content_id = idaa_archive_content_obj.archive_content_id_random;
|
||||
$slct.archive_content_obj = idaa_archive_content_obj;
|
||||
$slct_trigger = 'load__archive_content_obj';
|
||||
|
||||
// const url = new URL(location);
|
||||
// url.searchParams.set('archive_content_id', idaa_archive_content_obj.archive_content_id_random);
|
||||
// history.pushState({}, '', url);
|
||||
|
||||
// $ae_app.archives.show_main__options = true;
|
||||
// $ae_app.archives.show_list__archive_content_li = true;
|
||||
// $ae_app.archives.show_view__archive_content_id = false;
|
||||
$ae_app.archives.show_view__archive_content_media = false;
|
||||
$ae_app.archives.show_edit__archive_content_id = true;
|
||||
}}
|
||||
class="ae_btn ae_smallest btn btn-warning"
|
||||
title={`Edit content: ${idaa_archive_content_obj.name}`}
|
||||
>
|
||||
<span class="fas fa-edit"></span> Edit Content
|
||||
</button>
|
||||
<!-- <button
|
||||
on:click={() => {
|
||||
// Copy URL to clipboard
|
||||
// Is there a URL anymore?
|
||||
// const copy_text = document.getElementById(`archive_edit_url_${idaa_archive_content_obj.archive_content_id_random}`);
|
||||
}}
|
||||
class="ae_btn btn_sm btn_outline_info archive_edit_help"
|
||||
>
|
||||
<span class="fas fa-link"></span> URL
|
||||
</button> -->
|
||||
{/if}
|
||||
</section>
|
||||
|
||||
|
||||
<!-- Doing some checks before the media player/viewer shows. The player should be the only one showing. So there is a sort of global check first. -->
|
||||
{#if idaa_archive_content_obj.archive_content_id_random == $ae_app.archives.show_view__archive_content_media}
|
||||
<Player_archive_content_obj archive_content_id={idaa_archive_content_obj.archive_content_id_random} />
|
||||
{/if}
|
||||
|
||||
|
||||
<section class="ae_section archive_content__content">
|
||||
{#if idaa_archive_content_obj.description}
|
||||
<div
|
||||
class="archive_content__description ae_description"
|
||||
>
|
||||
<div class="ae_label archive_content__description">Description:</div>
|
||||
<div class="ae_value archive_content__description">
|
||||
{idaa_archive_content_obj.description}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if idaa_archive_content_obj.content_html}
|
||||
<div
|
||||
class="archive_content__content_html ae_content_html"
|
||||
>
|
||||
<div class="ae_label archive_content__content_html">Content:</div>
|
||||
<div class="ae_value archive_content__content_html">
|
||||
{@html idaa_archive_content_obj.content_html}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div
|
||||
class="ae_group"
|
||||
class:ae_d_none={!idaa_archive_content_obj.original_datetime && !idaa_archive_content_obj.original_timezone}
|
||||
>
|
||||
<span class="ae_label">Original date/time:</span>
|
||||
{#if idaa_archive_content_obj.original_datetime}
|
||||
<span class="ae_value ae_prop prop_original_datetime fs_smaller">{ae.util.iso_datetime_formatter(idaa_archive_content_obj.original_datetime, 'datetime_long')}</span>
|
||||
{/if}
|
||||
{#if idaa_archive_content_obj.original_timezone}
|
||||
<span class="ae_label">Timezone:</span>
|
||||
<span class="ae_value">{idaa_archive_content_obj.original_timezone}</span>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<section
|
||||
class="ae_section ae_footer ae_meta archive_content__meta"
|
||||
class:ae_d_none={!$ae_app.administrator_access}
|
||||
>
|
||||
<span
|
||||
class="archive_content__archive_content_type"
|
||||
class:ae_d_none={!idaa_archive_content_obj.archive_content_type}
|
||||
>
|
||||
Type: {idaa_archive_content_obj.archive_content_type}
|
||||
</span>
|
||||
<span class="ae_group">
|
||||
<span
|
||||
class="archive_content__created_on"
|
||||
>
|
||||
Created on: {ae.util.iso_datetime_formatter(idaa_archive_content_obj.created_on, 'datetime_short')}
|
||||
</span>
|
||||
<span
|
||||
class="archive_content__updated_on"
|
||||
class:ae_d_none={!idaa_archive_content_obj.updated_on}
|
||||
>
|
||||
Updated on: {ae.util.iso_datetime_formatter(idaa_archive_content_obj.updated_on, 'datetime_short')}
|
||||
</span>
|
||||
</span>
|
||||
</section>
|
||||
</div>
|
||||
{/if}
|
||||
{/each}
|
||||
|
||||
{:else}
|
||||
<div>No archives avalible to show at this time</div>
|
||||
{/if}
|
||||
</section>
|
||||
|
||||
|
||||
{#if $ae_app.archives.show_edit__archive_content_id}
|
||||
<!-- <section class="ae_edit archive_content_obj archive_content_id idaa_archive_content_id_edit"> -->
|
||||
<Element_modal_v3
|
||||
show = { true }
|
||||
modal_cover_body = { false }
|
||||
on:close={ () => {
|
||||
$slct.archive_content_id = null;
|
||||
$slct.archive_content_obj = {};
|
||||
|
||||
// $ae_app.archives.show_main__options = true;
|
||||
// $ae_app.archives.show_list__archive_content_li = true;
|
||||
$ae_app.archives.show_view__archive_content_media = false;
|
||||
$ae_app.archives.show_edit__archive_content_id = false;
|
||||
// $ae_app.archives.show_view__archive_content_id = false;
|
||||
|
||||
const url = new URL(location);
|
||||
url.searchParams.delete('archive_content_id');
|
||||
history.pushState({}, '', url);
|
||||
|
||||
let message = {'archive_content_id': null};
|
||||
window.parent.postMessage(message, "*");
|
||||
}}
|
||||
>
|
||||
<span slot="header_title">{@html ($slct.archive_content_obj.name ? $slct.archive_content_obj.name : 'New Archive Content')}</span>
|
||||
|
||||
<span slot="body">
|
||||
|
||||
<Edit_archive_content_obj
|
||||
on:created__archive_content_obj={handle_created_archive_content_obj}
|
||||
on:updated__archive_content_obj={handle_updated_archive_content_obj}
|
||||
on:deleted__archive_content_obj={handle_deleted_archive_content_obj}
|
||||
/>
|
||||
|
||||
</span>
|
||||
</Element_modal_v3>
|
||||
<!-- </section> -->
|
||||
{/if}
|
||||
|
||||
|
||||
<style>
|
||||
.ae_label {
|
||||
font-size: smaller;
|
||||
}
|
||||
.ae_value {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.ae_header h3 {
|
||||
font-size: 1.2em;
|
||||
margin: 0;
|
||||
/* padding: 0; */
|
||||
}
|
||||
|
||||
.ae_row.archive_content__group {
|
||||
width: 100%;
|
||||
}
|
||||
.ae_row.archive_content__group button {
|
||||
width: 100%;
|
||||
}
|
||||
.ae_value.archive_content__group {
|
||||
font-size: 1.4em;
|
||||
font-weight: bold;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
text-align: center;
|
||||
|
||||
border-bottom: solid thin black;
|
||||
}
|
||||
|
||||
.archive_content_obj .ae_meta {
|
||||
flex-direction: column;
|
||||
/* justify-content: space-between; */
|
||||
}
|
||||
|
||||
.archive_content_obj .ae_meta .ae_group {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.archive_content_obj .ae_meta .ae_options {
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
}
|
||||
</style>
|
||||
@@ -1,151 +0,0 @@
|
||||
<script lang="ts">
|
||||
// *** Import Svelte core
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
// *** Import Aether core variables and functions
|
||||
import { ae } from 'aether_npm_lib';
|
||||
import { slct, ae_app, slct_trigger } from './stores';
|
||||
|
||||
onMount(() => {
|
||||
console.log('** Component Mounted: ** List - Archive Obj Li');
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<section class="svelte_component ae_section ae_list archive_obj_li list__archive_obj archive_list">
|
||||
{#if $slct.archive_obj_li}
|
||||
|
||||
{#each $slct.archive_obj_li as idaa_archive_obj, index}
|
||||
<div
|
||||
id={`idaa_archive_id__${idaa_archive_obj.archive_id_random}`}
|
||||
class="archive ae_object archive_obj"
|
||||
>
|
||||
|
||||
<div class="ae_header archive__header">
|
||||
<span class="archive__name">{idaa_archive_obj.name}</span>
|
||||
{#if idaa_archive_obj.original_location}
|
||||
<span>(
|
||||
<!-- <span class="ae_label">Location:</span> -->
|
||||
<span class="ae_value">{idaa_archive_obj.original_location}</span>
|
||||
)
|
||||
</span>
|
||||
{/if}
|
||||
|
||||
{#if $ae_app.trusted_access && idaa_archive_obj.hide}<span class="badge badge-warning"><span class="fas fa-exclamation-triangle"></span> Hidden</span>{/if}
|
||||
{#if $ae_app.administrator_access && !idaa_archive_obj.enable}<span class="badge badge-warning"><span class="fas fa-exclamation-triangle"></span> Not enabled</span>{/if}
|
||||
</div>
|
||||
|
||||
<div class="ae_options archive_obj__options">
|
||||
<button
|
||||
on:click={() => {
|
||||
$slct.archive_id = idaa_archive_obj.archive_id_random;
|
||||
$slct.archive_obj = idaa_archive_obj;
|
||||
$ae_app.archives.content_group_sort = $slct.archive_obj.cfg_json.content_group_sort;
|
||||
$slct_trigger = 'load__archive_obj';
|
||||
|
||||
$ae_app.archives.show_main__options = true;
|
||||
$ae_app.archives.show_list__archive_obj_li = false;
|
||||
$ae_app.archives.show_view__archive_obj = true;
|
||||
$ae_app.archives.show_edit__archive_obj = false;
|
||||
}}
|
||||
class="btn btn-secondary"
|
||||
title={`View: ${idaa_archive_obj.name}`}
|
||||
>
|
||||
<span class="fas fa-envelope-open"></span> Open
|
||||
</button>
|
||||
|
||||
{#if $ae_app.trusted_access}
|
||||
<button
|
||||
on:click={() => {
|
||||
$slct.archive_id = idaa_archive_obj.archive_id_random;
|
||||
$slct.archive_obj = idaa_archive_obj;
|
||||
$slct_trigger = 'load__archive_obj';
|
||||
|
||||
// $ae_app.archives.show_main__options = true;
|
||||
// $ae_app.archives.show_list__archive_obj_li = true;
|
||||
$ae_app.archives.show_view__archive_obj = false;
|
||||
$ae_app.archives.show_edit__archive_obj = true;
|
||||
}}
|
||||
class="ae_btn ae_smallest btn btn-warning"
|
||||
title={`Edit archive: ${idaa_archive_obj.name}`}
|
||||
>
|
||||
<span class="fas fa-edit"></span> Edit Archive
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
|
||||
<section class="ae_section archive__content">
|
||||
<div
|
||||
class="archive_description description"
|
||||
>
|
||||
<!-- <div class="ae_label archive__description">Description:</div> -->
|
||||
<div class="ae_value archive__description">
|
||||
{@html idaa_archive_obj.description}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
<section class="ae_section ae_footer ae_meta archive__meta">
|
||||
<div class="ae_group">
|
||||
{#if !idaa_archive_obj.updated_on}
|
||||
<span
|
||||
class="archive__created_on"
|
||||
>
|
||||
<span class="ae_label">Created on:</span>
|
||||
<span class="ae_value">{ae.util.iso_datetime_formatter(idaa_archive_obj.created_on, 'datetime_short')}</span>
|
||||
</span>
|
||||
{:else}
|
||||
<span
|
||||
class="archive__updated_on"
|
||||
>
|
||||
<span class="ae_label">Updated on:</span>
|
||||
<span class="ae_value">{ae.util.iso_datetime_formatter(idaa_archive_obj.updated_on, 'datetime_short')}</span>
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
{/each}
|
||||
|
||||
{:else}
|
||||
<div>No archives avalible to show at this time</div>
|
||||
{/if}
|
||||
</section>
|
||||
|
||||
|
||||
<style>
|
||||
.archive_obj {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: 1em;
|
||||
}
|
||||
|
||||
.archive__name {
|
||||
font-size: 1.5em;
|
||||
font-weight: bold;
|
||||
}
|
||||
.archive__content {
|
||||
display: none;
|
||||
}
|
||||
.archive__meta {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.archive_obj .ae_meta {
|
||||
flex-direction: column;
|
||||
/* justify-content: space-between; */
|
||||
}
|
||||
|
||||
.archive_obj .ae_meta .ae_group {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.archive_obj .ae_meta .ae_options {
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
}
|
||||
</style>
|
||||
@@ -1,163 +0,0 @@
|
||||
<script lang="ts">
|
||||
// *** Import Svelte core
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
// *** Import Aether core variables and functions
|
||||
import { ae } from 'aether_npm_lib';
|
||||
import { slct, ae_app, slct_trigger } from './stores';
|
||||
|
||||
export let container_class_li = [];
|
||||
|
||||
onMount(() => {
|
||||
console.log('** Component Mounted: ** List - Sponsorships Obj');
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<section class="svelte_component ae_section ae_list list__sponsorship_obj sponsorship_obj_li {container_class_li.join(' ')}">
|
||||
{#if $slct.sponsorship_obj_li}
|
||||
<table class="ae_table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Options</th>
|
||||
<th>Name</th> <!-- This is the name of the organization or person -->
|
||||
<th>Level</th>
|
||||
<th>Paid</th>
|
||||
<th>Guests</th>
|
||||
<th>
|
||||
<!-- Show what POC (Point of Contact) stands for when hovering -->
|
||||
<abbr title="Point of Contact" class="ae_label">POC</abbr>
|
||||
</th>
|
||||
<th>Created</th>
|
||||
<th>Updated</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each $slct.sponsorship_obj_li as ae_sponsorship_obj, index}
|
||||
<tr
|
||||
id={`ae_sponsorship_id__${ae_sponsorship_obj.sponsorship_id_random}`}
|
||||
class="ae_object sponsorship_obj"
|
||||
>
|
||||
|
||||
<td class="ae_options sponsorship_obj__options">
|
||||
<button
|
||||
on:click={() => {
|
||||
$slct.sponsorship_id = ae_sponsorship_obj.sponsorship_id_random;
|
||||
$slct.sponsorship_obj = ae_sponsorship_obj;
|
||||
$slct_trigger = 'load__sponsorship_obj';
|
||||
|
||||
$ae_app.sponsorships.show_main__options = true;
|
||||
$ae_app.sponsorships.show_list__sponsorship_obj_li = true;
|
||||
$ae_app.sponsorships.show_view__sponsorship_obj = true;
|
||||
$ae_app.sponsorships.show_edit__sponsorship_obj = false;
|
||||
}}
|
||||
class="ae_btn btn_primary"
|
||||
title={`Open to see details: ${ae_sponsorship_obj.name}`}
|
||||
>
|
||||
<span class="fas fa-envelope-open"></span>
|
||||
<!-- <span class="fas fa-info-circle"></span> -->
|
||||
View
|
||||
</button>
|
||||
|
||||
{#if $ae_app.administrator_access}
|
||||
<button
|
||||
on:click={() => {
|
||||
$slct.sponsorship_id = ae_sponsorship_obj.sponsorship_id_random;
|
||||
$slct.sponsorship_obj = ae_sponsorship_obj;
|
||||
$slct_trigger = 'load__sponsorship_obj';
|
||||
|
||||
// $ae_app.sponsorships.show_main__options = true;
|
||||
// $ae_app.sponsorships.show_list__sponsorship_obj_li = true;
|
||||
$ae_app.sponsorships.show_view__sponsorship_obj = false;
|
||||
$ae_app.sponsorships.show_edit__sponsorship_obj = true;
|
||||
}}
|
||||
class="ae_btn btn_secondary"
|
||||
title={`Edit meeting: ${ae_sponsorship_obj.name}`}
|
||||
>
|
||||
<span class="fas fa-edit"></span> Edit
|
||||
</button>
|
||||
{/if}
|
||||
</td>
|
||||
|
||||
<td class="ae_value sponsorships__name">{ae_sponsorship_obj.name}</td>
|
||||
|
||||
<td class="">
|
||||
<span class="fas fa-gem"></span>
|
||||
{#if ae_sponsorship_obj.level_num}{ae_sponsorship_obj.level_num}{/if}
|
||||
{#if ae_sponsorship_obj.level_str}{ae_sponsorship_obj.level_str}{/if}
|
||||
</td>
|
||||
|
||||
<td>
|
||||
{#if ae_sponsorship_obj.paid}
|
||||
<!-- Show checkmark -->
|
||||
<span class="fas fa-check"
|
||||
title="Paid"></span>
|
||||
{:else}
|
||||
<!-- Show X or cross -->
|
||||
<span class="fas fa-times"
|
||||
title="Not Paid"></span>
|
||||
{/if}
|
||||
{#if ae_sponsorship_obj.amount}
|
||||
<span class="ae_value sponsorships__amount">${ae_sponsorship_obj.amount}</span>
|
||||
{/if}
|
||||
</td>
|
||||
|
||||
<td>
|
||||
{#if ae_sponsorship_obj.guest_li_json}
|
||||
<span class="fas fa-list-ol"></span> {ae_sponsorship_obj.guest_li_json.length}
|
||||
{:else}
|
||||
<!-- <span class="fas fa-list-ol"></span> -->
|
||||
-- None --
|
||||
{/if}
|
||||
</td>
|
||||
|
||||
<td><span class="ae_flex ae_flex_justify_around">
|
||||
{#if ae_sponsorship_obj.poc_json}
|
||||
<span>
|
||||
<span class="fas fa-user"></span> {ae_sponsorship_obj.poc_json.given_name} {ae_sponsorship_obj.poc_json.family_name}
|
||||
</span>
|
||||
<a href="mailto:{ae_sponsorship_obj.poc_json.email}"><span class="fas fa-envelope"></span> {ae_sponsorship_obj.poc_json.email}</a>
|
||||
{/if}
|
||||
</span></td>
|
||||
|
||||
<td>{ae.util.iso_datetime_formatter(ae_sponsorship_obj.created_on, 'datetime_short')}</td>
|
||||
<td>{ae.util.iso_datetime_formatter(ae_sponsorship_obj.updated_on, 'datetime_short')}</td>
|
||||
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
{:else}
|
||||
<div>No sponsorships avalible to show at this time</div>
|
||||
{/if}
|
||||
</section>
|
||||
|
||||
|
||||
<style>
|
||||
.ae_label {
|
||||
font-size: smaller;
|
||||
}
|
||||
.ae_value {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.ae_header h3 {
|
||||
font-size: 1.2em;
|
||||
margin: 0;
|
||||
/* padding: 0; */
|
||||
}
|
||||
|
||||
.sponsorship_obj .ae_meta {
|
||||
flex-direction: column;
|
||||
/* justify-content: space-between; */
|
||||
}
|
||||
|
||||
.sponsorship_obj .ae_meta .ae_group {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.sponsorship_obj .ae_meta .ae_options {
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
}
|
||||
</style>
|
||||
@@ -1,78 +0,0 @@
|
||||
<script lang="ts">
|
||||
import { createEventDispatcher, onMount } from 'svelte';
|
||||
import { fade } from 'svelte/transition';
|
||||
|
||||
// import { ae, Element_modal_v3 } from 'aether_npm_lib';
|
||||
import { slct, slct_trigger, ae_app } from './stores';
|
||||
|
||||
// export let archive_content_id = null;
|
||||
|
||||
let file_icons:any = {}
|
||||
file_icons['ac3'] = 'file-audio';
|
||||
file_icons['aac'] = 'file-audio';
|
||||
file_icons['csv'] = 'file-csv';
|
||||
file_icons['doc'] = 'file-word';
|
||||
file_icons['docx'] = 'file-word';
|
||||
file_icons['gif'] = 'file-image';
|
||||
file_icons['htm'] = 'file-code';
|
||||
file_icons['html'] = 'file-code';
|
||||
file_icons['jpeg'] = 'file-image';
|
||||
file_icons['jpg'] = 'file-image';
|
||||
file_icons['key'] = 'file-powerpoint';
|
||||
file_icons['mkv'] = 'file-video';
|
||||
file_icons['mov'] = 'file-video';
|
||||
file_icons['mp3'] = 'file-audio';
|
||||
file_icons['mp4'] = 'file-video';
|
||||
file_icons['pdf'] = 'file-pdf';
|
||||
file_icons['png'] = 'file-image';
|
||||
file_icons['ppt'] = 'file-powerpoint';
|
||||
file_icons['pptx'] = 'file-powerpoint';
|
||||
file_icons['txt'] = 'file-alt';
|
||||
file_icons['wav'] = 'file-audio';
|
||||
file_icons['webp'] = 'file-image';
|
||||
file_icons['xls'] = 'file-excel';
|
||||
file_icons['xlsx'] = 'file-excel';
|
||||
file_icons['zip'] = 'file-archive';
|
||||
|
||||
onMount(() => {
|
||||
console.log('** Component Mounted: ** Player - Archive Content Obj');
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- <h3 class="ae_title">Viewing: {$slct.archive_content_obj.name}</h3> -->
|
||||
|
||||
<section class="ae_content">
|
||||
{#if file_icons[$slct.archive_content_obj.file_extension] == 'file-audio'}
|
||||
<audio id="view_archive_content_audio" width="" height="" autoplay controls style="max-width: 100%; max-height: 65vh;">
|
||||
<source id="view_archive_content_audio_source" src="{$ae_app.app.base_url}{$slct.archive_content_obj.file_path}" type="audio/mpeg">
|
||||
<!--<source src="audio.ogg" type="audio/ogg">-->
|
||||
Your browser does not support the audio tag.
|
||||
</audio>
|
||||
|
||||
{:else if file_icons[$slct.archive_content_obj.file_extension] == 'file-video'}
|
||||
<video id="view_archive_content_video" width="" height="" autoplay controls style="max-width: 100%; max-height: 65vh;">
|
||||
<source id="view_archive_content_video_source" src="{$ae_app.app.base_url}{$slct.archive_content_obj.file_path}" type="video/mp4">
|
||||
<!--<source src="video.ogg" type="video/ogg">-->
|
||||
<track kind="captions" src="" srclang="en" label="English">
|
||||
Your browser does not support the video tag.
|
||||
</video>
|
||||
|
||||
{:else if file_icons[$slct.archive_content_obj.file_extension] == 'file-image'}
|
||||
<img id="view_archive_content_image" src="{$ae_app.app.base_url}{$slct.archive_content_obj.file_path}" alt="{$slct.archive_content_obj.name}" style="max-width: 100%; max-height: 65vh;" />
|
||||
{:else}
|
||||
<a href="{$ae_app.app.base_url}{$slct.archive_content_obj.file_path}">{$slct.archive_content_obj.filename}</a>
|
||||
{/if}
|
||||
|
||||
{#if $slct.archive_content_obj.description}
|
||||
<div id="archive_content__description" class="archive_content__description">
|
||||
{$slct.archive_content_obj.description}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if $slct.archive_content_obj.content_html}
|
||||
<div id="archive_content__content_html" class="archive_content__content_html">
|
||||
{@html $slct.archive_content_obj.content_html}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
</section>
|
||||
@@ -1,244 +0,0 @@
|
||||
<script lang="ts">
|
||||
import { createEventDispatcher, onMount } from 'svelte';
|
||||
import { fade } from 'svelte/transition';
|
||||
|
||||
import { ae, Element_modal_v3 } from 'aether_npm_lib';
|
||||
import { slct, slct_trigger, ae_app } from './stores';
|
||||
|
||||
// import Edit_archive_content_obj from './10_edit__archive_content_obj.svelte';
|
||||
import List_archive_content_obj from './10_list__archive_content_obj.svelte';
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
if ($slct.archive_id) {
|
||||
console.log(`Archive ID selected: ${$slct.archive_id}`);
|
||||
console.log(`Archive Object selected: ${$slct.archive_obj}`)
|
||||
|
||||
$slct_trigger = 'load__archive_obj';
|
||||
$slct_trigger = 'load__archive_content_obj_li';
|
||||
|
||||
// Auto show the selected Archive ID
|
||||
// Set the URL param "archive_id" to the current Archive ID. This is a just in case.
|
||||
const url = new URL(location);
|
||||
url.searchParams.set('archive_id', $slct.archive_id);
|
||||
history.pushState({}, '', url);
|
||||
|
||||
// $ae_app.archives.show_main__options = true;
|
||||
$ae_app.archives.show_list__archive_obj_li = false;
|
||||
$ae_app.archives.show_edit__archive_obj = false;
|
||||
$ae_app.archives.show_view__archive_obj = true;
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
console.log('** Component Mounted: ** View - Archive Obj');
|
||||
});
|
||||
|
||||
function handle_archive_content_obj_created(event) {
|
||||
console.log('*** handle_archive_content_obj_created() ***');
|
||||
console.log(event.detail);
|
||||
|
||||
$slct.archive_content_id = null;
|
||||
$slct.archive_content_obj = {};
|
||||
|
||||
$slct_trigger = 'load__archive_obj_li';
|
||||
$slct_trigger = 'load__archive_obj';
|
||||
$slct_trigger = 'load__archive_content_obj_li';
|
||||
|
||||
// $ae_app.archives.show_list__archive_obj_li = false;
|
||||
// $ae_app.archives.show_edit__archive_obj = false;
|
||||
// $ae_app.archives.show_view__archive_obj = true;
|
||||
$ae_app.archives.show_edit__archive_content_id = false;
|
||||
}
|
||||
function handle_archive_content_obj_updated(event) {
|
||||
console.log('*** handle_archive_content_obj_updated() ***');
|
||||
console.log(event.detail);
|
||||
|
||||
$slct_trigger = 'load__archive_obj';
|
||||
$slct_trigger = 'load__archive_content_obj_li';
|
||||
|
||||
// $ae_app.archives.show_list__archive_obj_li = false;
|
||||
// $ae_app.archives.show_edit__archive_obj = false;
|
||||
// $ae_app.archives.show_view__archive_obj = true;
|
||||
$ae_app.archives.show_edit__archive_content_id = false;
|
||||
}
|
||||
function handle_archive_content_obj_deleted(event) {
|
||||
console.log('*** handle_archive_content_obj_deleted() ***');
|
||||
console.log(event.detail);
|
||||
|
||||
$slct_trigger = 'load__archive_obj_li';
|
||||
$slct_trigger = 'load__archive_obj';
|
||||
$slct_trigger = 'load__archive_content_obj_li';
|
||||
|
||||
// $ae_app.archives.show_list__archive_obj_li = false;
|
||||
// $ae_app.archives.show_edit__archive_obj = false;
|
||||
// $ae_app.archives.show_view__archive_obj = true;
|
||||
$ae_app.archives.show_edit__archive_content_id = false;
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<section class="svelte_component ae_section ae_view archive_obj view__archive_obj" bind:clientHeight={$ae_app.iframe_height_modal_body}>
|
||||
|
||||
<header class="ae_header archive__header">
|
||||
<h2 class="archive__name">{@html $slct.archive_obj.name}</h2>
|
||||
</header>
|
||||
|
||||
<section class="archive__content">
|
||||
{#if $slct.archive_obj.description}<div class="ae_value archive__description">{@html $slct.archive_obj.description}</div>{/if}
|
||||
{#if $slct.archive_obj.content_html}<div class="ae_value">{@html $slct.archive_obj.content_html}</div>{/if}
|
||||
{#if $slct.archive_obj.original_url}
|
||||
<div>
|
||||
<span class="ae_label">URL:</span>
|
||||
<span class="ae_value">{$slct.archive_obj.original_url}</span>
|
||||
</div>
|
||||
{/if}
|
||||
{#if $slct.archive_obj.original_datetime}
|
||||
<div class="archive__original_datetime">
|
||||
<span class="ae_label">Start Date:</span>
|
||||
<span class="ae_value">{ae.util.iso_datetime_formatter($slct.archive_obj.original_datetime, 'datetime_long')}</span>
|
||||
</div>
|
||||
{/if}
|
||||
{#if $slct.archive_obj.original_timezone}
|
||||
<span class="ae_label">Timezone:</span>
|
||||
<span class="ae_value">{$slct.archive_obj.original_timezone}</span>
|
||||
{/if}
|
||||
{#if $slct.archive_obj.original_location}
|
||||
<div>
|
||||
<span class="ae_label">Location:</span>
|
||||
<span class="ae_value">{$slct.archive_obj.original_location}</span>
|
||||
</div>
|
||||
{/if}
|
||||
</section>
|
||||
|
||||
<section
|
||||
class="ae_section ae_meta archive__meta"
|
||||
class:ae_d_none={!$ae_app.administrator_access}
|
||||
>
|
||||
<div class="ae_group">
|
||||
<div class="archive__created_on_updated_on">
|
||||
<span class="ae_label">Created on:</span>
|
||||
<span class="ae_value archive__created_on">{ae.util.iso_datetime_formatter($slct.archive_obj.created_on, 'datetime_iso_no_seconds')}</span>
|
||||
{#if $slct.archive_obj.updated_on}
|
||||
<span class="ae_label">Updated on:</span>
|
||||
<span class="ae_value">{ae.util.iso_datetime_formatter($slct.archive_obj.updated_on, 'datetime_iso_no_seconds')}</span>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{#if $ae_app.trusted_access}
|
||||
<div class="ae_options">
|
||||
{#if $ae_app.trusted_access || $slct.archive_obj.external_person_id === $ae_app.novi_uuid}
|
||||
<button
|
||||
on:click={() => {
|
||||
$slct.archive_content_id = null;
|
||||
$slct.archive_content_obj = {};
|
||||
$ae_app.archives.show_edit__archive_content_id = true;
|
||||
}}
|
||||
class="ae_btn ae_smallest btn btn-warning"
|
||||
title={`Add content for: ${$slct.archive_obj.name}`}
|
||||
>
|
||||
<span class="fas fa-plus"></span> Add Content
|
||||
</button>
|
||||
|
||||
<button
|
||||
on:click={() => {
|
||||
// $slct.archive_id = $slct.archive_obj.archive_id_random;
|
||||
// $slct.archive_obj = $slct.archive_obj;
|
||||
|
||||
// const url = new URL(location);
|
||||
// url.searchParams.set('archive_id', $slct.archive_obj.archive_id_random);
|
||||
// history.pushState({}, '', url);
|
||||
|
||||
// $ae_app.archives.show_main__options = false;
|
||||
// $ae_app.archives.show_list__archive_obj_li = false;
|
||||
$ae_app.archives.show_view__archive_obj = false;
|
||||
$ae_app.archives.show_edit__archive_obj = true;
|
||||
}}
|
||||
class="ae_btn ae_smallest btn btn-xs btn-warning"
|
||||
title={`Edit archive: ${$slct.archive_obj.name}`}
|
||||
>
|
||||
<span class="fas fa-edit"></span> Edit Archive
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</section>
|
||||
|
||||
{#if $slct.archive_obj}
|
||||
<!-- {#each $slct.archive_content_obj_li as idaa_archive_content_obj, index} -->
|
||||
<List_archive_content_obj />
|
||||
<!-- {/each} -->
|
||||
{/if}
|
||||
|
||||
|
||||
|
||||
<!-- {#if $slct.archive_content_obj_li && $slct.archive_content_obj_li.length} -->
|
||||
<!-- {#each $slct.archive_content_obj_li as idaa_archive_content_obj, index}
|
||||
<hr />
|
||||
<span class="archive_content__name">{idaa_archive_content_obj.name}</span>
|
||||
<pre class="archive_content__content">{@html idaa_archive_content_obj.content}</pre>
|
||||
|
||||
<section class="ae_section ae_meta archive_content__meta">
|
||||
<div class="ae_group">
|
||||
<div class="archive_content__created_on_updated_on">
|
||||
Created on:
|
||||
<span class="archive_content__created_on">{ae.util.iso_datetime_formatter(idaa_archive_content_obj.created_on, 'datetime_iso_no_seconds')}
|
||||
{#if idaa_archive_content_obj.updated_on}
|
||||
Updated on:
|
||||
{ae.util.iso_datetime_formatter(idaa_archive_content_obj.updated_on, 'datetime_iso_no_seconds')}
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{#if $ae_app.trusted_access || idaa_archive_content_obj.external_person_id === $ae_app.novi_uuid}
|
||||
<div class="ae_options">
|
||||
<button on:click={() => {
|
||||
$slct.archive_content_id = idaa_archive_content_obj.archive_content_id_random;
|
||||
$slct.archive_content_obj = idaa_archive_content_obj;
|
||||
|
||||
// $ae_app.archives.show_archive_content_list = false;
|
||||
$ae_app.archives.show_edit__archive_content_id = true;
|
||||
// $ae_app.archives.show_view__archive_obj = false;
|
||||
}}
|
||||
class="btn btn-default"
|
||||
>
|
||||
<span class="fas fa-edit"></span> Edit Content
|
||||
</button>
|
||||
</div>
|
||||
{/if}
|
||||
</section>
|
||||
|
||||
{/each} -->
|
||||
<!-- {/if} -->
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<style>
|
||||
.ae_label {
|
||||
font-size: smaller;
|
||||
}
|
||||
.ae_value {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.archive_obj .ae_meta {
|
||||
flex-direction: column;
|
||||
/* justify-content: space-between; */
|
||||
}
|
||||
|
||||
.archive_obj .ae_meta .ae_group {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.archive_obj .ae_meta .ae_options {
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.archive__created_on_updated_on, .archive_content__created_on_updated_on {
|
||||
/* font-size: smaller; */
|
||||
/* background-color: hsla(0,80%,50%,1); */
|
||||
/* color: hsla(0,0%,50%,1); */
|
||||
}
|
||||
</style>
|
||||
@@ -1,261 +0,0 @@
|
||||
<script lang="ts">
|
||||
import { createEventDispatcher, onMount } from 'svelte';
|
||||
import { fade } from 'svelte/transition';
|
||||
|
||||
import { ae, Element_modal_v3 } from 'aether_npm_lib';
|
||||
import { slct, slct_trigger, ae_app } from './stores';
|
||||
|
||||
import Edit_post_comment_obj from './10_edit__post_comment_obj.svelte';
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
if ($slct.post_id) {
|
||||
console.log(`Post ID selected: ${$slct.post_id}`);
|
||||
console.log(`Post Object selected: ${$slct.post_obj}`)
|
||||
|
||||
$slct_trigger = 'load__post_obj';
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
console.log('** Component Mounted: ** View - Post Obj');
|
||||
});
|
||||
|
||||
function handle_post_comment_obj_created(event) {
|
||||
console.log('*** handle_post_comment_obj_created() ***');
|
||||
console.log(event.detail);
|
||||
|
||||
$slct.post_comment_id = null;
|
||||
$slct.post_comment_obj = {};
|
||||
|
||||
$slct_trigger = 'load__post_obj_li';
|
||||
$slct_trigger = 'load__post_obj';
|
||||
$slct_trigger = 'load__post_comment_obj_li';
|
||||
|
||||
// $ae_app.posts.show_post_list = false;
|
||||
// $ae_app.posts.show_edit__post_id = false;
|
||||
// $ae_app.posts.show_view__post_id = true;
|
||||
$ae_app.posts.show_edit__post_comment = false;
|
||||
}
|
||||
function handle_post_comment_obj_updated(event) {
|
||||
console.log('*** handle_post_comment_obj_updated() ***');
|
||||
console.log(event.detail);
|
||||
|
||||
$slct_trigger = 'load__post_obj';
|
||||
$slct_trigger = 'load__post_comment_obj_li';
|
||||
|
||||
// $ae_app.posts.show_post_list = false;
|
||||
// $ae_app.posts.show_edit__post_id = false;
|
||||
// $ae_app.posts.show_view__post_id = true;
|
||||
$ae_app.posts.show_edit__post_comment = false;
|
||||
}
|
||||
function handle_post_comment_obj_deleted(event) {
|
||||
console.log('*** handle_post_comment_obj_deleted() ***');
|
||||
console.log(event.detail);
|
||||
|
||||
$slct_trigger = 'load__post_obj_li';
|
||||
$slct_trigger = 'load__post_obj';
|
||||
$slct_trigger = 'load__post_comment_obj_li';
|
||||
|
||||
// $ae_app.posts.show_post_list = false;
|
||||
// $ae_app.posts.show_edit__post_id = false;
|
||||
// $ae_app.posts.show_view__post_id = true;
|
||||
$ae_app.posts.show_edit__post_comment = false;
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<section
|
||||
bind:clientHeight={$ae_app.iframe_height_modal_body}
|
||||
class="svelte_component ae_section ae_view post_obj view__post_obj"
|
||||
>
|
||||
|
||||
<div class="post__header">
|
||||
<h2 class="post__title">
|
||||
{@html $slct.post_obj.title}
|
||||
{#if $slct.post_obj.topic_id}<span class="badge badge-info bg-info"><span class="fas fa-user-md"></span> {$slct.post_obj.topic_name}</span>{/if}
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div class="post__content">{@html $slct.post_obj.content}</div>
|
||||
|
||||
<section class="ae_section ae_meta post__meta">
|
||||
<div class="ae_group">
|
||||
{#if ($slct.post_obj.anonymous)}
|
||||
<div class="post__posted_by">
|
||||
Posted by: <span class="fas fa-user-secret"></span> <span class="post__full_name">Anonymous</span>
|
||||
</div>
|
||||
{:else if ($slct.post_obj.full_name)}
|
||||
<div class="post__posted_by">
|
||||
Posted by: <span class="fas fa-user"></span> <span class="post__full_name">{$slct.post_obj.full_name}
|
||||
{#if $ae_app.trusted_access && $slct.post_obj.email}
|
||||
<a href="mailto:{$slct.post_obj.email}?subject=IDAA BB Post">{$slct.post_obj.email}</a>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="post__created_on_updated_on">
|
||||
{#if !$slct.post_obj.updated_on}
|
||||
<span class="ae_label">Created on:</span>
|
||||
<span class="ae_value post__created_on">{ae.util.iso_datetime_formatter($slct.post_obj.created_on, 'datetime_iso_no_seconds')}</span>
|
||||
{:else}
|
||||
<span class="ae_label">Updated on:</span>
|
||||
<span class="ae_value post__updated_on">
|
||||
{ae.util.iso_datetime_formatter($slct.post_obj.updated_on, 'datetime_iso_no_seconds')}</span>
|
||||
{/if}
|
||||
<span class="post__archive_on">
|
||||
<span class="ae_label">Archive on:</span>
|
||||
<span class="ae_value">{ae.util.iso_datetime_formatter($slct.post_obj.archive_on, 'datetime_iso_no_seconds')}</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ae_options">
|
||||
{#if $slct.post_obj.post_comment_count}
|
||||
<span class="ae_badge ae_info post__post_comment_count">
|
||||
<span class="fas fa-comment"></span> {($slct.post_obj.post_comment_count == 1 ? `${$slct.post_obj.post_comment_count} comment` : `${$slct.post_obj.post_comment_count} comments` )}
|
||||
</span>
|
||||
{/if}
|
||||
<button
|
||||
on:click={() => {
|
||||
$ae_app.posts.show_edit__post_comment = true;
|
||||
}}
|
||||
class="btn btn-primary"
|
||||
title={`New comment on: ${$slct.post_obj.title}`}
|
||||
>
|
||||
<span class="fas fa-plus"></span> New Comment
|
||||
</button>
|
||||
|
||||
{#if $ae_app.trusted_access || $slct.post_obj.external_person_id === $ae_app.novi_uuid || $slct.post_obj.email === $ae_app.novi_email}
|
||||
<button
|
||||
on:click={() => {
|
||||
// $slct.post_id = $slct.post_obj.post_id_random;
|
||||
// $slct.post_obj = $slct.post_obj;
|
||||
|
||||
// const url = new URL(location);
|
||||
// url.searchParams.set('post_id', $slct.post_obj.post_id_random);
|
||||
// history.pushState({}, '', url);
|
||||
|
||||
// $ae_app.posts.show_main__options = false;
|
||||
// $ae_app.posts.show_list__post_li = false;
|
||||
$ae_app.posts.show_view__post_id = false;
|
||||
$ae_app.posts.show_edit__post_id = true;
|
||||
}}
|
||||
class="ae_btn ae_smallest btn btn-xs btn-secondary"
|
||||
title={`Edit post: ${$slct.post_obj.name}`}
|
||||
>
|
||||
<span class="fas fa-edit"></span> Edit
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
{#if $ae_app.posts.show_edit__post_comment}
|
||||
<section class="bb_post_comment_crud">
|
||||
|
||||
<Element_modal_v3
|
||||
show = { true }
|
||||
modal_cover_body = { true }
|
||||
on:close={ () => {
|
||||
$slct.post_comment_id = null;
|
||||
$slct.post_comment_obj = {};
|
||||
|
||||
// $ae_app.posts.show_post_list = true;
|
||||
// $ae_app.posts.show_edit__post_id = false;
|
||||
// $ae_app.posts.show_view__post_id = false;
|
||||
$ae_app.posts.show_edit__post_comment = false;
|
||||
}}
|
||||
>
|
||||
<span slot="header_title">Comment on: {($slct.post_obj.title ? $slct.post_obj.title : '')}</span>
|
||||
|
||||
<span slot="body">
|
||||
<section class="post_comment_obj_view">
|
||||
<Edit_post_comment_obj on:post_comment_obj_created={handle_post_comment_obj_created} on:post_comment_obj_updated={handle_post_comment_obj_updated} on:post_comment_obj_deleted={handle_post_comment_obj_deleted} />
|
||||
</section>
|
||||
</span>
|
||||
</Element_modal_v3>
|
||||
</section>
|
||||
{/if}
|
||||
|
||||
{#if $slct.post_comment_obj_li.length}
|
||||
{#each $slct.post_comment_obj_li as idaa_post_comment_obj, index}
|
||||
<hr />
|
||||
<div class="post_comment__content">{@html idaa_post_comment_obj.content}</div>
|
||||
|
||||
|
||||
<section class="ae_section ae_meta post_comment__meta">
|
||||
<div class="ae_group">
|
||||
<span class="post_comment__posted_by `comment_by_container">
|
||||
<span class="comment_by_lable">Comment by:</span>
|
||||
{#if idaa_post_comment_obj.anonymous}
|
||||
<span class="fas fa-user-secret"></span>
|
||||
<span class="comment_by_full_name anonymous">Anonymous</span>
|
||||
{:else}
|
||||
<span class="fas fa-user"></span>
|
||||
<span class="comment_by_full_name">{idaa_post_comment_obj.full_name}</span>
|
||||
<!-- {#if idaa_post_comment_obj.email}
|
||||
(<a href="mailto:{idaa_post_comment_obj.email}"><span class="comment_by_email">{idaa_post_comment_obj.email}</span></a>)
|
||||
{/if} -->
|
||||
{/if}
|
||||
<div class="post_comment__created_on_updated_on">
|
||||
Created on:
|
||||
<span class="post_comment__created_on">{ae.util.iso_datetime_formatter(idaa_post_comment_obj.created_on, 'datetime_iso_no_seconds')}
|
||||
{#if idaa_post_comment_obj.updated_on}
|
||||
Updated on:
|
||||
{ae.util.iso_datetime_formatter(idaa_post_comment_obj.updated_on, 'datetime_iso_no_seconds')}
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{#if $ae_app.trusted_access || idaa_post_comment_obj.external_person_id === $ae_app.novi_uuid}
|
||||
<div class="ae_options">
|
||||
<button on:click={() => {
|
||||
$slct.post_comment_id = idaa_post_comment_obj.post_comment_id_random;
|
||||
$slct.post_comment_obj = idaa_post_comment_obj;
|
||||
|
||||
// $ae_app.posts.show_post_comment_list = false;
|
||||
$ae_app.posts.show_edit__post_comment = true;
|
||||
// $ae_app.posts.show_view__post_id = false;
|
||||
}}
|
||||
class="ae_btn ae_smallest btn btn-secondary"
|
||||
>
|
||||
<span class="fas fa-edit"></span> Edit Comment
|
||||
</button>
|
||||
</div>
|
||||
{/if}
|
||||
</section>
|
||||
|
||||
{/each}
|
||||
{/if}
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<style>
|
||||
.post_obj .ae_meta {
|
||||
flex-direction: column;
|
||||
/* justify-content: space-between; */
|
||||
}
|
||||
|
||||
.post_obj .ae_meta .ae_group {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.post_obj .ae_meta .ae_options {
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.post__posted_by, .post_comment__posted_by {
|
||||
/* font-size: smaller; */
|
||||
/* background-color: hsla(0,80%,50%,1); */
|
||||
/* color: hsla(0,0%,50%,1); */
|
||||
}
|
||||
|
||||
.post__created_on_updated_on, .post_comment__created_on_updated_on {
|
||||
/* font-size: smaller; */
|
||||
/* background-color: hsla(0,80%,50%,1); */
|
||||
/* color: hsla(0,0%,50%,1); */
|
||||
}
|
||||
</style>
|
||||
@@ -1,192 +0,0 @@
|
||||
<script lang="ts">
|
||||
import { createEventDispatcher, onMount } from 'svelte';
|
||||
import { fade } from 'svelte/transition';
|
||||
|
||||
import { ae } from 'aether_npm_lib';
|
||||
import { slct, slct_trigger, ae_app } from './stores';
|
||||
|
||||
export let container_class_li = [];
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
if ($slct.sponsorship_id) {
|
||||
console.log(`Sponsorship ID selected: ${$slct.sponsorship_id}`);
|
||||
console.log(`Sponsorship Object selected: ${$slct.sponsorship_obj}`)
|
||||
|
||||
$slct_trigger = 'load__sponsorship_obj';
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
console.log('** Component Mounted: ** View - Sponsorship Obj');
|
||||
});
|
||||
|
||||
|
||||
dayjs.extend(window.dayjs_plugin_utc)
|
||||
dayjs.extend(window.dayjs_plugin_timezone);
|
||||
console.log(`UTC offset: ${dayjs().utcOffset()}`);
|
||||
console.log(`TZ offset: ${dayjs().utcOffset('US/Pacific')}`);
|
||||
// let test_time = dayjs.utc('2024-01-08 11:55').tz('Asia/Taipei');
|
||||
// let test_time = dayjs.utc('2024-01-08 14:15').tz('America/New_York');
|
||||
let test_time = dayjs.tz('2024-01-08 14:15', 'US/Pacific');
|
||||
console.log(test_time.format('YYYY-MM-DD HH:mm'));
|
||||
let adjusted_to_local_tz = test_time.tz('America/New_York');
|
||||
console.log(adjusted_to_local_tz.format('YYYY-MM-DD HH:mm'));
|
||||
|
||||
let adjusted_to_local_tz_v2 = dayjs.tz('2024-01-08 14:15', 'US/Pacific').tz('America/New_York');
|
||||
console.log(adjusted_to_local_tz_v2);
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<section class="svelte_component ae_section ae_view sponsorship_obj view__sponsorship_obj {container_class_li.join(' ')}">
|
||||
|
||||
<div class="sponsorship__header">
|
||||
<h2 class="sponsorship__name">{@html $slct.sponsorship_obj.name}</h2>
|
||||
</div>
|
||||
|
||||
<div class="sponsorship__content">
|
||||
<div
|
||||
class="sponsorship_description description"
|
||||
>
|
||||
<div class="ae_label sponsorship__description">Description:</div>
|
||||
<pre class="ae_value sponsorship__description">{@html $slct.sponsorship_obj.description ? $slct.sponsorship_obj.description : '-- No Description Given --'}</pre>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class:ae_d_none={!$slct.sponsorship_obj.level_num}
|
||||
class="sponsorship_level"
|
||||
>
|
||||
<span class="ae_label">Level of Sponsorship:</span>
|
||||
<span class="ae_value"><span class="fas fa-gem"></span> {$slct.sponsorship_obj.level_num} — {$slct.sponsorship_obj.level_str}</span>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<span class="ae_label">Paid:</span>
|
||||
$
|
||||
<span class="ae_value">
|
||||
{$slct.sponsorship_obj.paid ? 'Yes, marked as paid' : 'Not yet marked as paid'}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="ae_list sponsorship__guests">
|
||||
<h2>Guest List</h2>
|
||||
|
||||
{#if $slct.sponsorship_obj.guest_li_json && $slct.sponsorship_obj.guest_li_json.length && $slct.sponsorship_obj.guest_li_json[0].full_name}
|
||||
<ul>
|
||||
{#each $slct.sponsorship_obj.guest_li_json as guest, index}
|
||||
<li class="sponsorship__guest"
|
||||
class:ae_d_none={!$slct.sponsorship_obj.guest_li_json[index].full_name}
|
||||
>
|
||||
<span class="ae_label">
|
||||
<span class="fas fa-user"></span> Contact:
|
||||
</span>
|
||||
{$slct.sponsorship_obj.guest_li_json[index].full_name}
|
||||
{#if $slct.sponsorship_obj.guest_li_json[index].email}
|
||||
| <a href="mailto:{$slct.sponsorship_obj.guest_li_json[index].email}?Subject={$slct.sponsorship_obj.full_name}">{$slct.sponsorship_obj.guest_li_json[index].email}</a>
|
||||
{/if}
|
||||
{#if $slct.sponsorship_obj.guest_li_json[index].phone_mobile}
|
||||
<span class="ae_label">| Mobile:</span>
|
||||
<a href="tel:{$slct.sponsorship_obj.guest_li_json[index].phone_mobile}">{$slct.sponsorship_obj.guest_li_json[index].phone_mobile}</a>
|
||||
{/if}
|
||||
{#if $slct.sponsorship_obj.guest_li_json[index].phone_home}
|
||||
<span class="ae_label">| Home:</span>
|
||||
<a href="tel:{$slct.sponsorship_obj.guest_li_json[index].phone_home}">{$slct.sponsorship_obj.guest_li_json[index].phone_home}</a>
|
||||
{/if}
|
||||
{#if $slct.sponsorship_obj.guest_li_json[index].phone_office}
|
||||
<span class="ae_label">| Office:</span>
|
||||
<a href="tel:{$slct.sponsorship_obj.guest_li_json[index].phone_office}">{$slct.sponsorship_obj.guest_li_json[index].phone_office}</a>
|
||||
{/if}
|
||||
{#if $slct.sponsorship_obj.guest_li_json[index].other_text}| {$slct.sponsorship_obj.guest_li_json[index].other_text}{/if}
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
{:else}
|
||||
<div class="ae_warning">No guest list found!</div>
|
||||
{/if}
|
||||
|
||||
</div>
|
||||
|
||||
<section class="ae_section ae_meta sponsorship__meta">
|
||||
<div class="ae_group">
|
||||
<span
|
||||
class="sponsorship__id"
|
||||
class:ae_d_none={!$ae_app.administrator_access}>
|
||||
ID:
|
||||
{$slct.sponsorship_obj.sponsorship_id_random}
|
||||
</span>
|
||||
<span
|
||||
class="sponsorship__created_on"
|
||||
>
|
||||
Created on: {ae.util.iso_datetime_formatter($slct.sponsorship_obj.created_on, 'datetime_short')}
|
||||
</span>
|
||||
<span
|
||||
class="sponsorship__updated_on"
|
||||
class:ae_d_none={!$slct.sponsorship_obj.updated_on}
|
||||
>
|
||||
Updated on: {ae.util.iso_datetime_formatter($slct.sponsorship_obj.updated_on, 'datetime_short')}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{#if $ae_app.trusted_access || $slct.sponsorship_obj.external_person_id === $ae_app.novi_uuid || $slct.sponsorship_obj.contact_1_email === $ae_app.novi_email}
|
||||
<div class="ae_options">
|
||||
<button
|
||||
on:click={() => {
|
||||
// $slct.sponsorship_id = $slct.sponsorship_obj.sponsorship_id_random;
|
||||
// $slct.sponsorship_obj = $slct.sponsorship_obj;
|
||||
|
||||
// const url = new URL(location);
|
||||
// url.searchParams.set('sponsorship_id', $slct.sponsorship_obj.sponsorship_id_random);
|
||||
// history.pushState({}, '', url);
|
||||
|
||||
// $ae_app.sponsorships.show_main__options = true;
|
||||
// $ae_app.sponsorships.show_list__sponsorship_obj_li = true;
|
||||
$ae_app.sponsorships.show_view__sponsorship_obj = false;
|
||||
$ae_app.sponsorships.show_edit__sponsorship_obj = true;
|
||||
}}
|
||||
class="btn btn-xs btn-secondary"
|
||||
title={`Edit sponsorship: ${$slct.sponsorship_obj.name}`}
|
||||
>
|
||||
<span class="fas fa-edit"></span> Edit
|
||||
</button>
|
||||
</div>
|
||||
{/if}
|
||||
</section>
|
||||
|
||||
</div>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<style>
|
||||
.ae_label {
|
||||
font-size: smaller;
|
||||
}
|
||||
.ae_value {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.sponsorship__user_timezone {
|
||||
font-size: smaller;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.sponsorship_obj .ae_meta {
|
||||
flex-direction: column;
|
||||
/* justify-content: space-between; */
|
||||
}
|
||||
|
||||
.sponsorship_obj .ae_meta .ae_group {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.sponsorship_obj .ae_meta .ae_options {
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
/* a {
|
||||
color: #82B6E1;
|
||||
} */
|
||||
</style>
|
||||
@@ -1,47 +0,0 @@
|
||||
<script lang="ts">
|
||||
import svelteLogo from './assets/svelte.svg'
|
||||
import viteLogo from '/vite.svg'
|
||||
import Counter from './lib/Counter.svelte'
|
||||
</script>
|
||||
|
||||
<main>
|
||||
<div>
|
||||
<a href="https://vitejs.dev" target="_blank" rel="noreferrer">
|
||||
<img src={viteLogo} class="logo" alt="Vite Logo" />
|
||||
</a>
|
||||
<a href="https://svelte.dev" target="_blank" rel="noreferrer">
|
||||
<img src={svelteLogo} class="logo svelte" alt="Svelte Logo" />
|
||||
</a>
|
||||
</div>
|
||||
<h1>Vite + Svelte</h1>
|
||||
|
||||
<div class="card">
|
||||
<Counter />
|
||||
</div>
|
||||
|
||||
<p>
|
||||
Check out <a href="https://github.com/sveltejs/kit#readme" target="_blank" rel="noreferrer">SvelteKit</a>, the official Svelte app framework powered by Vite!
|
||||
</p>
|
||||
|
||||
<p class="read-the-docs">
|
||||
Click on the Vite and Svelte logos to learn more
|
||||
</p>
|
||||
</main>
|
||||
|
||||
<style>
|
||||
.logo {
|
||||
height: 6em;
|
||||
padding: 1.5em;
|
||||
will-change: filter;
|
||||
transition: filter 300ms;
|
||||
}
|
||||
.logo:hover {
|
||||
filter: drop-shadow(0 0 2em #646cffaa);
|
||||
}
|
||||
.logo.svelte:hover {
|
||||
filter: drop-shadow(0 0 2em #ff3e00aa);
|
||||
}
|
||||
.read-the-docs {
|
||||
color: #888;
|
||||
}
|
||||
</style>
|
||||
166
src/ae-c-idaa-light.css
Normal file
166
src/ae-c-idaa-light.css
Normal file
@@ -0,0 +1,166 @@
|
||||
[data-theme='AE_c_IDAA_light'] {
|
||||
--text-scaling: 1.067;
|
||||
--base-font-color: var(--color-surface-950);
|
||||
|
||||
--base-font-family: system-ui, sans-serif;
|
||||
--base-font-size: inherit;
|
||||
--base-line-height: inherit;
|
||||
--base-font-weight: normal;
|
||||
--base-font-style: normal;
|
||||
--base-letter-spacing: 0em;
|
||||
--heading-font-color: inherit;
|
||||
|
||||
--heading-font-family: inherit;
|
||||
--heading-font-weight: bold;
|
||||
--heading-font-style: normal;
|
||||
--heading-letter-spacing: inherit;
|
||||
--anchor-font-color: var(--color-primary-600);
|
||||
|
||||
--anchor-font-family: inherit;
|
||||
--anchor-font-size: inherit;
|
||||
--anchor-line-height: inherit;
|
||||
--anchor-font-weight: inherit;
|
||||
--anchor-font-style: inherit;
|
||||
--anchor-letter-spacing: inherit;
|
||||
--anchor-text-decoration: none;
|
||||
--anchor-text-decoration-hover: underline;
|
||||
--anchor-text-decoration-active: none;
|
||||
--anchor-text-decoration-focus: none;
|
||||
--spacing: 0.25rem;
|
||||
--radius-base: 0.375rem;
|
||||
--radius-container: 0.75rem;
|
||||
--default-border-width: 1px;
|
||||
--default-divide-width: 1px;
|
||||
--default-ring-width: 1px;
|
||||
--body-background-color: var(--color-surface-50);
|
||||
|
||||
--color-primary-50: oklch(85.73% 0.07 251.8deg);
|
||||
--color-primary-100: oklch(78.5% 0.09 252.03deg);
|
||||
--color-primary-200: oklch(71.06% 0.1 253.6deg);
|
||||
--color-primary-300: oklch(63.76% 0.12 253.85deg);
|
||||
--color-primary-400: oklch(56.32% 0.14 255.25deg);
|
||||
--color-primary-500: oklch(49.23% 0.15 256.36deg);
|
||||
--color-primary-600: oklch(43.11% 0.14 258.86deg);
|
||||
--color-primary-700: oklch(36.85% 0.14 261.54deg);
|
||||
--color-primary-800: oklch(30.41% 0.13 263.99deg);
|
||||
--color-primary-900: oklch(23.91% 0.12 265.91deg);
|
||||
--color-primary-950: oklch(16.96% 0.12 264.05deg);
|
||||
|
||||
--color-primary-contrast-light: var(--color-primary-50);
|
||||
|
||||
--color-primary-contrast-500: var(--color-primary-contrast-light);
|
||||
--color-primary-contrast-600: var(--color-primary-contrast-light);
|
||||
--color-primary-contrast-700: var(--color-primary-contrast-light);
|
||||
--color-primary-contrast-800: var(--color-primary-contrast-light);
|
||||
--color-primary-contrast-900: var(--color-primary-contrast-light);
|
||||
--color-primary-contrast-950: var(--color-primary-contrast-light);
|
||||
--color-secondary-50: oklch(96.26% 0.06 196.24deg);
|
||||
--color-secondary-100: oklch(89.14% 0.07 220.79deg);
|
||||
--color-secondary-200: oklch(82.13% 0.08 234.87deg);
|
||||
--color-secondary-300: oklch(75.03% 0.11 245.33deg);
|
||||
--color-secondary-400: oklch(68.15% 0.14 250.72deg);
|
||||
--color-secondary-500: oklch(61.37% 0.16 255.34deg);
|
||||
--color-secondary-600: oklch(55.1% 0.16 256.81deg);
|
||||
--color-secondary-700: oklch(48.64% 0.15 258.4deg);
|
||||
--color-secondary-800: oklch(41.84% 0.15 260.39deg);
|
||||
--color-secondary-900: oklch(35.05% 0.14 262.03deg);
|
||||
--color-secondary-950: oklch(28.12% 0.14 262.47deg);
|
||||
|
||||
--color-secondary-contrast-light: var(--color-secondary-50);
|
||||
|
||||
--color-secondary-contrast-600: var(--color-secondary-contrast-light);
|
||||
--color-secondary-contrast-700: var(--color-secondary-contrast-light);
|
||||
--color-secondary-contrast-800: var(--color-secondary-contrast-light);
|
||||
--color-secondary-contrast-900: var(--color-secondary-contrast-light);
|
||||
--color-secondary-contrast-950: var(--color-secondary-contrast-light);
|
||||
--color-tertiary-50: oklch(100% 0 none);
|
||||
--color-tertiary-100: oklch(96.07% 0.01 251.15deg);
|
||||
--color-tertiary-200: oklch(91.88% 0.03 252.69deg);
|
||||
--color-tertiary-300: oklch(87.99% 0.05 253.24deg);
|
||||
--color-tertiary-400: oklch(83.81% 0.06 253.57deg);
|
||||
--color-tertiary-500: oklch(79.93% 0.08 253.32deg);
|
||||
--color-tertiary-600: oklch(72.53% 0.08 251.75deg);
|
||||
--color-tertiary-700: oklch(64.93% 0.08 249.75deg);
|
||||
--color-tertiary-800: oklch(57.14% 0.09 247.99deg);
|
||||
--color-tertiary-900: oklch(49.18% 0.09 246.55deg);
|
||||
--color-tertiary-950: oklch(41.1% 0.09 246.54deg);
|
||||
|
||||
--color-tertiary-contrast-light: var(--color-tertiary-50);
|
||||
|
||||
--color-tertiary-contrast-800: var(--color-tertiary-contrast-light);
|
||||
--color-tertiary-contrast-900: var(--color-tertiary-contrast-light);
|
||||
--color-tertiary-contrast-950: var(--color-tertiary-contrast-light);
|
||||
--color-success-50: oklch(95.82% 0.06 184.52deg);
|
||||
--color-success-100: oklch(91.55% 0.08 172.29deg);
|
||||
--color-success-200: oklch(87.44% 0.11 165.22deg);
|
||||
--color-success-300: oklch(83.26% 0.13 161.2deg);
|
||||
--color-success-400: oklch(79.56% 0.16 157.13deg);
|
||||
--color-success-500: oklch(76.12% 0.18 153.61deg);
|
||||
--color-success-600: oklch(69.31% 0.17 151.81deg);
|
||||
--color-success-700: oklch(62.07% 0.16 149.95deg);
|
||||
--color-success-800: oklch(54.9% 0.15 147.65deg);
|
||||
--color-success-900: oklch(47.26% 0.14 145.54deg);
|
||||
--color-success-950: oklch(39.64% 0.13 143.79deg);
|
||||
|
||||
--color-success-contrast-light: var(--color-success-50);
|
||||
|
||||
--color-success-contrast-800: var(--color-success-contrast-light);
|
||||
--color-success-contrast-900: var(--color-success-contrast-light);
|
||||
--color-success-contrast-950: var(--color-success-contrast-light);
|
||||
--color-warning-50: oklch(98.26% 0.1 108.02deg);
|
||||
--color-warning-100: oklch(95.84% 0.12 104.66deg);
|
||||
--color-warning-200: oklch(93.48% 0.13 102.21deg);
|
||||
--color-warning-300: oklch(91.49% 0.15 100.17deg);
|
||||
--color-warning-400: oklch(89.28% 0.16 98.19deg);
|
||||
--color-warning-500: oklch(87.14% 0.17 96.01deg);
|
||||
--color-warning-600: oklch(79.88% 0.16 96.31deg);
|
||||
--color-warning-700: oklch(72.35% 0.14 95.62deg);
|
||||
--color-warning-800: oklch(64.73% 0.13 95.92deg);
|
||||
--color-warning-900: oklch(56.77% 0.11 94.87deg);
|
||||
--color-warning-950: oklch(48.63% 0.1 95.22deg);
|
||||
|
||||
--color-warning-contrast-light: var(--color-warning-50);
|
||||
|
||||
--color-warning-contrast-800: var(--color-warning-contrast-light);
|
||||
--color-warning-contrast-900: var(--color-warning-contrast-light);
|
||||
--color-warning-contrast-950: var(--color-warning-contrast-light);
|
||||
--color-error-50: oklch(81.88% 0.1 38.14deg);
|
||||
--color-error-100: oklch(75.88% 0.13 31.15deg);
|
||||
--color-error-200: oklch(70.29% 0.16 27.32deg);
|
||||
--color-error-300: oklch(65.15% 0.19 25.65deg);
|
||||
--color-error-400: oklch(60.98% 0.21 25.56deg);
|
||||
--color-error-500: oklch(57.86% 0.22 26.62deg);
|
||||
--color-error-600: oklch(52.52% 0.2 26.86deg);
|
||||
--color-error-700: oklch(46.81% 0.18 27.02deg);
|
||||
--color-error-800: oklch(41.15% 0.16 27.63deg);
|
||||
--color-error-900: oklch(35.01% 0.14 27.9deg);
|
||||
--color-error-950: oklch(28.69% 0.12 29.23deg);
|
||||
|
||||
--color-error-contrast-light: var(--color-error-50);
|
||||
|
||||
--color-error-contrast-400: var(--color-error-contrast-light);
|
||||
--color-error-contrast-500: var(--color-error-contrast-light);
|
||||
--color-error-contrast-600: var(--color-error-contrast-light);
|
||||
--color-error-contrast-700: var(--color-error-contrast-light);
|
||||
--color-error-contrast-800: var(--color-error-contrast-light);
|
||||
--color-error-contrast-900: var(--color-error-contrast-light);
|
||||
--color-error-contrast-950: var(--color-error-contrast-light);
|
||||
--color-surface-50: oklch(100% 0 none);
|
||||
--color-surface-100: oklch(93.98% 0 105.57deg);
|
||||
--color-surface-200: oklch(87.66% 0 67.88deg);
|
||||
--color-surface-300: oklch(81.35% 0 106.1deg);
|
||||
--color-surface-400: oklch(74.79% 0 84.45deg);
|
||||
--color-surface-500: oklch(68.29% 0 91.36deg);
|
||||
--color-surface-600: oklch(60.99% 0 91.38deg);
|
||||
--color-surface-700: oklch(53.5% 0 84.49deg);
|
||||
--color-surface-800: oklch(46.03% 0 91.43deg);
|
||||
--color-surface-900: oklch(37.94% 0 84.52deg);
|
||||
--color-surface-950: oklch(29.34% 0 84.54deg);
|
||||
|
||||
--color-surface-contrast-light: var(--color-surface-50);
|
||||
|
||||
--color-surface-contrast-700: var(--color-surface-contrast-light);
|
||||
--color-surface-contrast-800: var(--color-surface-contrast-light);
|
||||
--color-surface-contrast-900: var(--color-surface-contrast-light);
|
||||
--color-surface-contrast-950: var(--color-surface-contrast-light);
|
||||
}
|
||||
205
src/ae-c-lci.css
Normal file
205
src/ae-c-lci.css
Normal file
@@ -0,0 +1,205 @@
|
||||
[data-theme='AE_c_LCI'] {
|
||||
--text-scaling: 1.067;
|
||||
--base-font-color: var(--color-surface-950);
|
||||
--base-font-color-dark: var(--color-surface-50);
|
||||
--base-font-family: system-ui, sans-serif;
|
||||
--base-font-size: inherit;
|
||||
--base-line-height: inherit;
|
||||
--base-font-weight: normal;
|
||||
--base-font-style: normal;
|
||||
--base-letter-spacing: 0em;
|
||||
--heading-font-color: inherit;
|
||||
--heading-font-color-dark: inherit;
|
||||
--heading-font-family: inherit;
|
||||
--heading-font-weight: bold;
|
||||
--heading-font-style: normal;
|
||||
--heading-letter-spacing: inherit;
|
||||
--anchor-font-color: var(--color-primary-500);
|
||||
--anchor-font-color-dark: var(--color-primary-500);
|
||||
--anchor-font-family: inherit;
|
||||
--anchor-font-size: inherit;
|
||||
--anchor-line-height: inherit;
|
||||
--anchor-font-weight: inherit;
|
||||
--anchor-font-style: inherit;
|
||||
--anchor-letter-spacing: inherit;
|
||||
--anchor-text-decoration: none;
|
||||
--anchor-text-decoration-hover: underline;
|
||||
--anchor-text-decoration-active: none;
|
||||
--anchor-text-decoration-focus: none;
|
||||
--spacing: 0.25rem;
|
||||
--radius-base: 0.375rem;
|
||||
--radius-container: 0.75rem;
|
||||
--default-border-width: 1px;
|
||||
--default-divide-width: 1px;
|
||||
--default-ring-width: 1px;
|
||||
--body-background-color: var(--color-surface-50);
|
||||
--body-background-color-dark: var(--color-surface-950);
|
||||
--color-primary-50: oklch(85.1% 0.07 265.19deg);
|
||||
--color-primary-100: oklch(77.89% 0.08 264.31deg);
|
||||
--color-primary-200: oklch(70.32% 0.08 264.44deg);
|
||||
--color-primary-300: oklch(62.86% 0.09 263.87deg);
|
||||
--color-primary-400: oklch(54.96% 0.1 263.8deg);
|
||||
--color-primary-500: oklch(47.12% 0.11 262.88deg);
|
||||
--color-primary-600: oklch(40.9% 0.1 264.73deg);
|
||||
--color-primary-700: oklch(34.53% 0.1 267.34deg);
|
||||
--color-primary-800: oklch(28.16% 0.09 268.81deg);
|
||||
--color-primary-900: oklch(21.29% 0.09 271.12deg);
|
||||
--color-primary-950: oklch(12.88% 0.09 264.05deg);
|
||||
--color-primary-contrast-dark: var(--color-primary-950);
|
||||
--color-primary-contrast-light: var(--color-primary-50);
|
||||
--color-primary-contrast-50: var(--color-primary-contrast-dark);
|
||||
--color-primary-contrast-100: var(--color-primary-contrast-dark);
|
||||
--color-primary-contrast-200: var(--color-primary-contrast-dark);
|
||||
--color-primary-contrast-300: var(--color-primary-contrast-dark);
|
||||
--color-primary-contrast-400: var(--color-primary-contrast-dark);
|
||||
--color-primary-contrast-500: var(--color-primary-contrast-light);
|
||||
--color-primary-contrast-600: var(--color-primary-contrast-light);
|
||||
--color-primary-contrast-700: var(--color-primary-contrast-light);
|
||||
--color-primary-contrast-800: var(--color-primary-contrast-light);
|
||||
--color-primary-contrast-900: var(--color-primary-contrast-light);
|
||||
--color-primary-contrast-950: var(--color-primary-contrast-light);
|
||||
--color-secondary-50: oklch(96.14% 0.06 196.21deg);
|
||||
--color-secondary-100: oklch(89.81% 0.07 212.45deg);
|
||||
--color-secondary-200: oklch(83.71% 0.08 223.06deg);
|
||||
--color-secondary-300: oklch(77.42% 0.1 231.73deg);
|
||||
--color-secondary-400: oklch(71.44% 0.12 237.59deg);
|
||||
--color-secondary-500: oklch(65.39% 0.14 243.22deg);
|
||||
--color-secondary-600: oklch(58.93% 0.13 245.07deg);
|
||||
--color-secondary-700: oklch(52.09% 0.12 248.03deg);
|
||||
--color-secondary-800: oklch(45.27% 0.12 250.54deg);
|
||||
--color-secondary-900: oklch(38.01% 0.11 254.24deg);
|
||||
--color-secondary-950: oklch(30.67% 0.11 256.73deg);
|
||||
--color-secondary-contrast-dark: var(--color-secondary-950);
|
||||
--color-secondary-contrast-light: var(--color-secondary-50);
|
||||
--color-secondary-contrast-50: var(--color-secondary-contrast-dark);
|
||||
--color-secondary-contrast-100: var(--color-secondary-contrast-dark);
|
||||
--color-secondary-contrast-200: var(--color-secondary-contrast-dark);
|
||||
--color-secondary-contrast-300: var(--color-secondary-contrast-dark);
|
||||
--color-secondary-contrast-400: var(--color-secondary-contrast-dark);
|
||||
--color-secondary-contrast-500: var(--color-secondary-contrast-dark);
|
||||
--color-secondary-contrast-600: var(--color-secondary-contrast-dark);
|
||||
--color-secondary-contrast-700: var(--color-secondary-contrast-light);
|
||||
--color-secondary-contrast-800: var(--color-secondary-contrast-light);
|
||||
--color-secondary-contrast-900: var(--color-secondary-contrast-light);
|
||||
--color-secondary-contrast-950: var(--color-secondary-contrast-light);
|
||||
--color-tertiary-50: oklch(87.75% 0.12 326.52deg);
|
||||
--color-tertiary-100: oklch(80.92% 0.13 323.93deg);
|
||||
--color-tertiary-200: oklch(73.87% 0.14 321.55deg);
|
||||
--color-tertiary-300: oklch(66.9% 0.15 319.41deg);
|
||||
--color-tertiary-400: oklch(59.72% 0.16 317.25deg);
|
||||
--color-tertiary-500: oklch(52.73% 0.17 315.13deg);
|
||||
--color-tertiary-600: oklch(46.6% 0.16 314.18deg);
|
||||
--color-tertiary-700: oklch(40.43% 0.14 312.8deg);
|
||||
--color-tertiary-800: oklch(33.85% 0.13 309.88deg);
|
||||
--color-tertiary-900: oklch(27.23% 0.12 306.83deg);
|
||||
--color-tertiary-950: oklch(19.83% 0.1 302.7deg);
|
||||
--color-tertiary-contrast-dark: var(--color-tertiary-950);
|
||||
--color-tertiary-contrast-light: var(--color-tertiary-50);
|
||||
--color-tertiary-contrast-50: var(--color-tertiary-contrast-dark);
|
||||
--color-tertiary-contrast-100: var(--color-tertiary-contrast-dark);
|
||||
--color-tertiary-contrast-200: var(--color-tertiary-contrast-dark);
|
||||
--color-tertiary-contrast-300: var(--color-tertiary-contrast-dark);
|
||||
--color-tertiary-contrast-400: var(--color-tertiary-contrast-light);
|
||||
--color-tertiary-contrast-500: var(--color-tertiary-contrast-light);
|
||||
--color-tertiary-contrast-600: var(--color-tertiary-contrast-light);
|
||||
--color-tertiary-contrast-700: var(--color-tertiary-contrast-light);
|
||||
--color-tertiary-contrast-800: var(--color-tertiary-contrast-light);
|
||||
--color-tertiary-contrast-900: var(--color-tertiary-contrast-light);
|
||||
--color-tertiary-contrast-950: var(--color-tertiary-contrast-light);
|
||||
--color-success-50: oklch(95.23% 0.07 195.99deg);
|
||||
--color-success-100: oklch(90.22% 0.09 189.46deg);
|
||||
--color-success-200: oklch(85.11% 0.1 186.03deg);
|
||||
--color-success-300: oklch(80.35% 0.12 181.75deg);
|
||||
--color-success-400: oklch(75.55% 0.12 178.92deg);
|
||||
--color-success-500: oklch(71.19% 0.13 174.73deg);
|
||||
--color-success-600: oklch(64.29% 0.12 173.65deg);
|
||||
--color-success-700: oklch(57.46% 0.11 171.75deg);
|
||||
--color-success-800: oklch(50.18% 0.1 170.68deg);
|
||||
--color-success-900: oklch(42.87% 0.09 167.65deg);
|
||||
--color-success-950: oklch(34.91% 0.07 164.42deg);
|
||||
--color-success-contrast-dark: var(--color-success-950);
|
||||
--color-success-contrast-light: var(--color-success-50);
|
||||
--color-success-contrast-50: var(--color-success-contrast-dark);
|
||||
--color-success-contrast-100: var(--color-success-contrast-dark);
|
||||
--color-success-contrast-200: var(--color-success-contrast-dark);
|
||||
--color-success-contrast-300: var(--color-success-contrast-dark);
|
||||
--color-success-contrast-400: var(--color-success-contrast-dark);
|
||||
--color-success-contrast-500: var(--color-success-contrast-dark);
|
||||
--color-success-contrast-600: var(--color-success-contrast-dark);
|
||||
--color-success-contrast-700: var(--color-success-contrast-light);
|
||||
--color-success-contrast-800: var(--color-success-contrast-light);
|
||||
--color-success-contrast-900: var(--color-success-contrast-light);
|
||||
--color-success-contrast-950: var(--color-success-contrast-light);
|
||||
--color-warning-50: oklch(95.67% 0.05 84.56deg);
|
||||
--color-warning-100: oklch(92.83% 0.06 82.16deg);
|
||||
--color-warning-200: oklch(90.12% 0.08 80.33deg);
|
||||
--color-warning-300: oklch(87.59% 0.1 80.01deg);
|
||||
--color-warning-400: oklch(85.03% 0.12 78.35deg);
|
||||
--color-warning-500: oklch(82.46% 0.14 76.71deg);
|
||||
--color-warning-600: oklch(76.34% 0.13 72.25deg);
|
||||
--color-warning-700: oklch(70.34% 0.13 68.09deg);
|
||||
--color-warning-800: oklch(63.99% 0.13 63.18deg);
|
||||
--color-warning-900: oklch(57.91% 0.13 57.97deg);
|
||||
--color-warning-950: oklch(51.69% 0.13 51.44deg);
|
||||
--color-warning-contrast-dark: var(--color-warning-950);
|
||||
--color-warning-contrast-light: var(--color-warning-50);
|
||||
--color-warning-contrast-50: var(--color-warning-contrast-dark);
|
||||
--color-warning-contrast-100: var(--color-warning-contrast-dark);
|
||||
--color-warning-contrast-200: var(--color-warning-contrast-dark);
|
||||
--color-warning-contrast-300: var(--color-warning-contrast-dark);
|
||||
--color-warning-contrast-400: var(--color-warning-contrast-dark);
|
||||
--color-warning-contrast-500: var(--color-warning-contrast-dark);
|
||||
--color-warning-contrast-600: var(--color-warning-contrast-light);
|
||||
--color-warning-contrast-700: var(--color-warning-contrast-light);
|
||||
--color-warning-contrast-800: var(--color-warning-contrast-light);
|
||||
--color-warning-contrast-900: var(--color-warning-contrast-light);
|
||||
--color-warning-contrast-950: var(--color-warning-contrast-light);
|
||||
--color-error-50: oklch(84.29% 0.09 46.91deg);
|
||||
--color-error-100: oklch(78.63% 0.12 39.19deg);
|
||||
--color-error-200: oklch(72.92% 0.14 34.35deg);
|
||||
--color-error-300: oklch(67.88% 0.17 31.48deg);
|
||||
--color-error-400: oklch(63.09% 0.19 30.02deg);
|
||||
--color-error-500: oklch(59.32% 0.21 29.47deg);
|
||||
--color-error-600: oklch(53.56% 0.19 29.25deg);
|
||||
--color-error-700: oklch(47.75% 0.17 29.2deg);
|
||||
--color-error-800: oklch(41.51% 0.15 28.7deg);
|
||||
--color-error-900: oklch(35.35% 0.14 28.7deg);
|
||||
--color-error-950: oklch(28.69% 0.12 29.23deg);
|
||||
--color-error-contrast-dark: var(--color-error-950);
|
||||
--color-error-contrast-light: var(--color-error-50);
|
||||
--color-error-contrast-50: var(--color-error-contrast-dark);
|
||||
--color-error-contrast-100: var(--color-error-contrast-dark);
|
||||
--color-error-contrast-200: var(--color-error-contrast-dark);
|
||||
--color-error-contrast-300: var(--color-error-contrast-dark);
|
||||
--color-error-contrast-400: var(--color-error-contrast-dark);
|
||||
--color-error-contrast-500: var(--color-error-contrast-light);
|
||||
--color-error-contrast-600: var(--color-error-contrast-light);
|
||||
--color-error-contrast-700: var(--color-error-contrast-light);
|
||||
--color-error-contrast-800: var(--color-error-contrast-light);
|
||||
--color-error-contrast-900: var(--color-error-contrast-light);
|
||||
--color-error-contrast-950: var(--color-error-contrast-light);
|
||||
--color-surface-50: oklch(100% 0 none);
|
||||
--color-surface-100: oklch(97.02% 0 none);
|
||||
--color-surface-200: oklch(94.01% 0 none);
|
||||
--color-surface-300: oklch(91.12% 0 196.34deg);
|
||||
--color-surface-400: oklch(88.07% 0 196.37deg);
|
||||
--color-surface-500: oklch(84.99% 0 196.4deg);
|
||||
--color-surface-600: oklch(77.78% 0 196.47deg);
|
||||
--color-surface-700: oklch(70.09% 0 196.54deg);
|
||||
--color-surface-800: oklch(62.51% 0 196.61deg);
|
||||
--color-surface-900: oklch(54.34% 0 196.68deg);
|
||||
--color-surface-950: oklch(46.22% 0 196.73deg);
|
||||
--color-surface-contrast-dark: var(--color-surface-950);
|
||||
--color-surface-contrast-light: var(--color-surface-50);
|
||||
--color-surface-contrast-50: var(--color-surface-contrast-dark);
|
||||
--color-surface-contrast-100: var(--color-surface-contrast-dark);
|
||||
--color-surface-contrast-200: var(--color-surface-contrast-dark);
|
||||
--color-surface-contrast-300: var(--color-surface-contrast-dark);
|
||||
--color-surface-contrast-400: var(--color-surface-contrast-dark);
|
||||
--color-surface-contrast-500: var(--color-surface-contrast-dark);
|
||||
--color-surface-contrast-600: var(--color-surface-contrast-dark);
|
||||
--color-surface-contrast-700: var(--color-surface-contrast-dark);
|
||||
--color-surface-contrast-800: var(--color-surface-contrast-dark);
|
||||
--color-surface-contrast-900: var(--color-surface-contrast-light);
|
||||
--color-surface-contrast-950: var(--color-surface-contrast-light);
|
||||
}
|
||||
205
src/ae-osit-default.css
Normal file
205
src/ae-osit-default.css
Normal file
@@ -0,0 +1,205 @@
|
||||
[data-theme='AE_OSIT_default'] {
|
||||
--text-scaling: 1.067;
|
||||
--base-font-color: var(--color-surface-950);
|
||||
--base-font-color-dark: var(--color-surface-50);
|
||||
--base-font-family: system-ui, sans-serif;
|
||||
--base-font-size: inherit;
|
||||
--base-line-height: inherit;
|
||||
--base-font-weight: normal;
|
||||
--base-font-style: normal;
|
||||
--base-letter-spacing: 0em;
|
||||
--heading-font-color: inherit;
|
||||
--heading-font-color-dark: inherit;
|
||||
--heading-font-family: inherit;
|
||||
--heading-font-weight: bold;
|
||||
--heading-font-style: normal;
|
||||
--heading-letter-spacing: inherit;
|
||||
--anchor-font-color: var(--color-primary-600);
|
||||
--anchor-font-color-dark: var(--color-primary-400);
|
||||
--anchor-font-family: inherit;
|
||||
--anchor-font-size: inherit;
|
||||
--anchor-line-height: inherit;
|
||||
--anchor-font-weight: inherit;
|
||||
--anchor-font-style: inherit;
|
||||
--anchor-letter-spacing: inherit;
|
||||
--anchor-text-decoration: none;
|
||||
--anchor-text-decoration-hover: underline;
|
||||
--anchor-text-decoration-active: none;
|
||||
--anchor-text-decoration-focus: none;
|
||||
--spacing: 0.25rem;
|
||||
--radius-base: 0.375rem;
|
||||
--radius-container: 0.75rem;
|
||||
--default-border-width: 1px;
|
||||
--default-divide-width: 1px;
|
||||
--default-ring-width: 1px;
|
||||
--body-background-color: var(--color-surface-50);
|
||||
--body-background-color-dark: var(--color-surface-950);
|
||||
--color-primary-50: oklch(85.73% 0.07 251.8deg);
|
||||
--color-primary-100: oklch(78.5% 0.09 252.03deg);
|
||||
--color-primary-200: oklch(71.06% 0.1 253.6deg);
|
||||
--color-primary-300: oklch(63.76% 0.12 253.85deg);
|
||||
--color-primary-400: oklch(56.32% 0.14 255.25deg);
|
||||
--color-primary-500: oklch(49.23% 0.15 256.36deg);
|
||||
--color-primary-600: oklch(43.11% 0.14 258.86deg);
|
||||
--color-primary-700: oklch(36.85% 0.14 261.54deg);
|
||||
--color-primary-800: oklch(30.41% 0.13 263.99deg);
|
||||
--color-primary-900: oklch(23.91% 0.12 265.91deg);
|
||||
--color-primary-950: oklch(16.96% 0.12 264.05deg);
|
||||
--color-primary-contrast-dark: var(--color-primary-950);
|
||||
--color-primary-contrast-light: var(--color-primary-50);
|
||||
--color-primary-contrast-50: var(--color-primary-contrast-dark);
|
||||
--color-primary-contrast-100: var(--color-primary-contrast-dark);
|
||||
--color-primary-contrast-200: var(--color-primary-contrast-dark);
|
||||
--color-primary-contrast-300: var(--color-primary-contrast-dark);
|
||||
--color-primary-contrast-400: var(--color-primary-contrast-dark);
|
||||
--color-primary-contrast-500: var(--color-primary-contrast-light);
|
||||
--color-primary-contrast-600: var(--color-primary-contrast-light);
|
||||
--color-primary-contrast-700: var(--color-primary-contrast-light);
|
||||
--color-primary-contrast-800: var(--color-primary-contrast-light);
|
||||
--color-primary-contrast-900: var(--color-primary-contrast-light);
|
||||
--color-primary-contrast-950: var(--color-primary-contrast-light);
|
||||
--color-secondary-50: oklch(96.26% 0.06 196.24deg);
|
||||
--color-secondary-100: oklch(89.14% 0.07 220.79deg);
|
||||
--color-secondary-200: oklch(82.13% 0.08 234.87deg);
|
||||
--color-secondary-300: oklch(75.03% 0.11 245.33deg);
|
||||
--color-secondary-400: oklch(68.15% 0.14 250.72deg);
|
||||
--color-secondary-500: oklch(61.37% 0.16 255.34deg);
|
||||
--color-secondary-600: oklch(55.1% 0.16 256.81deg);
|
||||
--color-secondary-700: oklch(48.64% 0.15 258.4deg);
|
||||
--color-secondary-800: oklch(41.84% 0.15 260.39deg);
|
||||
--color-secondary-900: oklch(35.05% 0.14 262.03deg);
|
||||
--color-secondary-950: oklch(28.12% 0.14 262.47deg);
|
||||
--color-secondary-contrast-dark: var(--color-secondary-950);
|
||||
--color-secondary-contrast-light: var(--color-secondary-50);
|
||||
--color-secondary-contrast-50: var(--color-secondary-contrast-dark);
|
||||
--color-secondary-contrast-100: var(--color-secondary-contrast-dark);
|
||||
--color-secondary-contrast-200: var(--color-secondary-contrast-dark);
|
||||
--color-secondary-contrast-300: var(--color-secondary-contrast-dark);
|
||||
--color-secondary-contrast-400: var(--color-secondary-contrast-dark);
|
||||
--color-secondary-contrast-500: var(--color-secondary-contrast-dark);
|
||||
--color-secondary-contrast-600: var(--color-secondary-contrast-light);
|
||||
--color-secondary-contrast-700: var(--color-secondary-contrast-light);
|
||||
--color-secondary-contrast-800: var(--color-secondary-contrast-light);
|
||||
--color-secondary-contrast-900: var(--color-secondary-contrast-light);
|
||||
--color-secondary-contrast-950: var(--color-secondary-contrast-light);
|
||||
--color-tertiary-50: oklch(100% 0 none);
|
||||
--color-tertiary-100: oklch(96.07% 0.01 251.15deg);
|
||||
--color-tertiary-200: oklch(91.88% 0.03 252.69deg);
|
||||
--color-tertiary-300: oklch(87.99% 0.05 253.24deg);
|
||||
--color-tertiary-400: oklch(83.81% 0.06 253.57deg);
|
||||
--color-tertiary-500: oklch(79.93% 0.08 253.32deg);
|
||||
--color-tertiary-600: oklch(72.53% 0.08 251.75deg);
|
||||
--color-tertiary-700: oklch(64.93% 0.08 249.75deg);
|
||||
--color-tertiary-800: oklch(57.14% 0.09 247.99deg);
|
||||
--color-tertiary-900: oklch(49.18% 0.09 246.55deg);
|
||||
--color-tertiary-950: oklch(41.1% 0.09 246.54deg);
|
||||
--color-tertiary-contrast-dark: var(--color-tertiary-950);
|
||||
--color-tertiary-contrast-light: var(--color-tertiary-50);
|
||||
--color-tertiary-contrast-50: var(--color-tertiary-contrast-dark);
|
||||
--color-tertiary-contrast-100: var(--color-tertiary-contrast-dark);
|
||||
--color-tertiary-contrast-200: var(--color-tertiary-contrast-dark);
|
||||
--color-tertiary-contrast-300: var(--color-tertiary-contrast-dark);
|
||||
--color-tertiary-contrast-400: var(--color-tertiary-contrast-dark);
|
||||
--color-tertiary-contrast-500: var(--color-tertiary-contrast-dark);
|
||||
--color-tertiary-contrast-600: var(--color-tertiary-contrast-dark);
|
||||
--color-tertiary-contrast-700: var(--color-tertiary-contrast-dark);
|
||||
--color-tertiary-contrast-800: var(--color-tertiary-contrast-light);
|
||||
--color-tertiary-contrast-900: var(--color-tertiary-contrast-light);
|
||||
--color-tertiary-contrast-950: var(--color-tertiary-contrast-light);
|
||||
--color-success-50: oklch(95.82% 0.06 184.52deg);
|
||||
--color-success-100: oklch(91.55% 0.08 172.29deg);
|
||||
--color-success-200: oklch(87.44% 0.11 165.22deg);
|
||||
--color-success-300: oklch(83.26% 0.13 161.2deg);
|
||||
--color-success-400: oklch(79.56% 0.16 157.13deg);
|
||||
--color-success-500: oklch(76.12% 0.18 153.61deg);
|
||||
--color-success-600: oklch(69.31% 0.17 151.81deg);
|
||||
--color-success-700: oklch(62.07% 0.16 149.95deg);
|
||||
--color-success-800: oklch(54.9% 0.15 147.65deg);
|
||||
--color-success-900: oklch(47.26% 0.14 145.54deg);
|
||||
--color-success-950: oklch(39.64% 0.13 143.79deg);
|
||||
--color-success-contrast-dark: var(--color-success-950);
|
||||
--color-success-contrast-light: var(--color-success-50);
|
||||
--color-success-contrast-50: var(--color-success-contrast-dark);
|
||||
--color-success-contrast-100: var(--color-success-contrast-dark);
|
||||
--color-success-contrast-200: var(--color-success-contrast-dark);
|
||||
--color-success-contrast-300: var(--color-success-contrast-dark);
|
||||
--color-success-contrast-400: var(--color-success-contrast-dark);
|
||||
--color-success-contrast-500: var(--color-success-contrast-dark);
|
||||
--color-success-contrast-600: var(--color-success-contrast-dark);
|
||||
--color-success-contrast-700: var(--color-success-contrast-dark);
|
||||
--color-success-contrast-800: var(--color-success-contrast-light);
|
||||
--color-success-contrast-900: var(--color-success-contrast-light);
|
||||
--color-success-contrast-950: var(--color-success-contrast-light);
|
||||
--color-warning-50: oklch(98.26% 0.1 108.02deg);
|
||||
--color-warning-100: oklch(95.84% 0.12 104.66deg);
|
||||
--color-warning-200: oklch(93.48% 0.13 102.21deg);
|
||||
--color-warning-300: oklch(91.49% 0.15 100.17deg);
|
||||
--color-warning-400: oklch(89.28% 0.16 98.19deg);
|
||||
--color-warning-500: oklch(87.14% 0.17 96.01deg);
|
||||
--color-warning-600: oklch(79.88% 0.16 96.31deg);
|
||||
--color-warning-700: oklch(72.35% 0.14 95.62deg);
|
||||
--color-warning-800: oklch(64.73% 0.13 95.92deg);
|
||||
--color-warning-900: oklch(56.77% 0.11 94.87deg);
|
||||
--color-warning-950: oklch(48.63% 0.1 95.22deg);
|
||||
--color-warning-contrast-dark: var(--color-warning-950);
|
||||
--color-warning-contrast-light: var(--color-warning-50);
|
||||
--color-warning-contrast-50: var(--color-warning-contrast-dark);
|
||||
--color-warning-contrast-100: var(--color-warning-contrast-dark);
|
||||
--color-warning-contrast-200: var(--color-warning-contrast-dark);
|
||||
--color-warning-contrast-300: var(--color-warning-contrast-dark);
|
||||
--color-warning-contrast-400: var(--color-warning-contrast-dark);
|
||||
--color-warning-contrast-500: var(--color-warning-contrast-dark);
|
||||
--color-warning-contrast-600: var(--color-warning-contrast-dark);
|
||||
--color-warning-contrast-700: var(--color-warning-contrast-dark);
|
||||
--color-warning-contrast-800: var(--color-warning-contrast-light);
|
||||
--color-warning-contrast-900: var(--color-warning-contrast-light);
|
||||
--color-warning-contrast-950: var(--color-warning-contrast-light);
|
||||
--color-error-50: oklch(81.88% 0.1 38.14deg);
|
||||
--color-error-100: oklch(75.88% 0.13 31.15deg);
|
||||
--color-error-200: oklch(70.29% 0.16 27.32deg);
|
||||
--color-error-300: oklch(65.15% 0.19 25.65deg);
|
||||
--color-error-400: oklch(60.98% 0.21 25.56deg);
|
||||
--color-error-500: oklch(57.86% 0.22 26.62deg);
|
||||
--color-error-600: oklch(52.52% 0.2 26.86deg);
|
||||
--color-error-700: oklch(46.81% 0.18 27.02deg);
|
||||
--color-error-800: oklch(41.15% 0.16 27.63deg);
|
||||
--color-error-900: oklch(35.01% 0.14 27.9deg);
|
||||
--color-error-950: oklch(28.69% 0.12 29.23deg);
|
||||
--color-error-contrast-dark: var(--color-error-950);
|
||||
--color-error-contrast-light: var(--color-error-50);
|
||||
--color-error-contrast-50: var(--color-error-contrast-dark);
|
||||
--color-error-contrast-100: var(--color-error-contrast-dark);
|
||||
--color-error-contrast-200: var(--color-error-contrast-dark);
|
||||
--color-error-contrast-300: var(--color-error-contrast-dark);
|
||||
--color-error-contrast-400: var(--color-error-contrast-light);
|
||||
--color-error-contrast-500: var(--color-error-contrast-light);
|
||||
--color-error-contrast-600: var(--color-error-contrast-light);
|
||||
--color-error-contrast-700: var(--color-error-contrast-light);
|
||||
--color-error-contrast-800: var(--color-error-contrast-light);
|
||||
--color-error-contrast-900: var(--color-error-contrast-light);
|
||||
--color-error-contrast-950: var(--color-error-contrast-light);
|
||||
--color-surface-50: oklch(100% 0 none);
|
||||
--color-surface-100: oklch(93.98% 0 105.57deg);
|
||||
--color-surface-200: oklch(87.66% 0 67.88deg);
|
||||
--color-surface-300: oklch(81.35% 0 106.1deg);
|
||||
--color-surface-400: oklch(74.79% 0 84.45deg);
|
||||
--color-surface-500: oklch(68.29% 0 91.36deg);
|
||||
--color-surface-600: oklch(60.99% 0 91.38deg);
|
||||
--color-surface-700: oklch(53.5% 0 84.49deg);
|
||||
--color-surface-800: oklch(46.03% 0 91.43deg);
|
||||
--color-surface-900: oklch(37.94% 0 84.52deg);
|
||||
--color-surface-950: oklch(29.34% 0 84.54deg);
|
||||
--color-surface-contrast-dark: var(--color-surface-950);
|
||||
--color-surface-contrast-light: var(--color-surface-50);
|
||||
--color-surface-contrast-50: var(--color-surface-contrast-dark);
|
||||
--color-surface-contrast-100: var(--color-surface-contrast-dark);
|
||||
--color-surface-contrast-200: var(--color-surface-contrast-dark);
|
||||
--color-surface-contrast-300: var(--color-surface-contrast-dark);
|
||||
--color-surface-contrast-400: var(--color-surface-contrast-dark);
|
||||
--color-surface-contrast-500: var(--color-surface-contrast-dark);
|
||||
--color-surface-contrast-600: var(--color-surface-contrast-dark);
|
||||
--color-surface-contrast-700: var(--color-surface-contrast-light);
|
||||
--color-surface-contrast-800: var(--color-surface-contrast-light);
|
||||
--color-surface-contrast-900: var(--color-surface-contrast-light);
|
||||
--color-surface-contrast-950: var(--color-surface-contrast-light);
|
||||
}
|
||||
205
src/aeclci_v1.css
Normal file
205
src/aeclci_v1.css
Normal file
@@ -0,0 +1,205 @@
|
||||
[data-theme='aeclci'] {
|
||||
--text-scaling: 1.067;
|
||||
--base-font-color: var(--color-surface-950);
|
||||
--base-font-color-dark: var(--color-surface-50);
|
||||
--base-font-family: system-ui, sans-serif;
|
||||
--base-font-size: inherit;
|
||||
--base-line-height: inherit;
|
||||
--base-font-weight: normal;
|
||||
--base-font-style: normal;
|
||||
--base-letter-spacing: 0em;
|
||||
--heading-font-color: inherit;
|
||||
--heading-font-color-dark: inherit;
|
||||
--heading-font-family: inherit;
|
||||
--heading-font-weight: bold;
|
||||
--heading-font-style: normal;
|
||||
--heading-letter-spacing: inherit;
|
||||
--anchor-font-color: var(--color-primary-500);
|
||||
--anchor-font-color-dark: var(--color-primary-500);
|
||||
--anchor-font-family: inherit;
|
||||
--anchor-font-size: inherit;
|
||||
--anchor-line-height: inherit;
|
||||
--anchor-font-weight: inherit;
|
||||
--anchor-font-style: inherit;
|
||||
--anchor-letter-spacing: inherit;
|
||||
--anchor-text-decoration: none;
|
||||
--anchor-text-decoration-hover: underline;
|
||||
--anchor-text-decoration-active: none;
|
||||
--anchor-text-decoration-focus: none;
|
||||
--spacing: 0.25rem;
|
||||
--radius-base: 0.375rem;
|
||||
--radius-container: 0.75rem;
|
||||
--default-border-width: 1px;
|
||||
--default-divide-width: 1px;
|
||||
--default-ring-width: 1px;
|
||||
--body-background-color: var(--color-surface-50);
|
||||
--body-background-color-dark: var(--color-surface-950);
|
||||
--color-primary-50: oklch(85.1% 0.07 265.19deg);
|
||||
--color-primary-100: oklch(77.89% 0.08 264.31deg);
|
||||
--color-primary-200: oklch(70.32% 0.08 264.44deg);
|
||||
--color-primary-300: oklch(62.86% 0.09 263.87deg);
|
||||
--color-primary-400: oklch(54.96% 0.1 263.8deg);
|
||||
--color-primary-500: oklch(47.12% 0.11 262.88deg);
|
||||
--color-primary-600: oklch(40.9% 0.1 264.73deg);
|
||||
--color-primary-700: oklch(34.53% 0.1 267.34deg);
|
||||
--color-primary-800: oklch(28.16% 0.09 268.81deg);
|
||||
--color-primary-900: oklch(21.29% 0.09 271.12deg);
|
||||
--color-primary-950: oklch(12.88% 0.09 264.05deg);
|
||||
--color-primary-contrast-dark: var(--color-primary-950);
|
||||
--color-primary-contrast-light: var(--color-primary-50);
|
||||
--color-primary-contrast-50: var(--color-primary-contrast-dark);
|
||||
--color-primary-contrast-100: var(--color-primary-contrast-dark);
|
||||
--color-primary-contrast-200: var(--color-primary-contrast-dark);
|
||||
--color-primary-contrast-300: var(--color-primary-contrast-dark);
|
||||
--color-primary-contrast-400: var(--color-primary-contrast-dark);
|
||||
--color-primary-contrast-500: var(--color-primary-contrast-light);
|
||||
--color-primary-contrast-600: var(--color-primary-contrast-light);
|
||||
--color-primary-contrast-700: var(--color-primary-contrast-light);
|
||||
--color-primary-contrast-800: var(--color-primary-contrast-light);
|
||||
--color-primary-contrast-900: var(--color-primary-contrast-light);
|
||||
--color-primary-contrast-950: var(--color-primary-contrast-light);
|
||||
--color-secondary-50: oklch(73.24% 0.12 278.78deg);
|
||||
--color-secondary-100: oklch(65.76% 0.12 276.12deg);
|
||||
--color-secondary-200: oklch(58.15% 0.12 273.33deg);
|
||||
--color-secondary-300: oklch(50.59% 0.12 270.28deg);
|
||||
--color-secondary-400: oklch(42.65% 0.12 267.23deg);
|
||||
--color-secondary-500: oklch(34.53% 0.12 264.22deg);
|
||||
--color-secondary-600: oklch(30.3% 0.11 264.59deg);
|
||||
--color-secondary-700: oklch(25.96% 0.09 265.69deg);
|
||||
--color-secondary-800: oklch(21.25% 0.08 267.5deg);
|
||||
--color-secondary-900: oklch(16.42% 0.06 269.55deg);
|
||||
--color-secondary-950: oklch(8.85% 0.06 264.05deg);
|
||||
--color-secondary-contrast-dark: var(--color-secondary-950);
|
||||
--color-secondary-contrast-light: var(--color-secondary-50);
|
||||
--color-secondary-contrast-50: var(--color-secondary-contrast-dark);
|
||||
--color-secondary-contrast-100: var(--color-secondary-contrast-dark);
|
||||
--color-secondary-contrast-200: var(--color-secondary-contrast-dark);
|
||||
--color-secondary-contrast-300: var(--color-secondary-contrast-light);
|
||||
--color-secondary-contrast-400: var(--color-secondary-contrast-light);
|
||||
--color-secondary-contrast-500: var(--color-secondary-contrast-light);
|
||||
--color-secondary-contrast-600: var(--color-secondary-contrast-light);
|
||||
--color-secondary-contrast-700: var(--color-secondary-contrast-light);
|
||||
--color-secondary-contrast-800: var(--color-secondary-contrast-light);
|
||||
--color-secondary-contrast-900: var(--color-secondary-contrast-light);
|
||||
--color-secondary-contrast-950: var(--color-secondary-contrast-light);
|
||||
--color-tertiary-50: oklch(87.75% 0.12 326.52deg);
|
||||
--color-tertiary-100: oklch(80.92% 0.13 323.93deg);
|
||||
--color-tertiary-200: oklch(73.87% 0.14 321.55deg);
|
||||
--color-tertiary-300: oklch(66.9% 0.15 319.41deg);
|
||||
--color-tertiary-400: oklch(59.72% 0.16 317.25deg);
|
||||
--color-tertiary-500: oklch(52.73% 0.17 315.13deg);
|
||||
--color-tertiary-600: oklch(46.6% 0.16 314.18deg);
|
||||
--color-tertiary-700: oklch(40.43% 0.14 312.8deg);
|
||||
--color-tertiary-800: oklch(33.85% 0.13 309.88deg);
|
||||
--color-tertiary-900: oklch(27.23% 0.12 306.83deg);
|
||||
--color-tertiary-950: oklch(19.83% 0.1 302.7deg);
|
||||
--color-tertiary-contrast-dark: var(--color-tertiary-950);
|
||||
--color-tertiary-contrast-light: var(--color-tertiary-50);
|
||||
--color-tertiary-contrast-50: var(--color-tertiary-contrast-dark);
|
||||
--color-tertiary-contrast-100: var(--color-tertiary-contrast-dark);
|
||||
--color-tertiary-contrast-200: var(--color-tertiary-contrast-dark);
|
||||
--color-tertiary-contrast-300: var(--color-tertiary-contrast-dark);
|
||||
--color-tertiary-contrast-400: var(--color-tertiary-contrast-light);
|
||||
--color-tertiary-contrast-500: var(--color-tertiary-contrast-light);
|
||||
--color-tertiary-contrast-600: var(--color-tertiary-contrast-light);
|
||||
--color-tertiary-contrast-700: var(--color-tertiary-contrast-light);
|
||||
--color-tertiary-contrast-800: var(--color-tertiary-contrast-light);
|
||||
--color-tertiary-contrast-900: var(--color-tertiary-contrast-light);
|
||||
--color-tertiary-contrast-950: var(--color-tertiary-contrast-light);
|
||||
--color-success-50: oklch(95.23% 0.07 195.99deg);
|
||||
--color-success-100: oklch(90.22% 0.09 189.46deg);
|
||||
--color-success-200: oklch(85.11% 0.1 186.03deg);
|
||||
--color-success-300: oklch(80.35% 0.12 181.75deg);
|
||||
--color-success-400: oklch(75.55% 0.12 178.92deg);
|
||||
--color-success-500: oklch(71.19% 0.13 174.73deg);
|
||||
--color-success-600: oklch(64.29% 0.12 173.65deg);
|
||||
--color-success-700: oklch(57.46% 0.11 171.75deg);
|
||||
--color-success-800: oklch(50.18% 0.1 170.68deg);
|
||||
--color-success-900: oklch(42.87% 0.09 167.65deg);
|
||||
--color-success-950: oklch(34.91% 0.07 164.42deg);
|
||||
--color-success-contrast-dark: var(--color-success-950);
|
||||
--color-success-contrast-light: var(--color-success-50);
|
||||
--color-success-contrast-50: var(--color-success-contrast-dark);
|
||||
--color-success-contrast-100: var(--color-success-contrast-dark);
|
||||
--color-success-contrast-200: var(--color-success-contrast-dark);
|
||||
--color-success-contrast-300: var(--color-success-contrast-dark);
|
||||
--color-success-contrast-400: var(--color-success-contrast-dark);
|
||||
--color-success-contrast-500: var(--color-success-contrast-dark);
|
||||
--color-success-contrast-600: var(--color-success-contrast-dark);
|
||||
--color-success-contrast-700: var(--color-success-contrast-light);
|
||||
--color-success-contrast-800: var(--color-success-contrast-light);
|
||||
--color-success-contrast-900: var(--color-success-contrast-light);
|
||||
--color-success-contrast-950: var(--color-success-contrast-light);
|
||||
--color-warning-50: oklch(95.67% 0.05 84.56deg);
|
||||
--color-warning-100: oklch(92.83% 0.06 82.16deg);
|
||||
--color-warning-200: oklch(90.12% 0.08 80.33deg);
|
||||
--color-warning-300: oklch(87.59% 0.1 80.01deg);
|
||||
--color-warning-400: oklch(85.03% 0.12 78.35deg);
|
||||
--color-warning-500: oklch(82.46% 0.14 76.71deg);
|
||||
--color-warning-600: oklch(76.34% 0.13 72.25deg);
|
||||
--color-warning-700: oklch(70.34% 0.13 68.09deg);
|
||||
--color-warning-800: oklch(63.99% 0.13 63.18deg);
|
||||
--color-warning-900: oklch(57.91% 0.13 57.97deg);
|
||||
--color-warning-950: oklch(51.69% 0.13 51.44deg);
|
||||
--color-warning-contrast-dark: var(--color-warning-950);
|
||||
--color-warning-contrast-light: var(--color-warning-50);
|
||||
--color-warning-contrast-50: var(--color-warning-contrast-dark);
|
||||
--color-warning-contrast-100: var(--color-warning-contrast-dark);
|
||||
--color-warning-contrast-200: var(--color-warning-contrast-dark);
|
||||
--color-warning-contrast-300: var(--color-warning-contrast-dark);
|
||||
--color-warning-contrast-400: var(--color-warning-contrast-dark);
|
||||
--color-warning-contrast-500: var(--color-warning-contrast-dark);
|
||||
--color-warning-contrast-600: var(--color-warning-contrast-light);
|
||||
--color-warning-contrast-700: var(--color-warning-contrast-light);
|
||||
--color-warning-contrast-800: var(--color-warning-contrast-light);
|
||||
--color-warning-contrast-900: var(--color-warning-contrast-light);
|
||||
--color-warning-contrast-950: var(--color-warning-contrast-light);
|
||||
--color-error-50: oklch(84.29% 0.09 46.91deg);
|
||||
--color-error-100: oklch(78.63% 0.12 39.19deg);
|
||||
--color-error-200: oklch(72.92% 0.14 34.35deg);
|
||||
--color-error-300: oklch(67.88% 0.17 31.48deg);
|
||||
--color-error-400: oklch(63.09% 0.19 30.02deg);
|
||||
--color-error-500: oklch(59.32% 0.21 29.47deg);
|
||||
--color-error-600: oklch(53.56% 0.19 29.25deg);
|
||||
--color-error-700: oklch(47.75% 0.17 29.2deg);
|
||||
--color-error-800: oklch(41.51% 0.15 28.7deg);
|
||||
--color-error-900: oklch(35.35% 0.14 28.7deg);
|
||||
--color-error-950: oklch(28.69% 0.12 29.23deg);
|
||||
--color-error-contrast-dark: var(--color-error-950);
|
||||
--color-error-contrast-light: var(--color-error-50);
|
||||
--color-error-contrast-50: var(--color-error-contrast-dark);
|
||||
--color-error-contrast-100: var(--color-error-contrast-dark);
|
||||
--color-error-contrast-200: var(--color-error-contrast-dark);
|
||||
--color-error-contrast-300: var(--color-error-contrast-dark);
|
||||
--color-error-contrast-400: var(--color-error-contrast-dark);
|
||||
--color-error-contrast-500: var(--color-error-contrast-light);
|
||||
--color-error-contrast-600: var(--color-error-contrast-light);
|
||||
--color-error-contrast-700: var(--color-error-contrast-light);
|
||||
--color-error-contrast-800: var(--color-error-contrast-light);
|
||||
--color-error-contrast-900: var(--color-error-contrast-light);
|
||||
--color-error-contrast-950: var(--color-error-contrast-light);
|
||||
--color-surface-50: oklch(100% 0 none);
|
||||
--color-surface-100: oklch(97.02% 0 none);
|
||||
--color-surface-200: oklch(94.01% 0 none);
|
||||
--color-surface-300: oklch(91.12% 0 196.34deg);
|
||||
--color-surface-400: oklch(88.07% 0 196.37deg);
|
||||
--color-surface-500: oklch(84.99% 0 196.4deg);
|
||||
--color-surface-600: oklch(77.78% 0 196.47deg);
|
||||
--color-surface-700: oklch(70.09% 0 196.54deg);
|
||||
--color-surface-800: oklch(62.51% 0 196.61deg);
|
||||
--color-surface-900: oklch(54.34% 0 196.68deg);
|
||||
--color-surface-950: oklch(46.22% 0 196.73deg);
|
||||
--color-surface-contrast-dark: var(--color-surface-950);
|
||||
--color-surface-contrast-light: var(--color-surface-50);
|
||||
--color-surface-contrast-50: var(--color-surface-contrast-dark);
|
||||
--color-surface-contrast-100: var(--color-surface-contrast-dark);
|
||||
--color-surface-contrast-200: var(--color-surface-contrast-dark);
|
||||
--color-surface-contrast-300: var(--color-surface-contrast-dark);
|
||||
--color-surface-contrast-400: var(--color-surface-contrast-dark);
|
||||
--color-surface-contrast-500: var(--color-surface-contrast-dark);
|
||||
--color-surface-contrast-600: var(--color-surface-contrast-dark);
|
||||
--color-surface-contrast-700: var(--color-surface-contrast-dark);
|
||||
--color-surface-contrast-800: var(--color-surface-contrast-dark);
|
||||
--color-surface-contrast-900: var(--color-surface-contrast-light);
|
||||
--color-surface-contrast-950: var(--color-surface-contrast-light);
|
||||
}
|
||||
1555
src/app.css
1555
src/app.css
File diff suppressed because it is too large
Load Diff
9
src/app.d.ts
vendored
Normal file
9
src/app.d.ts
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
// See https://kit.svelte.dev/docs/types#app
|
||||
// for information about these interfaces
|
||||
// and what to do when importing types
|
||||
declare namespace App {
|
||||
// interface Locals {}
|
||||
// interface PageData {}
|
||||
// interface Error {}
|
||||
// interface Platform {}
|
||||
}
|
||||
43
src/app.html
Normal file
43
src/app.html
Normal file
@@ -0,0 +1,43 @@
|
||||
<!doctype html>
|
||||
<html lang="en" class="light" data-theme="">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
|
||||
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
|
||||
<link rel="manifest" href="%sveltekit.assets%/manifest.json" />
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" />
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,400;0,700;1,400;1,700&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Noto+Serif:ital,wght@0,400;0,700;1,400;1,700&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Roboto+Mono:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;1,100;1,200;1,300;1,400;1,500;1,600;1,700&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css"
|
||||
integrity="sha512-1ycn6IcaQQ40/MKBW2W4Rhis/DbILU74C1vSrLJxCq57o941Ym01SwNsOMqvEBFlcgUa6xLiPY/NS5R+E6ztJQ=="
|
||||
crossorigin="anonymous"
|
||||
referrerpolicy="no-referrer"
|
||||
/>
|
||||
|
||||
<!-- <link href="app.css" rel="stylesheet"> -->
|
||||
|
||||
%sveltekit.head%
|
||||
</head>
|
||||
<!-- h-full w-full overflow-auto -->
|
||||
<!-- overflow-x-scroll -->
|
||||
<body data-sveltekit-preload-data="hover" class="h-full w-full">
|
||||
<div style="display: contents" class="">%sveltekit.body%</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="26.6" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 308"><path fill="#FF3E00" d="M239.682 40.707C211.113-.182 154.69-12.301 113.895 13.69L42.247 59.356a82.198 82.198 0 0 0-37.135 55.056a86.566 86.566 0 0 0 8.536 55.576a82.425 82.425 0 0 0-12.296 30.719a87.596 87.596 0 0 0 14.964 66.244c28.574 40.893 84.997 53.007 125.787 27.016l71.648-45.664a82.182 82.182 0 0 0 37.135-55.057a86.601 86.601 0 0 0-8.53-55.577a82.409 82.409 0 0 0 12.29-30.718a87.573 87.573 0 0 0-14.963-66.244"></path><path fill="#FFF" d="M106.889 270.841c-23.102 6.007-47.497-3.036-61.103-22.648a52.685 52.685 0 0 1-9.003-39.85a49.978 49.978 0 0 1 1.713-6.693l1.35-4.115l3.671 2.697a92.447 92.447 0 0 0 28.036 14.007l2.663.808l-.245 2.659a16.067 16.067 0 0 0 2.89 10.656a17.143 17.143 0 0 0 18.397 6.828a15.786 15.786 0 0 0 4.403-1.935l71.67-45.672a14.922 14.922 0 0 0 6.734-9.977a15.923 15.923 0 0 0-2.713-12.011a17.156 17.156 0 0 0-18.404-6.832a15.78 15.78 0 0 0-4.396 1.933l-27.35 17.434a52.298 52.298 0 0 1-14.553 6.391c-23.101 6.007-47.497-3.036-61.101-22.649a52.681 52.681 0 0 1-9.004-39.849a49.428 49.428 0 0 1 22.34-33.114l71.664-45.677a52.218 52.218 0 0 1 14.563-6.398c23.101-6.007 47.497 3.036 61.101 22.648a52.685 52.685 0 0 1 9.004 39.85a50.559 50.559 0 0 1-1.713 6.692l-1.35 4.116l-3.67-2.693a92.373 92.373 0 0 0-28.037-14.013l-2.664-.809l.246-2.658a16.099 16.099 0 0 0-2.89-10.656a17.143 17.143 0 0 0-18.398-6.828a15.786 15.786 0 0 0-4.402 1.935l-71.67 45.674a14.898 14.898 0 0 0-6.73 9.975a15.9 15.9 0 0 0 2.709 12.012a17.156 17.156 0 0 0 18.404 6.832a15.841 15.841 0 0 0 4.402-1.935l27.345-17.427a52.147 52.147 0 0 1 14.552-6.397c23.101-6.006 47.497 3.037 61.102 22.65a52.681 52.681 0 0 1 9.003 39.848a49.453 49.453 0 0 1-22.34 33.12l-71.664 45.673a52.218 52.218 0 0 1-14.563 6.398"></path></svg>
|
||||
|
Before Width: | Height: | Size: 1.9 KiB |
7
src/index.test.ts
Normal file
7
src/index.test.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
|
||||
describe('sum test', () => {
|
||||
it('adds 1 + 2 to equal 3', () => {
|
||||
expect(1 + 2).toBe(3);
|
||||
});
|
||||
});
|
||||
@@ -1,10 +0,0 @@
|
||||
<script lang="ts">
|
||||
let count: number = 0
|
||||
const increment = () => {
|
||||
count += 1
|
||||
}
|
||||
</script>
|
||||
|
||||
<button on:click={increment}>
|
||||
count is {count}
|
||||
</button>
|
||||
130
src/lib/ae_api/api_delete_object.ts
Normal file
130
src/lib/ae_api/api_delete_object.ts
Normal file
@@ -0,0 +1,130 @@
|
||||
// import axios from 'axios';
|
||||
|
||||
// Updated 2024-05-23
|
||||
export const delete_object = async function delete_object({
|
||||
api_cfg = null,
|
||||
endpoint = '',
|
||||
params = {},
|
||||
data = {},
|
||||
return_meta = false,
|
||||
log_lvl = 0,
|
||||
retry_count = 5 // Number of retry attempts
|
||||
}: {
|
||||
api_cfg: any;
|
||||
endpoint: string;
|
||||
params?: any;
|
||||
data?: any;
|
||||
return_meta?: boolean;
|
||||
log_lvl?: number;
|
||||
retry_count?: number;
|
||||
}) {
|
||||
if (log_lvl) {
|
||||
console.log(`*** delete_object() *** Endpoint: ${endpoint}`);
|
||||
console.log('Params:', params);
|
||||
if (log_lvl > 1) {
|
||||
console.log('Data:', data);
|
||||
}
|
||||
}
|
||||
|
||||
if (!api_cfg) {
|
||||
console.error('No API Config was provided. Returning false.');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Construct the URL with query parameters
|
||||
const url = new URL(endpoint, api_cfg['base_url']);
|
||||
Object.keys(params).forEach((key) => url.searchParams.append(key, params[key]));
|
||||
|
||||
// Clean the headers
|
||||
const headers_cleaned: Record<string, string> = {};
|
||||
for (const prop in api_cfg['headers']) {
|
||||
const prop_cleaned = prop.replaceAll('_', '-');
|
||||
headers_cleaned[prop_cleaned] = api_cfg['headers'][prop];
|
||||
}
|
||||
|
||||
if (log_lvl > 1) {
|
||||
console.log('Cleaned Headers:', headers_cleaned);
|
||||
}
|
||||
|
||||
const fetchOptions: RequestInit = {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
...headers_cleaned,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(data)
|
||||
};
|
||||
|
||||
if (log_lvl > 1) {
|
||||
console.log('Fetch Options:', fetchOptions);
|
||||
}
|
||||
|
||||
for (let attempt = 1; attempt <= retry_count; attempt++) {
|
||||
try {
|
||||
const response = await fetch(url.toString(), fetchOptions);
|
||||
|
||||
if (log_lvl) {
|
||||
console.log(`Response: status=${response.status} attempt=${attempt}`);
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
if (response.status === 404) {
|
||||
console.warn('404 Not Found. Returning null.');
|
||||
return null; // Returning null since there were no results
|
||||
}
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
const json = await response.json();
|
||||
|
||||
if (log_lvl > 1) {
|
||||
console.log('Response JSON:', json);
|
||||
}
|
||||
|
||||
// Return the response data or metadata
|
||||
return return_meta ? json : json.data;
|
||||
} catch (error) {
|
||||
console.error(`API DELETE error on attempt ${attempt}:`, error);
|
||||
|
||||
// If this is the last attempt, return false
|
||||
if (attempt === retry_count) {
|
||||
console.error('Max retry attempts reached. Returning false.');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Log retry information
|
||||
if (log_lvl) {
|
||||
console.log(`Retrying... (${attempt}/${retry_count})`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// https://stackoverflow.com/questions/51069552/axios-delete-request-with-body-and-headers
|
||||
|
||||
// let axios_api = axios.create({
|
||||
// baseURL: api_cfg['base_url'],
|
||||
// // timeout: 2000,
|
||||
// /* other custom settings */
|
||||
// });
|
||||
// axios_api.defaults.headers = api_cfg['headers'];
|
||||
|
||||
// //OLD: axios_api.delete(endpoint, { 'data': data })
|
||||
// let response_data = await axios_api.delete(endpoint, { params: params, 'data': data })
|
||||
// .then(function (response) {
|
||||
// console.log(response.data);
|
||||
// return response.data;
|
||||
// })
|
||||
// .catch(function (error: any) {
|
||||
// if (error.response && error.response.status === 404) {
|
||||
// return null; // Returning null since there were no results
|
||||
// }
|
||||
// console.log(error);
|
||||
// return false; // Returning false since something may have gone wrong. Also more in line with what the API returns.
|
||||
// // return error;
|
||||
// });
|
||||
|
||||
// if (log_lvl > 1) {
|
||||
// console.log(response_data);
|
||||
// }
|
||||
// return response_data;
|
||||
};
|
||||
172
src/lib/ae_api/api_get__crud_obj_id.ts
Normal file
172
src/lib/ae_api/api_get__crud_obj_id.ts
Normal file
@@ -0,0 +1,172 @@
|
||||
import type { key_val } from '$lib/stores/ae_stores';
|
||||
import { get_object } from './api_get_object';
|
||||
|
||||
// Updated 2023-12-01
|
||||
export async function get_ae_obj_id_crud({
|
||||
api_cfg,
|
||||
no_account_id = false,
|
||||
obj_type,
|
||||
obj_id,
|
||||
use_alt_table = false,
|
||||
use_alt_base = false,
|
||||
inc = {},
|
||||
enabled = 'enabled',
|
||||
hidden = 'not_hidden',
|
||||
limit = 999999,
|
||||
offset = 0,
|
||||
data = {},
|
||||
// key,
|
||||
// jwt = null,
|
||||
headers = {},
|
||||
params = {},
|
||||
timeout = 25000,
|
||||
return_meta = false,
|
||||
log_lvl = 0
|
||||
}: {
|
||||
api_cfg: any;
|
||||
no_account_id?: boolean;
|
||||
obj_type: string;
|
||||
obj_id: string;
|
||||
use_alt_table?: boolean;
|
||||
use_alt_base?: boolean;
|
||||
inc?: any;
|
||||
enabled?: 'enabled' | 'all' | 'not_enabled' | undefined;
|
||||
hidden?: 'hidden' | 'all' | 'not_hidden' | undefined;
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
data?: any;
|
||||
// key: string,
|
||||
// jwt?: string,
|
||||
headers?: any;
|
||||
params?: key_val;
|
||||
timeout?: number;
|
||||
return_meta?: boolean;
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
if (log_lvl) {
|
||||
console.log('*** get_ae_obj_id_crud() ***');
|
||||
}
|
||||
|
||||
// data = {};
|
||||
// data['super_key'] = key;
|
||||
// data['jwt'] = jwt;
|
||||
// NOTE: The key and or JWT should be in the header of the DELETE, GET, PATCH, POST
|
||||
|
||||
let endpoint = '';
|
||||
if (obj_type == 'account') {
|
||||
endpoint = `/crud/account/${obj_id}`;
|
||||
} else if (obj_type == 'address') {
|
||||
endpoint = `/crud/address/${obj_id}`;
|
||||
} else if (obj_type == 'archive') {
|
||||
endpoint = `/crud/archive/${obj_id}`;
|
||||
} else if (obj_type == 'archive_content') {
|
||||
endpoint = `/crud/archive/content/${obj_id}`;
|
||||
} else if (obj_type == 'contact') {
|
||||
endpoint = `/crud/contact/${obj_id}`;
|
||||
} else if (obj_type == 'data_store') {
|
||||
endpoint = `/crud/data_store/${obj_id}`;
|
||||
} else if (obj_type == 'event') {
|
||||
endpoint = `/crud/event/${obj_id}`;
|
||||
} else if (obj_type == 'event_abstract') {
|
||||
endpoint = `/crud/event/abstract/${obj_id}`;
|
||||
} else if (obj_type == 'event_badge') {
|
||||
endpoint = `/crud/event/badge/${obj_id}`;
|
||||
} else if (obj_type == 'event_device') {
|
||||
endpoint = `/crud/event/device/${obj_id}`;
|
||||
} else if (obj_type == 'event_exhibit') {
|
||||
endpoint = `/crud/event/exhibit/${obj_id}`;
|
||||
} else if (obj_type == 'event_exhibit_tracking') {
|
||||
endpoint = `/crud/event/exhibit/tracking/${obj_id}`;
|
||||
} else if (obj_type == 'event_file') {
|
||||
endpoint = `/crud/event/file/${obj_id}`;
|
||||
} else if (obj_type == 'event_location') {
|
||||
endpoint = `/crud/event/location/${obj_id}`;
|
||||
} else if (obj_type == 'event_person') {
|
||||
endpoint = `/crud/event/person/${obj_id}`;
|
||||
} else if (obj_type == 'event_presentation') {
|
||||
endpoint = `/crud/event/presentation/${obj_id}`;
|
||||
} else if (obj_type == 'event_presenter') {
|
||||
endpoint = `/crud/event/presenter/${obj_id}`;
|
||||
} else if (obj_type == 'event_session') {
|
||||
endpoint = `/crud/event/session/${obj_id}`;
|
||||
} else if (obj_type == 'event_track') {
|
||||
endpoint = `/crud/event/track/${obj_id}`;
|
||||
} else if (obj_type == 'grant') {
|
||||
endpoint = `/crud/grant/${obj_id}`;
|
||||
} else if (obj_type == 'hosted_file') {
|
||||
endpoint = `/crud/hosted_file/${obj_id}`;
|
||||
} else if (obj_type == 'journal') {
|
||||
endpoint = `/crud/journal/${obj_id}`;
|
||||
} else if (obj_type == 'journal_entry') {
|
||||
endpoint = `/crud/journal/entry/${obj_id}`;
|
||||
} else if (obj_type == 'order') {
|
||||
endpoint = `/crud/order/${obj_id}`;
|
||||
} else if (obj_type == 'order_line') {
|
||||
endpoint = `/crud/order/line/${obj_id}`;
|
||||
} else if (obj_type == 'page') {
|
||||
endpoint = `/crud/page/${obj_id}`;
|
||||
} else if (obj_type == 'person') {
|
||||
endpoint = `/crud/person/${obj_id}`;
|
||||
} else if (obj_type == 'post') {
|
||||
endpoint = `/crud/post/${obj_id}`;
|
||||
} else if (obj_type == 'post_comment') {
|
||||
endpoint = `/crud/post/comment/${obj_id}`;
|
||||
} else if (obj_type == 'site') {
|
||||
endpoint = `/crud/site/${obj_id}`;
|
||||
} else if (obj_type == 'site_domain') {
|
||||
endpoint = `/crud/site/domain/${obj_id}`;
|
||||
} else if (obj_type == 'sponsorship_cfg') {
|
||||
endpoint = `/crud/sponsorship/cfg/${obj_id}`;
|
||||
} else if (obj_type == 'sponsorship') {
|
||||
endpoint = `/crud/sponsorship/${obj_id}`;
|
||||
// } else if (obj_type == 'user') {
|
||||
// endpoint = `/crud/user/${obj_id}`;
|
||||
} else {
|
||||
console.log(`Unknown object type: ${obj_type}`);
|
||||
return false;
|
||||
}
|
||||
if (log_lvl) {
|
||||
console.log('Endpoint:', endpoint);
|
||||
}
|
||||
|
||||
params['use_alt_table'] = use_alt_table;
|
||||
params['use_alt_base'] = use_alt_base;
|
||||
|
||||
if (log_lvl) {
|
||||
console.log('Params:', params);
|
||||
}
|
||||
|
||||
if (no_account_id) {
|
||||
headers['x-no-account-id'] = 'Nothing to See Here';
|
||||
delete headers['x-account-id'];
|
||||
delete api_cfg['headers']['x-account-id'];
|
||||
// headers['x-account-id'] = null;
|
||||
// headers['x-account-id'] = '_XY7DXtc9Mxx';
|
||||
// params['x_no_account_id_token'] = 'Nothing to See Here';
|
||||
|
||||
// Remove the x-account-id header
|
||||
// if (headers['x-account-id']) {
|
||||
// delete headers['x-account-id'];
|
||||
// }
|
||||
|
||||
// headers['x-account-id'] = null;
|
||||
// headers['x-no-account-id-token'] = 'Nothing to See Here'; // get_object() will fix the underscores to dashes
|
||||
}
|
||||
|
||||
const object_obj_get_promise = await get_object({
|
||||
api_cfg: api_cfg,
|
||||
endpoint: endpoint,
|
||||
headers: headers,
|
||||
params: params,
|
||||
timeout: timeout,
|
||||
log_lvl: log_lvl
|
||||
}).catch(function (error: any) {
|
||||
console.log('API GET CRUD object ID request failed.', error);
|
||||
});
|
||||
|
||||
if (log_lvl > 1) {
|
||||
console.log('GET Object result =', object_obj_get_promise);
|
||||
}
|
||||
|
||||
return object_obj_get_promise;
|
||||
}
|
||||
229
src/lib/ae_api/api_get__crud_obj_li_v1.ts
Normal file
229
src/lib/ae_api/api_get__crud_obj_li_v1.ts
Normal file
@@ -0,0 +1,229 @@
|
||||
import type { key_val } from '$lib/stores/ae_stores';
|
||||
import { get_object } from './api_get_object';
|
||||
|
||||
// The lookup "obj_type" should broken out into a separate function. - 2024-08-07
|
||||
// Updated 2023-11-15
|
||||
export async function get_ae_obj_li_for_obj_id_crud({
|
||||
api_cfg,
|
||||
obj_type,
|
||||
for_obj_type,
|
||||
for_obj_id, // NOTE: Changed 2023-12-06 to no longer required
|
||||
use_alt_table = false,
|
||||
use_alt_base = false,
|
||||
// inc = {},
|
||||
enabled = 'enabled',
|
||||
hidden = 'not_hidden',
|
||||
order_by_li = null,
|
||||
limit = 999999,
|
||||
offset = 0,
|
||||
// key,
|
||||
// jwt = null,
|
||||
headers = {},
|
||||
params_json = null, // NOTE: This is a JSON object that needs to be safely converted to a string for the params. This is used for the API endpoint. Example: { "fulltext_search": { "default_qry_str": "Search string for default", "address_default_qry_str": "Search string for address", "contact_1_default_qry_str": "Search string for contact_1" } }
|
||||
// json_obj = null, // NOTE: This is a JSON object that needs to be safely converted to a string for the params. This is used for the search endpoint.
|
||||
params = {},
|
||||
return_meta = false,
|
||||
log_lvl = 0
|
||||
}: {
|
||||
api_cfg: any;
|
||||
obj_type: string;
|
||||
for_obj_type: null | string;
|
||||
for_obj_id?: string;
|
||||
use_alt_table?: boolean;
|
||||
use_alt_base?: boolean;
|
||||
// inc?: key_val
|
||||
enabled?: 'enabled' | 'all' | 'not_enabled' | undefined;
|
||||
hidden?: 'hidden' | 'all' | 'not_hidden' | undefined;
|
||||
order_by_li?: any;
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
// key: string,
|
||||
// jwt?: string,
|
||||
headers?: any;
|
||||
params_json?: any;
|
||||
// json_obj?: any,
|
||||
params?: key_val;
|
||||
return_meta?: boolean;
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
if (log_lvl) {
|
||||
console.log(`*** get_ae_obj_li_for_obj_id_crud() *** [${obj_type}]`);
|
||||
}
|
||||
|
||||
// data = {};
|
||||
// data['super_key'] = key;
|
||||
// data['jwt'] = jwt;
|
||||
// NOTE: The key and or JWT should be in the header of the DELETE, GET, PATCH, POST
|
||||
|
||||
// const endpoint = `/crud/${obj_type}/list`;
|
||||
|
||||
let endpoint = '';
|
||||
if (obj_type == 'account') {
|
||||
endpoint = `/crud/account/list`;
|
||||
} else if (obj_type == 'address') {
|
||||
endpoint = `/crud/address/list`;
|
||||
} else if (obj_type == 'archive') {
|
||||
endpoint = `/crud/archive/list`;
|
||||
} else if (obj_type == 'archive_content') {
|
||||
endpoint = `/crud/archive/content/list`;
|
||||
} else if (obj_type == 'contact') {
|
||||
endpoint = `/crud/contact/list`;
|
||||
} else if (obj_type == 'data_store') {
|
||||
endpoint = `/crud/data_store/list`;
|
||||
} else if (obj_type == 'event') {
|
||||
endpoint = `/crud/event/list`;
|
||||
} else if (obj_type == 'event_abstract') {
|
||||
endpoint = `/crud/event/abstract/list`;
|
||||
} else if (obj_type == 'event_badge') {
|
||||
endpoint = `/crud/event/badge/list`;
|
||||
} else if (obj_type == 'event_device') {
|
||||
endpoint = `/crud/event/device/list`;
|
||||
} else if (obj_type == 'event_exhibit') {
|
||||
endpoint = `/crud/event/exhibit/list`;
|
||||
} else if (obj_type == 'event_exhibit_tracking') {
|
||||
endpoint = `/crud/event/exhibit/tracking/list`;
|
||||
} else if (obj_type == 'event_file') {
|
||||
endpoint = `/crud/event/file/list`;
|
||||
} else if (obj_type == 'event_location') {
|
||||
endpoint = `/crud/event/location/list`;
|
||||
} else if (obj_type == 'event_person') {
|
||||
endpoint = `/crud/event/person/list`;
|
||||
} else if (obj_type == 'event_presentation') {
|
||||
endpoint = `/crud/event/presentation/list`;
|
||||
} else if (obj_type == 'event_presenter') {
|
||||
endpoint = `/crud/event/presenter/list`;
|
||||
} else if (obj_type == 'event_session') {
|
||||
endpoint = `/crud/event/session/list`;
|
||||
} else if (obj_type == 'event_track') {
|
||||
endpoint = `/crud/event/track/list`;
|
||||
} else if (obj_type == 'grant') {
|
||||
endpoint = `/crud/grant/list`;
|
||||
} else if (obj_type == 'hosted_file') {
|
||||
endpoint = `/crud/hosted_file/list`;
|
||||
} else if (obj_type == 'journal') {
|
||||
endpoint = `/crud/journal/list`;
|
||||
} else if (obj_type == 'journal_entry') {
|
||||
endpoint = `/crud/journal/entry/list`;
|
||||
} else if (obj_type == 'order') {
|
||||
endpoint = `/crud/order/list`;
|
||||
} else if (obj_type == 'order_line') {
|
||||
endpoint = `/crud/order/line/list`;
|
||||
} else if (obj_type == 'page') {
|
||||
endpoint = `/crud/page/list`;
|
||||
} else if (obj_type == 'person') {
|
||||
endpoint = `/crud/person/list`;
|
||||
} else if (obj_type == 'post') {
|
||||
endpoint = `/crud/post/list`;
|
||||
} else if (obj_type == 'post_comment') {
|
||||
endpoint = `/crud/post/comment/list`;
|
||||
} else if (obj_type == 'site') {
|
||||
endpoint = `/crud/site/list`;
|
||||
} else if (obj_type == 'sponsorship_cfg') {
|
||||
endpoint = `/crud/sponsorship/cfg/list`;
|
||||
} else if (obj_type == 'sponsorship') {
|
||||
endpoint = `/crud/sponsorship/list`;
|
||||
// } else if (obj_type == 'user') {
|
||||
// endpoint = `/crud/user/list`;
|
||||
} else if (obj_type == 'lu' && for_obj_type == 'country_subdivision') {
|
||||
endpoint = `/crud/lu/country_subdivision/list`;
|
||||
for_obj_type = null;
|
||||
} else if (obj_type == 'lu' && for_obj_type == 'country') {
|
||||
endpoint = `/crud/lu/country/list`;
|
||||
for_obj_type = null;
|
||||
} else if (obj_type == 'lu' && for_obj_type == 'time_zone') {
|
||||
endpoint = `/crud/lu/time_zone/list`;
|
||||
for_obj_type = null;
|
||||
} else {
|
||||
console.log(`Unknown object type: ${obj_type}`);
|
||||
return false;
|
||||
}
|
||||
if (log_lvl) {
|
||||
console.log('Endpoint:', endpoint);
|
||||
}
|
||||
|
||||
if (for_obj_type) {
|
||||
params['for_obj_type'] = for_obj_type;
|
||||
}
|
||||
if (for_obj_id) {
|
||||
params['for_obj_id'] = for_obj_id;
|
||||
}
|
||||
|
||||
params['use_alt_table'] = use_alt_table;
|
||||
params['use_alt_base'] = use_alt_base;
|
||||
|
||||
/* Need to deal with inc params here */
|
||||
|
||||
const allowed_enabled_list = ['all', 'enabled', 'not_enabled'];
|
||||
if (allowed_enabled_list.includes(enabled)) {
|
||||
params['enabled'] = enabled;
|
||||
}
|
||||
|
||||
const allowed_hidden_list = ['all', 'hidden', 'not_hidden'];
|
||||
if (allowed_hidden_list.includes(hidden)) {
|
||||
params['hidden'] = hidden;
|
||||
}
|
||||
|
||||
// NOTE: The order_by_li variable is in the "headers" because if is a the URL GET params do not handle multiple values very well. Maybe base64 encore in the future or something? Reminder that GET requests should not have a body (no JSON).
|
||||
// NOTE: The order_by_li should be a key value pair of the property/DB field to sort and how to sort (ASC or DESC)
|
||||
if (order_by_li) {
|
||||
if (log_lvl) {
|
||||
console.log('Order By:', order_by_li);
|
||||
}
|
||||
headers['order_by_li'] = order_by_li;
|
||||
}
|
||||
|
||||
if (limit >= 0) {
|
||||
params['limit'] = limit;
|
||||
}
|
||||
|
||||
if (offset >= 0) {
|
||||
params['offset'] = offset;
|
||||
}
|
||||
|
||||
if (params_json) {
|
||||
// NOTE: This is a JSON object that needs to be safely converted to a string for the params. This is used for the search endpoint.
|
||||
// Max characters for a GET request is 2083. This is a limitation of the browser (Microsoft IE and Edge).
|
||||
if (log_lvl) {
|
||||
console.log('JSON Object:', params_json);
|
||||
console.log(JSON.stringify(params_json));
|
||||
}
|
||||
// NOTE: "jp" stands for "JSON Params"
|
||||
params['jp'] = encodeURIComponent(JSON.stringify(params_json));
|
||||
if (params['jp'].length > 2083) {
|
||||
console.log(
|
||||
`The JSON object is too large to be used as a GET parameter. The overall max URL length is 2083 characters. Please use the POST endpoint instead. Length = ${params['jp'].length} [THIS DOES NOT EXIST YET]`
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// if (json_obj) {
|
||||
// // NOTE: This is a JSON object that needs to be safely converted to a string for the params. This is used for the search endpoint.
|
||||
// // Max characters for a GET request is 2083. This is a limitation of the browser (Microsoft IE and Edge).
|
||||
// console.log('JSON Object:', json_obj);
|
||||
// params['json_str'] = encodeURIComponent(JSON.stringify(json_obj));
|
||||
// if (params['json_str'].length > 2083) {
|
||||
// console.log(`The JSON object is too large to be used as a GET parameter. The overall max URL length is 2083 characters. Please use the POST endpoint instead. Length = ${params['json_str'].length} [THIS DOES NOT EXIST YET]`);
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
|
||||
if (log_lvl) {
|
||||
console.log('Params:', params);
|
||||
}
|
||||
|
||||
const object_li_get_promise = await get_object({
|
||||
api_cfg: api_cfg,
|
||||
endpoint: endpoint,
|
||||
headers: headers,
|
||||
params: params,
|
||||
return_meta: return_meta,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
|
||||
if (log_lvl > 1) {
|
||||
console.log(object_li_get_promise);
|
||||
}
|
||||
|
||||
return object_li_get_promise;
|
||||
}
|
||||
174
src/lib/ae_api/api_get__crud_obj_li_v2.ts
Normal file
174
src/lib/ae_api/api_get__crud_obj_li_v2.ts
Normal file
@@ -0,0 +1,174 @@
|
||||
import type { key_val } from '$lib/stores/ae_stores';
|
||||
import { get_object } from './api_get_object';
|
||||
|
||||
// Refactored 2025-11-13 to use a lookup map for endpoints.
|
||||
const objTypeToEndpointMap: Record<string, string> = {
|
||||
account: '/crud/account/list',
|
||||
address: '/crud/address/list',
|
||||
archive: '/crud/archive/list',
|
||||
archive_content: '/crud/archive/content/list',
|
||||
contact: '/crud/contact/list',
|
||||
data_store: '/crud/data_store/list',
|
||||
event: '/crud/event/list',
|
||||
event_abstract: '/crud/event/abstract/list',
|
||||
event_badge: '/crud/event/badge/list',
|
||||
event_badge_template: '/crud/event/badge/template/list',
|
||||
event_device: '/crud/event/device/list',
|
||||
event_exhibit: '/crud/event/exhibit/list',
|
||||
event_exhibit_tracking: '/crud/event/exhibit/tracking/list',
|
||||
event_file: '/crud/event/file/list',
|
||||
event_location: '/crud/event/location/list',
|
||||
event_person: '/crud/event/person/list',
|
||||
event_presentation: '/crud/event/presentation/list',
|
||||
event_presenter: '/crud/event/presenter/list',
|
||||
event_session: '/crud/event/session/list',
|
||||
event_track: '/crud/event/track/list',
|
||||
grant: '/crud/grant/list',
|
||||
hosted_file: '/crud/hosted_file/list',
|
||||
journal: '/crud/journal/list',
|
||||
journal_entry: '/crud/journal/entry/list',
|
||||
order: '/crud/order/list',
|
||||
order_line: '/crud/order/line/list',
|
||||
page: '/crud/page/list',
|
||||
person: '/crud/person/list',
|
||||
post: '/crud/post/list',
|
||||
post_comment: '/crud/post/comment/list',
|
||||
site: '/crud/site/list',
|
||||
sponsorship_cfg: '/crud/sponsorship/cfg/list',
|
||||
sponsorship: '/crud/sponsorship/list',
|
||||
// user: '/crud/user/list',
|
||||
'lu-country_subdivision': '/crud/lu/country_subdivision/list',
|
||||
'lu-country': '/crud/lu/country/list',
|
||||
'lu-time_zone': '/crud/lu/time_zone/list'
|
||||
};
|
||||
|
||||
function getEndpointForObjType(obj_type: string, for_obj_type?: string): string {
|
||||
if (obj_type === 'lu' && for_obj_type) {
|
||||
const key = `lu-${for_obj_type}`;
|
||||
const endpoint = objTypeToEndpointMap[key];
|
||||
if (endpoint) return endpoint;
|
||||
}
|
||||
|
||||
const endpoint = objTypeToEndpointMap[obj_type];
|
||||
if (endpoint) return endpoint;
|
||||
|
||||
throw new Error(`Unknown object type: ${obj_type}`);
|
||||
}
|
||||
|
||||
type OrderBy = { [key: string]: 'ASC' | 'DESC' };
|
||||
|
||||
interface GetAeObjLiForObjIdCrudV2Params {
|
||||
api_cfg: any; // Consider defining a specific type for api_cfg
|
||||
obj_type: string;
|
||||
for_obj_type: string;
|
||||
for_obj_id?: string;
|
||||
use_alt_tbl?: boolean | string;
|
||||
use_alt_mdl?: boolean | string;
|
||||
use_alt_exp?: boolean | string;
|
||||
inc?: key_val;
|
||||
enabled?: 'all' | 'enabled' | 'not_enabled';
|
||||
hidden?: 'all' | 'hidden' | 'not_hidden';
|
||||
order_by_li?: OrderBy[] | null;
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
headers?: Record<string, string>;
|
||||
params_json?: any;
|
||||
params?: key_val;
|
||||
log_lvl?: number;
|
||||
}
|
||||
|
||||
export async function get_ae_obj_li_for_obj_id_crud_v2({
|
||||
api_cfg,
|
||||
obj_type,
|
||||
for_obj_type,
|
||||
for_obj_id,
|
||||
use_alt_tbl = false,
|
||||
use_alt_mdl = false,
|
||||
use_alt_exp = false,
|
||||
enabled = 'enabled',
|
||||
hidden = 'not_hidden',
|
||||
order_by_li = null,
|
||||
limit = 999999,
|
||||
offset = 0,
|
||||
headers = {},
|
||||
params_json = null,
|
||||
params = {},
|
||||
log_lvl = 0
|
||||
}: GetAeObjLiForObjIdCrudV2Params) {
|
||||
if (log_lvl) {
|
||||
console.log('*** get_ae_obj_li_for_obj_id_crud_v2() ***');
|
||||
}
|
||||
|
||||
try {
|
||||
const endpoint = `/v2${getEndpointForObjType(obj_type, for_obj_type)}`;
|
||||
if (log_lvl) {
|
||||
console.log('Endpoint:', endpoint);
|
||||
}
|
||||
|
||||
// We need to remove a few parameters from the params object that are not allowed.
|
||||
delete params['qry__enabled'];
|
||||
delete params['qry__hidden'];
|
||||
delete params['qry__limit'];
|
||||
delete params['qry__offset'];
|
||||
|
||||
if (for_obj_type) params['for_obj_type'] = for_obj_type;
|
||||
if (for_obj_id) params['for_obj_id'] = for_obj_id;
|
||||
|
||||
if (use_alt_tbl === true) params['tbl_alt'] = 'alt';
|
||||
if (use_alt_mdl === true) params['mdl_alt'] = 'alt';
|
||||
if (use_alt_exp === true) params['exp_alt'] = 'alt';
|
||||
|
||||
const allowed_enabled_list = ['all', 'enabled', 'not_enabled'];
|
||||
if (allowed_enabled_list.includes(enabled)) {
|
||||
params['enabled'] = enabled;
|
||||
}
|
||||
|
||||
const allowed_hidden_list = ['all', 'hidden', 'not_hidden'];
|
||||
if (allowed_hidden_list.includes(hidden)) {
|
||||
params['hidden'] = hidden;
|
||||
}
|
||||
|
||||
// NOTE: The order_by_li variable is in the "headers" because URL GET params do not handle complex objects very well.
|
||||
if (order_by_li) {
|
||||
headers['order_by_li'] = JSON.stringify(order_by_li);
|
||||
}
|
||||
|
||||
if (limit > 0) params['limit'] = limit;
|
||||
if (offset > 0) params['offset'] = offset;
|
||||
|
||||
if (params_json) {
|
||||
// NOTE: "jp" stands for "JSON Params". This is a JSON object that needs to be safely converted to a string for the params.
|
||||
// Max characters for a GET request is ~2000. This is a limitation of the browser.
|
||||
const json_params_str = encodeURIComponent(JSON.stringify(params_json));
|
||||
if (json_params_str.length > 2083) {
|
||||
// Using console.error instead of throwing an error to avoid crashing the app for a known limitation.
|
||||
console.error(
|
||||
`The JSON object is too large to be used as a GET parameter. Max length is 2083 characters. Length = ${json_params_str.length}`
|
||||
);
|
||||
return false;
|
||||
}
|
||||
params['jp'] = json_params_str;
|
||||
}
|
||||
|
||||
if (log_lvl) {
|
||||
console.log('Params:', params);
|
||||
}
|
||||
|
||||
const object_li_get_promise = await get_object({
|
||||
api_cfg: api_cfg,
|
||||
endpoint: endpoint,
|
||||
headers: headers,
|
||||
params: params,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
|
||||
if (log_lvl > 1) {
|
||||
console.log(object_li_get_promise);
|
||||
}
|
||||
|
||||
return object_li_get_promise;
|
||||
} catch (error) {
|
||||
console.error('Error in get_ae_obj_li_for_obj_id_crud_v2:', error);
|
||||
return false; // Or handle the error as appropriate
|
||||
}
|
||||
}
|
||||
236
src/lib/ae_api/api_get_object.ts
Normal file
236
src/lib/ae_api/api_get_object.ts
Normal file
@@ -0,0 +1,236 @@
|
||||
import type { key_val } from '$lib/stores/ae_stores';
|
||||
|
||||
export let temp_get_blob_percent_completed = 0;
|
||||
export const get_blob_percent_completed = temp_get_blob_percent_completed;
|
||||
|
||||
export const temp_get_object_percent_completed = 0;
|
||||
export const get_object_percent_completed = temp_get_object_percent_completed;
|
||||
|
||||
export const get_object = async function get_object({
|
||||
api_cfg = null,
|
||||
endpoint = '',
|
||||
headers = {},
|
||||
params = {},
|
||||
data = {},
|
||||
timeout = 60000,
|
||||
return_meta = false,
|
||||
return_blob = false,
|
||||
filename = '',
|
||||
auto_download = false,
|
||||
as_list = false, // Is this still really needed?
|
||||
// The task_id value should be a random string that is unique to the task. This is used to identify the task in the message event.
|
||||
task_id = crypto.randomUUID(),
|
||||
log_lvl = 0,
|
||||
retry_count = 5 // Number of retry attempts
|
||||
}: {
|
||||
api_cfg: any;
|
||||
endpoint: string;
|
||||
headers?: any;
|
||||
params?: any;
|
||||
data?: any;
|
||||
timeout?: number;
|
||||
return_meta?: boolean;
|
||||
return_blob?: boolean;
|
||||
filename?: null | string;
|
||||
auto_download?: boolean;
|
||||
as_list?: boolean;
|
||||
task_id?: string;
|
||||
log_lvl?: number;
|
||||
retry_count?: number;
|
||||
}) {
|
||||
if (log_lvl) {
|
||||
console.log(`*** get_object() *** Endpoint: ${endpoint} AE Task ID: ${task_id}`);
|
||||
console.log('Params:', params);
|
||||
if (log_lvl > 1) {
|
||||
console.log('Data:', data);
|
||||
}
|
||||
}
|
||||
|
||||
if (!api_cfg) {
|
||||
console.log('No API Config was provided. Returning false.');
|
||||
return false;
|
||||
}
|
||||
|
||||
const url = new URL(endpoint, api_cfg['base_url']);
|
||||
Object.keys(params).forEach((key) => url.searchParams.append(key, params[key]));
|
||||
|
||||
const controller = new AbortController();
|
||||
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
||||
|
||||
// Remove a header parameter if it is set to null
|
||||
if (
|
||||
api_cfg['headers'].hasOwnProperty('x-no-account-id') &&
|
||||
api_cfg['headers']['x-no-account-id'] === null
|
||||
) {
|
||||
delete api_cfg['headers']['x-no-account-id'];
|
||||
}
|
||||
|
||||
// Clean the headers
|
||||
const headers_cleaned: key_val = {};
|
||||
for (const prop in headers) {
|
||||
const prop_cleaned = prop.replaceAll('_', '-');
|
||||
if (typeof headers[prop] != 'string') {
|
||||
headers[prop] = JSON.stringify(headers[prop]);
|
||||
}
|
||||
headers_cleaned[prop_cleaned] = headers[prop];
|
||||
if (log_lvl > 1) {
|
||||
console.log(`${prop_cleaned}: ${headers_cleaned[prop_cleaned]}`);
|
||||
}
|
||||
}
|
||||
headers = headers_cleaned;
|
||||
if (log_lvl > 1) {
|
||||
console.log('All headers cleaned:', headers);
|
||||
}
|
||||
|
||||
const fetchOptions: RequestInit = {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
...api_cfg['headers'],
|
||||
...headers
|
||||
},
|
||||
signal: controller.signal
|
||||
};
|
||||
|
||||
if (log_lvl > 1) {
|
||||
console.log('Fetch options:', fetchOptions);
|
||||
}
|
||||
|
||||
let fetch_method: any = fetch;
|
||||
if (api_cfg.fetch) {
|
||||
if (log_lvl > 1) {
|
||||
console.log('Using custom fetch function from api_cfg!!!');
|
||||
}
|
||||
fetch_method = api_cfg.fetch;
|
||||
}
|
||||
|
||||
for (let attempt = 1; attempt <= retry_count; attempt++) {
|
||||
try {
|
||||
const response = await fetch_method(url.toString(), fetchOptions).catch(function (
|
||||
error: any
|
||||
) {
|
||||
console.log(
|
||||
'API GET Object *fetch* request was aborted or failed in an unexpected way.',
|
||||
error
|
||||
);
|
||||
});
|
||||
clearTimeout(timeoutId);
|
||||
|
||||
if (!response) {
|
||||
if (log_lvl > 1) {
|
||||
console.log(
|
||||
'API GET Object: Something went wrong with *fetch* request. Returning false? Throwing an error!'
|
||||
);
|
||||
}
|
||||
throw new Error(
|
||||
`HTTP fetch request was aborted or failed in an unexpected way! URL = ${url.toString()}`
|
||||
); // This will allow it to retry
|
||||
// return false; // This will stop the retries
|
||||
}
|
||||
|
||||
if (log_lvl) {
|
||||
console.log(
|
||||
`Response: status=${response.status} statusText=${response.statusText} url=${response.url} attempt=${attempt}`
|
||||
);
|
||||
}
|
||||
if (log_lvl > 1) {
|
||||
console.log('Response:', response);
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
if (response.status === 404) {
|
||||
if (log_lvl) {
|
||||
console.log('The response was a 404 not found "error". Returning null.');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
console.log('The response was not ok. Throwing an error!');
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
if (!return_blob) {
|
||||
const json = await response.json();
|
||||
if (log_lvl > 1) {
|
||||
console.log('Response JSON:', json);
|
||||
}
|
||||
if (!Array.isArray(json.data) && as_list) {
|
||||
return [json.data];
|
||||
}
|
||||
return json.data || json;
|
||||
} else {
|
||||
const reader = response.body?.getReader();
|
||||
const contentLength = +response.headers.get('Content-Length')!;
|
||||
let receivedLength = 0;
|
||||
const chunks = [];
|
||||
|
||||
while (true) {
|
||||
const { done, value } = await reader!.read();
|
||||
if (done) break;
|
||||
chunks.push(value);
|
||||
receivedLength += value.length;
|
||||
|
||||
const percent_completed = Math.round((receivedLength * 100) / contentLength);
|
||||
if (log_lvl > 1) {
|
||||
console.log(
|
||||
'GET Blob Progress:',
|
||||
percent_completed,
|
||||
'Total:',
|
||||
contentLength,
|
||||
'Loaded:',
|
||||
receivedLength,
|
||||
'Percent Completed',
|
||||
percent_completed
|
||||
);
|
||||
}
|
||||
|
||||
temp_get_blob_percent_completed = percent_completed;
|
||||
|
||||
try {
|
||||
if (typeof window !== 'undefined') {
|
||||
window.postMessage(
|
||||
{
|
||||
type: 'api_download_blob',
|
||||
status: 'downloading',
|
||||
task_id: task_id,
|
||||
endpoint: endpoint,
|
||||
filename: filename,
|
||||
size_total: contentLength,
|
||||
size_loaded: receivedLength,
|
||||
percent_completed: percent_completed
|
||||
},
|
||||
'*'
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Error posting message:', e);
|
||||
}
|
||||
}
|
||||
|
||||
const blob = new Blob(chunks);
|
||||
if (auto_download) {
|
||||
const downloadUrl = window.URL.createObjectURL(blob);
|
||||
const link = document.createElement('a');
|
||||
link.href = downloadUrl;
|
||||
link.setAttribute('download', filename || 'download');
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
link.remove();
|
||||
return true;
|
||||
} else {
|
||||
return blob;
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(`API GET object request *fetch* error on attempt ${attempt}:`, error);
|
||||
|
||||
if (attempt === retry_count) {
|
||||
console.log('Max retry attempts reached. Returning false.');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Log retry information
|
||||
if (log_lvl) {
|
||||
console.log(`Retrying... (${attempt}/${retry_count})`);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
526
src/lib/ae_api/api_get_object_v1.ts
Normal file
526
src/lib/ae_api/api_get_object_v1.ts
Normal file
@@ -0,0 +1,526 @@
|
||||
import axios from 'axios';
|
||||
|
||||
import type { key_val } from '$lib/stores/ae_stores';
|
||||
|
||||
export let temp_get_blob_percent_completed = 0;
|
||||
// export let get_blob_percent_completed = readable(temp_get_blob_percent_completed);
|
||||
export const get_blob_percent_completed = temp_get_blob_percent_completed;
|
||||
|
||||
export let temp_get_object_percent_completed = 0;
|
||||
// export let get_object_percent_completed = readable(temp_get_object_percent_completed);
|
||||
export const get_object_percent_completed = temp_get_object_percent_completed;
|
||||
|
||||
// Updated 2024-05-23
|
||||
export const get_object = async function get_object({
|
||||
api_cfg = null,
|
||||
endpoint = '',
|
||||
headers = {},
|
||||
params = {},
|
||||
data = {},
|
||||
timeout = 60000,
|
||||
return_meta = false,
|
||||
return_blob = false,
|
||||
filename = '',
|
||||
auto_download = false,
|
||||
as_list = false,
|
||||
// The task_id value should be a random string that is unique to the task. This is used to identify the task in the message event.
|
||||
task_id = crypto.randomUUID(),
|
||||
log_lvl = 0
|
||||
}: {
|
||||
api_cfg: any;
|
||||
endpoint: string;
|
||||
headers?: any;
|
||||
params?: any;
|
||||
data?: any;
|
||||
timeout?: number;
|
||||
return_meta?: boolean;
|
||||
return_blob?: boolean;
|
||||
filename?: null | string;
|
||||
auto_download?: boolean;
|
||||
as_list?: boolean;
|
||||
task_id?: string;
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
if (log_lvl) {
|
||||
console.log(`*** get_object() *** Endpoint: ${endpoint} AE Task ID: ${task_id}`);
|
||||
console.log('Params:', params);
|
||||
if (log_lvl > 1) {
|
||||
console.log('Data:', data);
|
||||
console.log(`Base URL: ${api_cfg['base_url']}; Timeout: ${timeout}`);
|
||||
console.log('API Config:', api_cfg);
|
||||
}
|
||||
if (log_lvl > 2) {
|
||||
console.log(
|
||||
`Return Meta: ${return_meta}; Return Blob: ${return_blob}; Filename: ${filename}; Auto Download: ${auto_download}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (!api_cfg) {
|
||||
console.log('No API Config was provided. Returning false.');
|
||||
return false;
|
||||
}
|
||||
|
||||
const axios_api = axios.create({
|
||||
baseURL: api_cfg['base_url'],
|
||||
timeout: timeout // in milliseconds; 60000 = 60 seconds
|
||||
/* other custom settings */
|
||||
});
|
||||
axios_api.defaults.headers = api_cfg['headers'];
|
||||
if (log_lvl) {
|
||||
console.log('axios_api.defaults.headers:', axios_api.defaults.headers);
|
||||
console.log('Additional headers:', headers);
|
||||
}
|
||||
|
||||
// console.log('Clean the headers. No _underscores_!')
|
||||
const headers_cleaned: key_val = {};
|
||||
for (const prop in headers) {
|
||||
// No underscores allowed in the header parameters!
|
||||
const prop_cleaned = prop.replaceAll('_', '-');
|
||||
|
||||
// The value must be a string for the header!
|
||||
if (typeof headers[prop] != 'string') {
|
||||
headers[prop] = JSON.stringify(headers[prop]);
|
||||
}
|
||||
|
||||
headers_cleaned[prop_cleaned] = headers[prop];
|
||||
|
||||
if (log_lvl) {
|
||||
console.log(`${prop_cleaned}: ${headers_cleaned[prop_cleaned]}`);
|
||||
}
|
||||
}
|
||||
headers = headers_cleaned;
|
||||
if (log_lvl) {
|
||||
console.log('All headers cleaned:', headers);
|
||||
}
|
||||
|
||||
if (log_lvl) {
|
||||
console.log('URL params:');
|
||||
}
|
||||
for (const prop in params) {
|
||||
if (log_lvl > 1) {
|
||||
console.log(`URL param: ${prop}: ${params[prop]}`);
|
||||
}
|
||||
if (params[prop] === null) {
|
||||
params[prop] = 'null';
|
||||
}
|
||||
}
|
||||
|
||||
// Handle the case where there is no Blob expected to be returned. Mainly JSON and text data.
|
||||
if (!return_blob) {
|
||||
const response_data_promise = await axios_api
|
||||
.get(endpoint, {
|
||||
headers: headers,
|
||||
params: params,
|
||||
onDownloadProgress: (progressEvent) => {
|
||||
const percent_completed = Math.round(
|
||||
(progressEvent.loaded * 100) / progressEvent.total
|
||||
);
|
||||
if (log_lvl > 1) {
|
||||
console.log(
|
||||
'GET Data Progress:',
|
||||
progressEvent.progress,
|
||||
'Total:',
|
||||
progressEvent.total,
|
||||
'Loaded:',
|
||||
progressEvent.loaded,
|
||||
'Percent Completed',
|
||||
percent_completed
|
||||
);
|
||||
}
|
||||
|
||||
temp_get_object_percent_completed = percent_completed;
|
||||
|
||||
// WARNING: This needs to be tied to an object type and ID. This is a temporary solution.
|
||||
try {
|
||||
// Check if window is defined. This is to prevent errors in SvelteKit.
|
||||
if (typeof window !== 'undefined') {
|
||||
window.postMessage(
|
||||
{
|
||||
type: 'api_download_data',
|
||||
status: 'downloading',
|
||||
task_id: task_id,
|
||||
endpoint: endpoint,
|
||||
filename: filename,
|
||||
size_total: progressEvent.total,
|
||||
size_loaded: progressEvent.loaded,
|
||||
percent_completed: percent_completed
|
||||
},
|
||||
'*'
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('Error posting message to window:', error);
|
||||
}
|
||||
}
|
||||
})
|
||||
.then(function (response) {
|
||||
if (log_lvl) {
|
||||
console.log(
|
||||
`GET Response: status=${response.status} statusText=${response.statusText} baseURL=${response.config.baseURL} url=${response.config.url} method=${response.config.method} headers=${response.config.headers} params=${JSON.stringify(response.config.params)}`
|
||||
);
|
||||
}
|
||||
if (log_lvl > 1) {
|
||||
console.log('GET Response:', response);
|
||||
}
|
||||
|
||||
// Post file download message
|
||||
try {
|
||||
if (typeof window !== 'undefined') {
|
||||
window.postMessage(
|
||||
{
|
||||
type: 'api_download_data',
|
||||
status: 'complete',
|
||||
task_id: task_id,
|
||||
endpoint: endpoint,
|
||||
filename: filename,
|
||||
size_total: 0,
|
||||
size_loaded: 0,
|
||||
percent_completed: 100
|
||||
},
|
||||
'*'
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('Error posting message to window:', error);
|
||||
}
|
||||
|
||||
if (!Array.isArray(response.data['data']) && as_list) {
|
||||
if (log_lvl) {
|
||||
console.log(
|
||||
'Data result is a dictionary/object, not an array/list. Forcing return as an array/list'
|
||||
);
|
||||
}
|
||||
const return_data = [];
|
||||
return_data.push(response.data['data']);
|
||||
return return_data;
|
||||
} else if (response.data['data']) {
|
||||
const return_data = response.data['data'];
|
||||
if (log_lvl) {
|
||||
if (Array.isArray(return_data)) {
|
||||
console.log(
|
||||
`Data result is an array/list. Array length: ${return_data.length}`
|
||||
);
|
||||
} else {
|
||||
console.log(`Data result is a dictionary/object, not an array/list.`);
|
||||
}
|
||||
}
|
||||
return return_data;
|
||||
} else {
|
||||
const return_data = response.data;
|
||||
if (log_lvl) {
|
||||
if (Array.isArray(return_data)) {
|
||||
console.log(
|
||||
`Not a standard response from Aether's API. Data result is an array/list. Array length: ${return_data.length}`
|
||||
);
|
||||
} else {
|
||||
console.log(
|
||||
`Not a standard response from Aether's API. Data result is a dictionary/object, not an array/list.`
|
||||
);
|
||||
}
|
||||
}
|
||||
return return_data;
|
||||
}
|
||||
})
|
||||
.catch(function (error: any) {
|
||||
// Handle the common and expected 404 "error" first
|
||||
if (error.response && error.response.status === 404) {
|
||||
if (log_lvl) {
|
||||
console.log('The response was a 404 not found "error". Returning null.');
|
||||
}
|
||||
if (log_lvl > 1) {
|
||||
console.log(error.response);
|
||||
}
|
||||
if (log_lvl > 2) {
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
// Post file download message
|
||||
try {
|
||||
if (typeof window !== 'undefined') {
|
||||
window.postMessage(
|
||||
{
|
||||
type: 'api_download_data',
|
||||
status: 'complete',
|
||||
task_id: task_id,
|
||||
endpoint: endpoint,
|
||||
filename: filename,
|
||||
size_total: 0,
|
||||
size_loaded: 0,
|
||||
percent_completed: 0
|
||||
},
|
||||
'*'
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('Error posting message to window:', error);
|
||||
}
|
||||
return null; // Returning null since there were no results
|
||||
}
|
||||
|
||||
if (log_lvl) {
|
||||
console.log(`Base URL: ${api_cfg['base_url']} | Endpoint: ${endpoint}`);
|
||||
console.log('Error Message:', error.message); // Is this needed here or below in the in the else portion???
|
||||
|
||||
if (error.response) {
|
||||
// The request was made and the server responded with a status code that falls out of the range of 2xx
|
||||
console.log('Error Response Data', error.response.data);
|
||||
console.log('Error Response Status', error.response.status);
|
||||
console.log('Error Response Headers', error.response.headers);
|
||||
} else if (error.request) {
|
||||
// The request was made but no response was received `error.request` is an instance of XMLHttpRequest in the browser and an instance of http.ClientRequest in node.js
|
||||
if (log_lvl > 1) {
|
||||
console.log('Error Request', error.request);
|
||||
}
|
||||
} else {
|
||||
// Something happened in setting up the request that triggered an Error
|
||||
console.log('Error Message', error.message);
|
||||
}
|
||||
}
|
||||
if (log_lvl > 2) {
|
||||
console.log('Error:', error);
|
||||
console.log(error.config);
|
||||
}
|
||||
|
||||
if (error.code === 'ECONNABORTED') {
|
||||
// Timeout Error (You can implement retry here where suitable)
|
||||
console.log('Timeout Error: ', error.message);
|
||||
}
|
||||
if (log_lvl) {
|
||||
console.log('The response was an error. Returning false.');
|
||||
}
|
||||
|
||||
return false; // Returning false since something may have gone wrong. This includes timeouts. Also more in line with what the API returns.
|
||||
// return error;
|
||||
});
|
||||
|
||||
if (log_lvl > 1) {
|
||||
// console.log(`Response Data: ${response_data_promise}`);
|
||||
console.log(`Response Data:`, response_data_promise);
|
||||
// console.log(response_data_promise);
|
||||
}
|
||||
if (response_data_promise) {
|
||||
// The most common and expected response.
|
||||
// console.log('Returning result. This is generally expected.');
|
||||
return response_data_promise;
|
||||
} else if (response_data_promise === null) {
|
||||
// Less common, but expected response if no results were returned.
|
||||
if (log_lvl) {
|
||||
console.log('Returning null. This is expected if no results were found. (404)');
|
||||
}
|
||||
return response_data_promise;
|
||||
} else if (response_data_promise === false) {
|
||||
// Not common, but expected response if the request to the API had an issue.
|
||||
console.log('Returning false. There may have been an issue with this request.');
|
||||
return response_data_promise;
|
||||
} else {
|
||||
// This generally should not happen. It likely means the query was bad or an API issue.
|
||||
console.log('Returning (JSON/text) unknown. This should not happen in most cases.');
|
||||
Promise.reject(new Error('fail')).then(resolved, rejected);
|
||||
}
|
||||
|
||||
// Handle the case where a Blob is expected to be returned.
|
||||
} else {
|
||||
// console.log('Expecting a Blob to be returned...');
|
||||
|
||||
const response_data_promise = await axios_api
|
||||
.get(endpoint, {
|
||||
params: params,
|
||||
responseType: 'blob',
|
||||
onDownloadProgress: (progressEvent) => {
|
||||
const percent_completed = Math.round(
|
||||
(progressEvent.loaded * 100) / progressEvent.total
|
||||
);
|
||||
console.log(
|
||||
'GET Blob Progress:',
|
||||
progressEvent.progress,
|
||||
'Total:',
|
||||
progressEvent.total,
|
||||
'Loaded:',
|
||||
progressEvent.loaded,
|
||||
'Percent Completed',
|
||||
percent_completed
|
||||
);
|
||||
|
||||
temp_get_blob_percent_completed = percent_completed;
|
||||
|
||||
// WARNING: This needs to be tied to an object type and ID. This is a temporary solution.
|
||||
try {
|
||||
if (typeof window !== 'undefined') {
|
||||
window.postMessage(
|
||||
{
|
||||
type: 'api_download_blob',
|
||||
status: 'downloading',
|
||||
task_id: task_id,
|
||||
endpoint: endpoint,
|
||||
filename: filename,
|
||||
size_total: progressEvent.total,
|
||||
size_loaded: progressEvent.loaded,
|
||||
percent_completed: percent_completed
|
||||
},
|
||||
'*'
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('Error posting message to window:', error);
|
||||
}
|
||||
}
|
||||
})
|
||||
.then(function (response) {
|
||||
if (log_lvl) {
|
||||
console.log(
|
||||
`GET (blob) Response: status=${response.status} statusText=${response.statusText} baseURL=${response.config.baseURL} url=${response.config.url} method=${response.config.method} headers=${response.config.headers} params=${response.config.params}`
|
||||
);
|
||||
}
|
||||
if (log_lvl > 1) {
|
||||
console.log('GET (blob) Response:', response);
|
||||
}
|
||||
|
||||
const { data, headers } = response;
|
||||
|
||||
// Careful if this download filename needs to be changed to a different file extension. The browser/client may not know how to handle it.
|
||||
if (filename) {
|
||||
} else if (headers['content-disposition']) {
|
||||
filename = headers['content-disposition'].replace(/\w+;filename=(.*)/, '$1');
|
||||
} else {
|
||||
filename = 'unknown_file.ext';
|
||||
}
|
||||
|
||||
// WARNING: This needs to be tied to an object type and ID. This is a temporary solution.
|
||||
try {
|
||||
if (typeof window !== 'undefined') {
|
||||
window.postMessage(
|
||||
{
|
||||
type: 'api_download_blob',
|
||||
status: 'complete',
|
||||
task_id: task_id,
|
||||
endpoint: endpoint,
|
||||
filename: filename,
|
||||
size_total: 0,
|
||||
size_loaded: 0,
|
||||
percent_completed: 100
|
||||
},
|
||||
'*'
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('Error posting message to window:', error);
|
||||
}
|
||||
|
||||
if (auto_download) {
|
||||
if (log_lvl) {
|
||||
console.log(`Auto Download: ${filename}`);
|
||||
}
|
||||
const url = window.URL.createObjectURL(new Blob([response.data]));
|
||||
const link = document.createElement('a');
|
||||
link.href = url;
|
||||
link.setAttribute('download', filename);
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
return true;
|
||||
} else {
|
||||
return response;
|
||||
}
|
||||
})
|
||||
.catch(function (error: any) {
|
||||
// Handle the common and expected 404 "error" first
|
||||
if (error.response && error.response.status === 404) {
|
||||
if (log_lvl) {
|
||||
console.log('The response was a 404 not found "error". Returning null.');
|
||||
}
|
||||
if (log_lvl > 1) {
|
||||
console.log(error.response);
|
||||
}
|
||||
if (log_lvl > 2) {
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
// Post file download message
|
||||
try {
|
||||
if (typeof window !== 'undefined') {
|
||||
window.postMessage(
|
||||
{
|
||||
type: 'api_download_blob',
|
||||
status: 'complete',
|
||||
task_id: task_id,
|
||||
endpoint: endpoint,
|
||||
filename: filename,
|
||||
size_total: 0,
|
||||
size_loaded: 0,
|
||||
percent_completed: 0
|
||||
},
|
||||
'*'
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('Error posting message to window:', error);
|
||||
}
|
||||
return null; // Returning null since there were no results
|
||||
}
|
||||
|
||||
if (log_lvl) {
|
||||
console.log(`Base URL: ${api_cfg['base_url']} | Endpoint: ${endpoint}`);
|
||||
console.log('Error Message:', error.message); // Is this needed here or below in the in the else portion???
|
||||
|
||||
if (error.response) {
|
||||
// The request was made and the server responded with a status code that falls out of the range of 2xx
|
||||
console.log('Error Response Data', error.response.data);
|
||||
console.log('Error Response Status', error.response.status);
|
||||
console.log('Error Response Headers', error.response.headers);
|
||||
} else if (error.request) {
|
||||
// The request was made but no response was received `error.request` is an instance of XMLHttpRequest in the browser and an instance of http.ClientRequest in node.js
|
||||
if (log_lvl > 1) {
|
||||
console.log('Error Request', error.request);
|
||||
}
|
||||
} else {
|
||||
// Something happened in setting up the request that triggered an Error
|
||||
console.log('Error Message', error.message);
|
||||
}
|
||||
}
|
||||
|
||||
if (error.code === 'ECONNABORTED') {
|
||||
// Timeout Error (You can implement retry here where suitable)
|
||||
console.log('Timeout Error: ', error.message);
|
||||
}
|
||||
|
||||
if (log_lvl) {
|
||||
console.log('The response was an error. Returning false.');
|
||||
}
|
||||
|
||||
return false; // Returning false since something may have gone wrong. This includes timeouts. Also more in line with what the API returns.
|
||||
// return error;
|
||||
});
|
||||
|
||||
if (response_data_promise) {
|
||||
// The most common and expected response.
|
||||
// console.log('Returning result. This is generally expected.');
|
||||
// let test_blob = new Blob([response_data_promise.data]);
|
||||
// console.log(test_blob);
|
||||
// return test_blob;
|
||||
// console.log(response_data_promise.blob());
|
||||
return response_data_promise;
|
||||
} else if (response_data_promise === null) {
|
||||
// Less common, but expected response if no results were returned.
|
||||
if (log_lvl) {
|
||||
console.log('Returning null. This is expected if no results were found. (404)');
|
||||
}
|
||||
return response_data_promise;
|
||||
} else if (response_data_promise === false) {
|
||||
// Not common, but expected response if the request to the API had an issue.
|
||||
console.log('Returning false. There may have been an issue with this request.');
|
||||
return response_data_promise;
|
||||
} else {
|
||||
// This generally should not happen. It likely means the query was bad or an API issue.
|
||||
console.log('Returning (blob) unknown. This should not happen in most cases.');
|
||||
Promise.reject(new Error('fail')).then(resolved, rejected);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function resolved(result: any) {
|
||||
console.log('Resolved');
|
||||
}
|
||||
|
||||
function rejected(result: any) {
|
||||
console.error(result);
|
||||
}
|
||||
144
src/lib/ae_api/api_patch_object.ts
Normal file
144
src/lib/ae_api/api_patch_object.ts
Normal file
@@ -0,0 +1,144 @@
|
||||
// import axios from 'axios';
|
||||
|
||||
// Updated 2024-05-23
|
||||
export const patch_object = async function patch_object({
|
||||
api_cfg = null,
|
||||
endpoint = '',
|
||||
params = {},
|
||||
data = {},
|
||||
return_meta = false,
|
||||
log_lvl = 0,
|
||||
retry_count = 5 // Number of retry attempts
|
||||
}: {
|
||||
api_cfg: any;
|
||||
endpoint: string;
|
||||
params?: any;
|
||||
data?: any;
|
||||
return_meta?: boolean;
|
||||
log_lvl?: number;
|
||||
retry_count?: number;
|
||||
}) {
|
||||
if (log_lvl) {
|
||||
console.log(`*** patch_object() *** Endpoint: ${endpoint}`);
|
||||
console.log('Params:', params);
|
||||
if (log_lvl > 1) {
|
||||
console.log('Data:', data);
|
||||
}
|
||||
}
|
||||
|
||||
if (!api_cfg) {
|
||||
console.error('No API Config was provided. Returning false.');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Construct the URL with query parameters
|
||||
const url = new URL(endpoint, api_cfg['base_url']);
|
||||
Object.keys(params).forEach((key) => url.searchParams.append(key, params[key]));
|
||||
|
||||
// Clean the headers
|
||||
const headers_cleaned: Record<string, string> = {};
|
||||
for (const prop in api_cfg['headers']) {
|
||||
const prop_cleaned = prop.replaceAll('_', '-');
|
||||
headers_cleaned[prop_cleaned] = api_cfg['headers'][prop];
|
||||
}
|
||||
|
||||
if (log_lvl > 1) {
|
||||
console.log('Cleaned Headers:', headers_cleaned);
|
||||
}
|
||||
|
||||
const fetchOptions: RequestInit = {
|
||||
method: 'PATCH',
|
||||
headers: {
|
||||
...headers_cleaned,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(data)
|
||||
};
|
||||
|
||||
if (log_lvl > 1) {
|
||||
console.log('Fetch Options:', fetchOptions);
|
||||
}
|
||||
|
||||
for (let attempt = 1; attempt <= retry_count; attempt++) {
|
||||
try {
|
||||
const response = await fetch(url.toString(), fetchOptions);
|
||||
|
||||
if (log_lvl) {
|
||||
console.log(`Response: status=${response.status} attempt=${attempt}`);
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
if (response.status === 404) {
|
||||
console.warn('404 Not Found. Returning null.');
|
||||
return null; // Returning null since there were no results
|
||||
}
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
const json = await response.json();
|
||||
|
||||
if (log_lvl > 1) {
|
||||
console.log('Response JSON:', json);
|
||||
}
|
||||
|
||||
// Return the response data or metadata
|
||||
return return_meta ? json : json.data;
|
||||
} catch (error) {
|
||||
console.error(`API PATCH error on attempt ${attempt}:`, error);
|
||||
|
||||
// If this is the last attempt, return false
|
||||
if (attempt === retry_count) {
|
||||
console.error('Max retry attempts reached. Returning false.');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Log retry information
|
||||
if (log_lvl) {
|
||||
console.log(`Retrying... (${attempt}/${retry_count})`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// let axios_api = axios.create({
|
||||
// baseURL: api_cfg['base_url'],
|
||||
// /* other custom settings */
|
||||
// });
|
||||
// axios_api.defaults.headers = api_cfg['headers'];
|
||||
|
||||
// for (let attempt = 1; attempt <= retry_count; attempt++) {
|
||||
// try {
|
||||
// const response = await axios_api.patch(endpoint, data, { params: params });
|
||||
// if (log_lvl) {
|
||||
// console.log(`Response: status=${response.status} attempt=${attempt}`);
|
||||
// }
|
||||
// if (log_lvl > 1) {
|
||||
// console.log('Response Data:', response.data);
|
||||
// }
|
||||
|
||||
// // Return the response data
|
||||
// return response.data['data'];
|
||||
// } catch (error) {
|
||||
// if (log_lvl) {
|
||||
// console.error(`Error on attempt ${attempt}:`, error);
|
||||
// }
|
||||
|
||||
// // Handle specific errors (e.g., 404)
|
||||
// if (error.response && error.response.status === 404) {
|
||||
// console.warn('404 Not Found. Returning null.');
|
||||
// return null; // Returning null since there were no results
|
||||
// }
|
||||
|
||||
// // If this is the last attempt, return false
|
||||
// if (attempt === retry_count) {
|
||||
// console.error('Max retry attempts reached. Returning false.');
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// // Log retry information
|
||||
// if (log_lvl) {
|
||||
// console.log(`Retrying... (${attempt}/${retry_count})`);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return response_data;
|
||||
};
|
||||
351
src/lib/ae_api/api_post_object.ts
Normal file
351
src/lib/ae_api/api_post_object.ts
Normal file
@@ -0,0 +1,351 @@
|
||||
// import axios from 'axios';
|
||||
|
||||
export const temp_post_blob_percent_completed = 0;
|
||||
export const post_blob_percent_completed = temp_post_blob_percent_completed;
|
||||
export const temp_post_object_percent_completed = 0;
|
||||
export const post_object_percent_completed = temp_post_object_percent_completed;
|
||||
|
||||
// Updated 2024-05-23
|
||||
export const post_object = async function post_object({
|
||||
api_cfg = null,
|
||||
endpoint = '',
|
||||
params = {},
|
||||
data = {},
|
||||
form_data = null,
|
||||
return_meta = false,
|
||||
return_blob = false,
|
||||
filename = '',
|
||||
auto_download = false,
|
||||
// The task_id value should be a random string that is unique to the task. This is used to identify the task in the message event.
|
||||
task_id = crypto.randomUUID(),
|
||||
log_lvl = 0,
|
||||
retry_count = 5
|
||||
}: {
|
||||
api_cfg: any;
|
||||
endpoint: string;
|
||||
params?: any;
|
||||
data?: any;
|
||||
form_data?: any;
|
||||
return_meta?: boolean;
|
||||
return_blob?: boolean;
|
||||
filename?: string;
|
||||
auto_download?: boolean;
|
||||
task_id?: string;
|
||||
log_lvl?: number;
|
||||
retry_count?: number;
|
||||
}) {
|
||||
if (log_lvl) {
|
||||
console.log(`*** post_object() *** Endpoint: ${endpoint} Task ID: ${task_id}`);
|
||||
console.log('Params:', params);
|
||||
if (log_lvl > 1) {
|
||||
console.log('Data:', data);
|
||||
console.log(typeof data);
|
||||
console.log(`Base URL: ${api_cfg['base_url']}`);
|
||||
console.log('API Config:', api_cfg);
|
||||
}
|
||||
if (log_lvl > 2) {
|
||||
console.log(`Return Meta: ${return_meta}`);
|
||||
console.log(`Return Blob: ${return_blob}`);
|
||||
console.log(`Filename: ${filename}`);
|
||||
console.log(`Auto Download: ${auto_download}`);
|
||||
}
|
||||
}
|
||||
|
||||
// console.log('HERE!! API POST 0');
|
||||
|
||||
if (!api_cfg) {
|
||||
console.error('No API Config was provided. Returning false.');
|
||||
return false;
|
||||
}
|
||||
|
||||
// console.log('HERE!! API POST 1');
|
||||
|
||||
// Construct the URL with query parameters
|
||||
const url = new URL(endpoint, api_cfg['base_url']);
|
||||
if (params) {
|
||||
Object.keys(params).forEach((key) => url.searchParams.append(key, params[key]));
|
||||
}
|
||||
|
||||
// console.log('HERE!! API POST 2');
|
||||
|
||||
// Clean the headers
|
||||
const headers_cleaned: Record<string, string> = {};
|
||||
for (const prop in api_cfg['headers']) {
|
||||
const prop_cleaned = prop.replaceAll('_', '-');
|
||||
headers_cleaned[prop_cleaned] = api_cfg['headers'][prop];
|
||||
}
|
||||
|
||||
// console.log('HERE!! API POST 3');
|
||||
|
||||
if (form_data) {
|
||||
// headers_cleaned['Content-Type'] = 'multipart/form-data';
|
||||
delete headers_cleaned['Content-Type'];
|
||||
delete headers_cleaned['content-type']; // Just in case
|
||||
delete headers_cleaned['Content-type']; // Just in case
|
||||
console.log('Form Data:', form_data);
|
||||
} else {
|
||||
headers_cleaned['Content-Type'] = 'application/json';
|
||||
}
|
||||
|
||||
if (log_lvl > 1) {
|
||||
console.log('Cleaned Headers:', headers_cleaned);
|
||||
}
|
||||
|
||||
// console.log('HERE!! API POST 4');
|
||||
|
||||
for (let attempt = 1; attempt <= retry_count; attempt++) {
|
||||
try {
|
||||
const controller = new AbortController();
|
||||
const fetchOptions: RequestInit = {
|
||||
method: 'POST',
|
||||
headers: headers_cleaned,
|
||||
body: form_data ? form_data : JSON.stringify(data),
|
||||
signal: controller.signal
|
||||
};
|
||||
|
||||
if (log_lvl > 1) {
|
||||
console.log('Fetch Options:', fetchOptions);
|
||||
}
|
||||
|
||||
const response = await fetch(url.toString(), fetchOptions);
|
||||
|
||||
if (log_lvl) {
|
||||
console.log(`Response: status=${response.status} attempt=${attempt}`);
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
if (response.status === 404) {
|
||||
console.warn('404 Not Found. Returning null.');
|
||||
return null; // Returning null since there were no results
|
||||
}
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
if (!return_blob) {
|
||||
const json = await response.json();
|
||||
|
||||
if (log_lvl > 1) {
|
||||
console.log('Response JSON:', json);
|
||||
}
|
||||
|
||||
// Post a message to the window indicating the upload is complete
|
||||
try {
|
||||
window.postMessage(
|
||||
{
|
||||
type: 'api_post_json_form',
|
||||
status: 'complete',
|
||||
task_id: task_id,
|
||||
endpoint: endpoint,
|
||||
size_total: 0,
|
||||
size_loaded: 0,
|
||||
percent_completed: 100,
|
||||
progress: 100,
|
||||
rate: 0
|
||||
},
|
||||
'*'
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('Error posting message to window:', error);
|
||||
}
|
||||
|
||||
// Return the response data or metadata
|
||||
return return_meta ? json : json.data;
|
||||
} else {
|
||||
const blob = await response.blob();
|
||||
|
||||
if (auto_download) {
|
||||
const downloadUrl = window.URL.createObjectURL(blob);
|
||||
const link = document.createElement('a');
|
||||
link.href = downloadUrl;
|
||||
link.setAttribute('download', filename || 'download');
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
link.remove();
|
||||
return true;
|
||||
} else {
|
||||
return blob;
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`API POST error on attempt ${attempt}:`, error);
|
||||
|
||||
// If this is the last attempt, return false
|
||||
if (attempt === retry_count) {
|
||||
console.error('Max retry attempts reached. Returning false.');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Log retry information
|
||||
if (log_lvl) {
|
||||
console.log(`Retrying... (${attempt}/${retry_count})`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// let axios_api = axios.create({
|
||||
// baseURL: api_cfg['base_url'],
|
||||
// /* other custom settings */
|
||||
// });
|
||||
// axios_api.defaults.headers = api_cfg['headers'];
|
||||
// console.log('Axios API', axios_api);
|
||||
// // console.log('Axios API POST', axios_api.post);
|
||||
|
||||
// // if (typeof data == 'FormData') {
|
||||
// if (form_data) {
|
||||
// axios_api.defaults.headers['content-type'] = 'multipart/form-data';
|
||||
// data = form_data;
|
||||
// } else {
|
||||
// axios_api.defaults.headers['content-type'] = 'application/json';
|
||||
// }
|
||||
|
||||
// if (!return_blob) {
|
||||
// let response_data = await axios_api.post(
|
||||
// endpoint,
|
||||
// data,
|
||||
// {
|
||||
// params: params,
|
||||
// onUploadProgress: (progressEvent) => {
|
||||
// let percent_completed = Math.round(
|
||||
// (progressEvent.loaded * 100) / progressEvent.total
|
||||
// );
|
||||
// console.log('POST Progress:', progressEvent.progress, 'Total:', progressEvent.total, 'Loaded:', progressEvent.loaded, 'Percent Completed', percent_completed);
|
||||
|
||||
// temp_post_object_percent_completed = percent_completed;
|
||||
|
||||
// try {
|
||||
// window.postMessage({
|
||||
// type: 'api_post_json_form',
|
||||
// status: 'uploading',
|
||||
// task_id: task_id,
|
||||
// endpoint: endpoint,
|
||||
// size_total: progressEvent.total,
|
||||
// size_loaded: progressEvent.loaded,
|
||||
// percent_completed: percent_completed,
|
||||
// progress: progressEvent.progress,
|
||||
// rate: progressEvent.rate,
|
||||
// },
|
||||
// '*'
|
||||
// );
|
||||
// } catch (error) {
|
||||
// console.log('Error posting message to window:', error);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// )
|
||||
// .then(function (response) {
|
||||
// console.log('POST Response Data:', response.data);
|
||||
// try {
|
||||
// window.postMessage({
|
||||
// type: 'api_post_json_form',
|
||||
// status: 'complete',
|
||||
// task_id: task_id,
|
||||
// endpoint: endpoint,
|
||||
// size_total: 0,
|
||||
// size_loaded: 0,
|
||||
// percent_completed: 100,
|
||||
// progress: 100,
|
||||
// rate: 0,
|
||||
// },
|
||||
// '*'
|
||||
// );
|
||||
// } catch (error) {
|
||||
// console.log('Error posting message to window:', error);
|
||||
// }
|
||||
|
||||
// if (response.data['data'].result === null) {
|
||||
// // This should mean that the request was successful, but a result of None/null was returned from Aether API.
|
||||
// // console.log('Returning null after POST');
|
||||
// return null;
|
||||
// } else {
|
||||
// // This should mean that the request was successful, and a result with data was returned from Aether API.
|
||||
// // console.log('Returning data after POST');
|
||||
// return response.data['data'];
|
||||
// }
|
||||
// //return response.data;
|
||||
// })
|
||||
// .catch(function (error: any) {
|
||||
// if (error.response && error.response.status === 404) {
|
||||
// return null; // Returning null since there were no results
|
||||
// }
|
||||
// console.log(error);
|
||||
// return false; // Returning false since something may have gone wrong. Also more in line with what the API returns.
|
||||
// // return error;
|
||||
// });
|
||||
|
||||
// if (log_lvl > 1) {
|
||||
// console.log('Response Data:', response_data);
|
||||
// }
|
||||
// axios_api.defaults.headers['content-type'] = 'application/json';
|
||||
// return response_data;
|
||||
|
||||
// } else {
|
||||
// // console.log('Expecting a Blob to be returned...');
|
||||
|
||||
// let response_data_promise = await axios_api.post(
|
||||
// endpoint,
|
||||
// data,
|
||||
// {
|
||||
// params: params,
|
||||
// responseType: 'blob',
|
||||
// onDownloadProgress: (progressEvent) => {
|
||||
// let percent_completed = Math.round(
|
||||
// (progressEvent.loaded * 100) / progressEvent.total
|
||||
// );
|
||||
// console.log('POST Blob Progress:', progressEvent.progress, 'Total:', progressEvent.total, 'Loaded:', progressEvent.loaded, 'Percent Completed', percent_completed);
|
||||
|
||||
// temp_post_blob_percent_completed = percent_completed;
|
||||
// }
|
||||
// }
|
||||
// )
|
||||
// .then(function (response) {
|
||||
// if (log_lvl) {
|
||||
// console.log(response);
|
||||
// }
|
||||
|
||||
// const { data, headers } = response
|
||||
// console.log(headers);
|
||||
|
||||
// if (filename) {
|
||||
// } else if (headers['content-disposition']) {
|
||||
// filename = headers['content-disposition'].replace(/\w+;filename=(.*)/, '$1');
|
||||
// } else {
|
||||
// filename = 'unknown_file.ext';
|
||||
// }
|
||||
|
||||
// if (auto_download) {
|
||||
// const url = window.URL.createObjectURL(new Blob([response.data]));
|
||||
// const link = document.createElement('a');
|
||||
// link.href = url;
|
||||
// // link.setAttribute('download', 'event_exhibit_tracking_export.xlsx'); //or any other extension
|
||||
// link.setAttribute('download', filename); //or any other extension
|
||||
// document.body.appendChild(link);
|
||||
// link.click();
|
||||
// return true;
|
||||
// } else {
|
||||
// return response;
|
||||
// }
|
||||
// });
|
||||
|
||||
// if (response_data_promise) {
|
||||
// // The most common and expected response.
|
||||
// // console.log('Returning result. This is generally expected.');
|
||||
// // let test_blob = new Blob([response_data_promise.data]);
|
||||
// // console.log(test_blob);
|
||||
// // return test_blob;
|
||||
// // console.log(response_data_promise.blob());
|
||||
// return response_data_promise;
|
||||
// } else {
|
||||
// // This generally should not happen. It likely means the query was bad or an API issue.
|
||||
// console.log('Returning unknown. This should not happen in most cases.');
|
||||
// Promise.reject(new Error('fail')).then(resolved, rejected);
|
||||
// }
|
||||
// }
|
||||
};
|
||||
|
||||
// function resolved(result: any) {
|
||||
// console.log('Resolved');
|
||||
// }
|
||||
|
||||
// function rejected(result: any) {
|
||||
// console.error(result);
|
||||
// }
|
||||
28
src/lib/ae_archives/README.md
Normal file
28
src/lib/ae_archives/README.md
Normal file
@@ -0,0 +1,28 @@
|
||||
# Aether (AE) Archives Module
|
||||
|
||||
The Archives module is a system for storing and retrieving archived data. It is composed of two main data structures: `Archive` and `Archive_Content`.
|
||||
|
||||
## Data Structures
|
||||
|
||||
### Archive
|
||||
|
||||
An `Archive` is a container for a collection of `Archive_Content` items. It has a name, description, and other metadata.
|
||||
|
||||
### Archive Content
|
||||
|
||||
An `Archive_Content` item represents a single piece of content within an `Archive`. This can be text, a file, a URL, or other data.
|
||||
|
||||
## Functionality
|
||||
|
||||
This module provides the following functionality:
|
||||
|
||||
- **CRUD Operations:** Create, Read, Update, and Delete operations for both `Archive` and `Archive_Content` objects.
|
||||
- **Local Caching:** Uses Dexie.js to cache data in the browser's IndexedDB for offline access and faster load times.
|
||||
- **API Interaction:** All data operations are synced with the backend API.
|
||||
|
||||
## Files
|
||||
|
||||
- `ae_archives__archive.ts`: Contains functions for managing `Archive` objects.
|
||||
- `ae_archives__archive_content.ts`: Contains functions for managing `Archive_Content` objects.
|
||||
- `ae_archives_functions.ts`: Exports all the functions from the module for easy use in other parts of the application.
|
||||
- `db_archives.ts`: Defines the IndexedDB schema for the archives module using Dexie.js.
|
||||
892
src/lib/ae_archives/ae_archives__archive.ts
Normal file
892
src/lib/ae_archives/ae_archives__archive.ts
Normal file
@@ -0,0 +1,892 @@
|
||||
import type { key_val } from '$lib/stores/ae_stores';
|
||||
import { api } from '$lib/api/api';
|
||||
|
||||
import { db_save_ae_obj_li__ae_obj } from '$lib/ae_core/core__idb_dexie';
|
||||
import { db_archives } from '$lib/ae_archives/db_archives';
|
||||
|
||||
import { load_ae_obj_li__archive_content } from '$lib/ae_archives/ae_archives__archive_content';
|
||||
|
||||
const ae_promises: key_val = {};
|
||||
|
||||
// Updated 2024-09-25
|
||||
export async function load_ae_obj_id__archive({
|
||||
api_cfg,
|
||||
archive_id,
|
||||
inc_content_li = false,
|
||||
enabled = 'enabled',
|
||||
hidden = 'not_hidden',
|
||||
limit = 99,
|
||||
offset = 0,
|
||||
params = {},
|
||||
try_cache = true,
|
||||
log_lvl = 0
|
||||
}: {
|
||||
api_cfg: any;
|
||||
archive_id: string;
|
||||
inc_content_li?: boolean;
|
||||
enabled?: 'enabled' | 'all' | 'not_enabled' | undefined;
|
||||
hidden?: 'hidden' | 'all' | 'not_hidden' | undefined;
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
params?: key_val;
|
||||
try_cache?: boolean;
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
if (log_lvl) {
|
||||
console.log(`*** load_ae_obj_id__archive() *** archive_id=${archive_id}`);
|
||||
}
|
||||
|
||||
ae_promises.load__archive_obj = await api
|
||||
.get_ae_obj_id_crud({
|
||||
api_cfg: api_cfg,
|
||||
obj_type: 'archive',
|
||||
obj_id: archive_id,
|
||||
use_alt_table: true,
|
||||
use_alt_base: false,
|
||||
params: params,
|
||||
log_lvl: log_lvl
|
||||
})
|
||||
.then(async function (archive_obj_get_result) {
|
||||
if (archive_obj_get_result) {
|
||||
if (try_cache) {
|
||||
// Process the results first
|
||||
const processed_obj_li = await process_ae_obj__archive_props({
|
||||
obj_li: [archive_obj_get_result],
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
if (log_lvl) {
|
||||
console.log('Processed object list:', processed_obj_li);
|
||||
}
|
||||
// Save the updated results list to the database
|
||||
if (log_lvl) {
|
||||
console.log('Saving to DB...');
|
||||
}
|
||||
await db_save_ae_obj_li__ae_obj({
|
||||
db_instance: db_archives,
|
||||
table_name: 'archive',
|
||||
obj_li: processed_obj_li,
|
||||
properties_to_save: properties_to_save,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
if (log_lvl) {
|
||||
console.log('DB save completed.');
|
||||
}
|
||||
|
||||
// // This is expecting a list
|
||||
// db_save_ae_obj_li__archive({
|
||||
// obj_type: 'archive',
|
||||
// obj_li: [archive_obj_get_result]
|
||||
// });
|
||||
}
|
||||
return archive_obj_get_result;
|
||||
} else {
|
||||
console.log('No results returned.');
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.catch(function (error: any) {
|
||||
console.log('No results returned or failed.', error);
|
||||
});
|
||||
|
||||
if (log_lvl) {
|
||||
console.log('ae_promises.load__archive_obj:', ae_promises.load__archive_obj);
|
||||
}
|
||||
|
||||
if (inc_content_li) {
|
||||
// Load the contents for the archive
|
||||
if (log_lvl) {
|
||||
console.log(`Need to load the content list for the archive now`);
|
||||
}
|
||||
const load_archive_content_obj_li = load_ae_obj_li__archive_content({
|
||||
api_cfg: api_cfg,
|
||||
for_obj_type: 'archive',
|
||||
for_obj_id: archive_id,
|
||||
enabled: enabled, // all, disabled, enabled
|
||||
hidden: hidden, // all, hidden, not_hidden
|
||||
limit: limit, // Limit for the comments
|
||||
offset: offset,
|
||||
params: params,
|
||||
try_cache: try_cache,
|
||||
log_lvl: log_lvl
|
||||
}).then((archive_content_obj_li) => {
|
||||
if (log_lvl) {
|
||||
console.log(`archive_content_obj_li = `, archive_content_obj_li);
|
||||
}
|
||||
return archive_content_obj_li;
|
||||
});
|
||||
|
||||
if (log_lvl) {
|
||||
console.log(`archive_content_obj_li = `, load_archive_content_obj_li);
|
||||
}
|
||||
ae_promises.load__archive_obj.archive_content_li = load_archive_content_obj_li;
|
||||
}
|
||||
|
||||
return ae_promises.load__archive_obj;
|
||||
}
|
||||
|
||||
// Updated 2024-11-20
|
||||
export async function load_ae_obj_li__archive({
|
||||
api_cfg,
|
||||
for_obj_type = 'account',
|
||||
for_obj_id,
|
||||
inc_content_li = false,
|
||||
enabled = 'enabled',
|
||||
hidden = 'not_hidden',
|
||||
limit = 99,
|
||||
offset = 0,
|
||||
order_by_li = {
|
||||
priority: 'DESC',
|
||||
sort: 'DESC',
|
||||
name: 'ASC',
|
||||
updated_on: 'DESC',
|
||||
created_on: 'DESC'
|
||||
},
|
||||
params = {},
|
||||
try_cache = true,
|
||||
log_lvl = 0
|
||||
}: {
|
||||
api_cfg: any;
|
||||
for_obj_type: string;
|
||||
for_obj_id: string;
|
||||
inc_content_li?: boolean;
|
||||
enabled?: 'enabled' | 'all' | 'not_enabled' | undefined;
|
||||
hidden?: 'hidden' | 'all' | 'not_hidden' | undefined;
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
order_by_li?: key_val;
|
||||
params?: key_val;
|
||||
try_cache?: boolean;
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
if (log_lvl) {
|
||||
console.log(
|
||||
`*** load_ae_obj_li__archive() *** for_obj_type=${for_obj_type} for_obj_id=${for_obj_id}`
|
||||
);
|
||||
}
|
||||
|
||||
const params_json: key_val = {};
|
||||
|
||||
// console.log('params_json:', params_json);
|
||||
|
||||
ae_promises.load__archive_obj_li = await api
|
||||
.get_ae_obj_li_for_obj_id_crud_v2({
|
||||
api_cfg: api_cfg,
|
||||
obj_type: 'archive',
|
||||
for_obj_type: for_obj_type,
|
||||
for_obj_id: for_obj_id,
|
||||
use_alt_tbl: false,
|
||||
use_alt_mdl: false,
|
||||
use_alt_exp: false,
|
||||
enabled: enabled,
|
||||
hidden: hidden,
|
||||
order_by_li: order_by_li,
|
||||
limit: limit,
|
||||
offset: offset,
|
||||
params_json: params_json,
|
||||
params: params,
|
||||
log_lvl: log_lvl
|
||||
})
|
||||
.then(async function (archive_obj_li_get_result) {
|
||||
if (archive_obj_li_get_result) {
|
||||
if (try_cache) {
|
||||
// Process the results first
|
||||
const processed_obj_li = await process_ae_obj__archive_props({
|
||||
obj_li: archive_obj_li_get_result,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
if (log_lvl) {
|
||||
console.log('Processed object list:', processed_obj_li);
|
||||
}
|
||||
// Save the updated results list to the database
|
||||
if (log_lvl) {
|
||||
console.log('Saving to DB...');
|
||||
}
|
||||
await db_save_ae_obj_li__ae_obj({
|
||||
db_instance: db_archives,
|
||||
table_name: 'archive',
|
||||
obj_li: processed_obj_li,
|
||||
properties_to_save: properties_to_save,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
if (log_lvl) {
|
||||
console.log('DB save completed.');
|
||||
}
|
||||
|
||||
// db_save_ae_obj_li__archive({
|
||||
// obj_type: 'archive',
|
||||
// obj_li: archive_obj_li_get_result
|
||||
// });
|
||||
}
|
||||
return archive_obj_li_get_result;
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
});
|
||||
|
||||
if (log_lvl) {
|
||||
console.log('ae_promises.load__archive_obj_li:', ae_promises.load__archive_obj_li);
|
||||
}
|
||||
|
||||
if (inc_content_li) {
|
||||
// Load the contents for the archives
|
||||
if (log_lvl) {
|
||||
console.log(`Need to load the content list for each archive now`);
|
||||
}
|
||||
for (let i = 0; i < ae_promises.load__archive_obj_li.length; i++) {
|
||||
const archive_obj = ae_promises.load__archive_obj_li[i];
|
||||
const archive_id = archive_obj.archive_id_random;
|
||||
|
||||
const load_archive_content_obj_li = load_ae_obj_li__archive_content({
|
||||
api_cfg: api_cfg,
|
||||
for_obj_type: 'archive',
|
||||
for_obj_id: archive_id,
|
||||
enabled: enabled, // all, disabled, enabled
|
||||
hidden: hidden, // all, hidden, not_hidden
|
||||
limit: limit, // Limit for the comments
|
||||
offset: offset,
|
||||
params: params,
|
||||
try_cache: try_cache,
|
||||
log_lvl: log_lvl
|
||||
}).then((archive_content_obj_li) => {
|
||||
if (log_lvl) {
|
||||
console.log(`archive_content_obj_li = `, archive_content_obj_li);
|
||||
}
|
||||
|
||||
return archive_content_obj_li;
|
||||
});
|
||||
|
||||
if (log_lvl) {
|
||||
console.log(`load_archive_content_obj_li = `, load_archive_content_obj_li);
|
||||
}
|
||||
|
||||
if (load_archive_content_obj_li) {
|
||||
ae_promises.load__archive_obj_li[i].archive_content_obj_li =
|
||||
load_archive_content_obj_li;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ae_promises.load__archive_obj_li;
|
||||
}
|
||||
|
||||
// Updated 2025-06-23
|
||||
export async function create_ae_obj__archive({
|
||||
api_cfg,
|
||||
account_id,
|
||||
data_kv,
|
||||
params = {},
|
||||
try_cache = true,
|
||||
log_lvl = 0
|
||||
}: {
|
||||
api_cfg: any;
|
||||
account_id: string;
|
||||
data_kv: key_val;
|
||||
params?: key_val;
|
||||
try_cache?: boolean;
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
if (log_lvl) {
|
||||
console.log(`*** create_ae_obj__archive() *** account_id=${account_id}`);
|
||||
}
|
||||
|
||||
if (!account_id) {
|
||||
console.log(`ERROR: Archives - Archive - account_id required to create`);
|
||||
return false;
|
||||
}
|
||||
|
||||
ae_promises.create__archive = await api
|
||||
.create_ae_obj_crud({
|
||||
api_cfg: api_cfg,
|
||||
obj_type: 'archive',
|
||||
fields: {
|
||||
account_id_random: account_id,
|
||||
...data_kv
|
||||
},
|
||||
key: api_cfg.api_crud_super_key,
|
||||
params: params,
|
||||
return_obj: true,
|
||||
log_lvl: log_lvl
|
||||
})
|
||||
.then(async function (archive_obj_create_result) {
|
||||
if (archive_obj_create_result) {
|
||||
if (try_cache) {
|
||||
// Process the results first
|
||||
const processed_obj_li = await process_ae_obj__archive_props({
|
||||
obj_li: [archive_obj_create_result],
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
if (log_lvl) {
|
||||
console.log('Processed object list:', processed_obj_li);
|
||||
}
|
||||
// Save the updated results list to the database
|
||||
if (log_lvl) {
|
||||
console.log('Saving to DB...');
|
||||
}
|
||||
await db_save_ae_obj_li__ae_obj({
|
||||
db_instance: db_archives,
|
||||
table_name: 'archive',
|
||||
obj_li: processed_obj_li,
|
||||
properties_to_save: properties_to_save,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
if (log_lvl) {
|
||||
console.log('DB save completed.');
|
||||
}
|
||||
|
||||
// db_save_ae_obj_li__archive(
|
||||
// {
|
||||
// obj_type: 'archive',
|
||||
// obj_li: [archive_obj_create_result]
|
||||
// });
|
||||
}
|
||||
return archive_obj_create_result;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.catch(function (error: any) {
|
||||
console.log('No results returned or failed.', error);
|
||||
});
|
||||
|
||||
if (log_lvl) {
|
||||
console.log('ae_promises.create__archive:', ae_promises.create__archive);
|
||||
}
|
||||
return ae_promises.create__archive;
|
||||
}
|
||||
|
||||
// Updated 2024-11-08
|
||||
export async function delete_ae_obj_id__archive({
|
||||
api_cfg,
|
||||
archive_id,
|
||||
method = 'delete', // 'delete', 'disable', 'hide'
|
||||
params = {},
|
||||
try_cache = true,
|
||||
log_lvl = 0
|
||||
}: {
|
||||
api_cfg: any;
|
||||
archive_id: string;
|
||||
method?: string;
|
||||
params?: key_val;
|
||||
try_cache?: boolean;
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
if (log_lvl) {
|
||||
console.log(`*** delete_ae_obj_id__archive() *** archive_id=${archive_id}`);
|
||||
}
|
||||
|
||||
ae_promises.delete__archive_obj = await api
|
||||
.delete_ae_obj_id_crud({
|
||||
api_cfg: api_cfg,
|
||||
obj_type: 'archive',
|
||||
obj_id: archive_id,
|
||||
key: api_cfg.api_crud_super_key,
|
||||
params: params,
|
||||
method: method,
|
||||
log_lvl: log_lvl
|
||||
})
|
||||
.catch(function (error: any) {
|
||||
console.log('No results returned or failed.', error);
|
||||
})
|
||||
.finally(function () {
|
||||
if (try_cache) {
|
||||
if (log_lvl) {
|
||||
console.log(`Attempting to remove IDB entry for archive_id=${archive_id}`);
|
||||
}
|
||||
db_archives.content.delete(archive_id); // Delete from the DB no matter what.
|
||||
}
|
||||
});
|
||||
|
||||
if (log_lvl) {
|
||||
console.log('ae_promises.delete__archive_obj:', ae_promises.delete__archive_obj);
|
||||
}
|
||||
|
||||
return ae_promises.delete__archive_obj;
|
||||
}
|
||||
|
||||
// Updated 2025-06-23
|
||||
export async function update_ae_obj__archive({
|
||||
api_cfg,
|
||||
archive_id,
|
||||
data_kv,
|
||||
params = {},
|
||||
try_cache = true,
|
||||
log_lvl = 0
|
||||
}: {
|
||||
api_cfg: any;
|
||||
archive_id: string;
|
||||
data_kv: key_val;
|
||||
params?: key_val;
|
||||
try_cache?: boolean;
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
if (log_lvl) {
|
||||
console.log(`*** update_ae_obj__archive() *** archive_id=${archive_id}`, data_kv);
|
||||
}
|
||||
|
||||
// Perform the API update
|
||||
const result = await api.update_ae_obj_id_crud({
|
||||
api_cfg: api_cfg,
|
||||
obj_type: 'archive',
|
||||
obj_id: archive_id,
|
||||
fields: data_kv,
|
||||
key: api_cfg.api_crud_super_key,
|
||||
params: params,
|
||||
return_obj: true,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
|
||||
// Handle the result
|
||||
if (result) {
|
||||
if (try_cache) {
|
||||
// Process the results first
|
||||
const processed_obj_li = await process_ae_obj__archive_props({
|
||||
obj_li: [result],
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
if (log_lvl) {
|
||||
console.log('Processed object list:', processed_obj_li);
|
||||
}
|
||||
// Save the updated results list to the database
|
||||
if (log_lvl) {
|
||||
console.log('Saving to DB...');
|
||||
}
|
||||
await db_save_ae_obj_li__ae_obj({
|
||||
db_instance: db_archives,
|
||||
table_name: 'archive',
|
||||
obj_li: processed_obj_li,
|
||||
properties_to_save: properties_to_save,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
if (log_lvl) {
|
||||
console.log('DB save completed.');
|
||||
}
|
||||
|
||||
// await db_save_ae_obj_li__archive({
|
||||
// obj_type: 'archive',
|
||||
// obj_li: [result],
|
||||
// log_lvl: log_lvl,
|
||||
// });
|
||||
}
|
||||
return result;
|
||||
} else {
|
||||
console.error('Failed to update archive.');
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// This new function is using CRUD v2. This should allow for more flexibility in the queries.
|
||||
// Updated 2024-09-25
|
||||
export async function qry__archive({
|
||||
api_cfg,
|
||||
archive_id,
|
||||
qry_str,
|
||||
qry_files,
|
||||
qry_start_datetime, // Example greater than: '2024-10-24'
|
||||
enabled = 'enabled',
|
||||
hidden = 'not_hidden',
|
||||
limit = 50,
|
||||
offset = 0,
|
||||
params = {},
|
||||
try_cache = true,
|
||||
log_lvl = 0
|
||||
}: {
|
||||
api_cfg: any;
|
||||
archive_id: any;
|
||||
qry_str?: string;
|
||||
qry_files?: null | boolean;
|
||||
qry_start_datetime?: null | string; // Greater than this datetime
|
||||
enabled?: 'enabled' | 'all' | 'not_enabled' | undefined; // all, disabled, enabled
|
||||
hidden?: 'hidden' | 'all' | 'not_hidden' | undefined; // all, hidden, not_hidden
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
params?: any;
|
||||
try_cache?: boolean;
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
console.log(`*** qry__archive() *** archive_id=${archive_id} qry_str=${qry_str}`);
|
||||
|
||||
// let enabled: string = (params.qry__enabled ?? 'enabled'); // all, disabled, enabled
|
||||
// let hidden: string = (params.qry__hidden ?? 'not_hidden'); // all, hidden, not_hidden
|
||||
// let limit: number = (params.qry__limit ?? 25); // 99
|
||||
// let offset: number = (params.qry__offset ?? 0); // 0
|
||||
|
||||
const params_json: key_val = {};
|
||||
|
||||
// if (qry_str && qry_str.length > 2) {
|
||||
// params_json['ft_qry'] = {};
|
||||
// params_json['ft_qry']['default_qry_str'] = qry_str;
|
||||
// }
|
||||
|
||||
params_json['qry'] = [];
|
||||
|
||||
if (qry_files === true) {
|
||||
const qry_param = {
|
||||
type: 'AND',
|
||||
field: 'file_count_all',
|
||||
operator: '>',
|
||||
value: 0
|
||||
};
|
||||
params_json['qry'].push(qry_param);
|
||||
} else if (qry_files === false) {
|
||||
const qry_param = {
|
||||
type: 'AND',
|
||||
field: 'file_count_all',
|
||||
operator: 'IS',
|
||||
value: null
|
||||
};
|
||||
params_json['qry'].push(qry_param);
|
||||
}
|
||||
|
||||
if (qry_start_datetime) {
|
||||
const qry_param = {
|
||||
type: 'AND',
|
||||
field: 'start_datetime',
|
||||
operator: '>',
|
||||
value: qry_start_datetime
|
||||
};
|
||||
params_json['qry'].push(qry_param);
|
||||
}
|
||||
|
||||
const order_by_li = {
|
||||
priority: 'DESC',
|
||||
sort: 'DESC',
|
||||
start_datetime: 'ASC',
|
||||
name: 'ASC',
|
||||
updated_on: 'DESC',
|
||||
created_on: 'DESC'
|
||||
};
|
||||
|
||||
ae_promises.load__archive_obj_li = await api
|
||||
.get_ae_obj_li_for_obj_id_crud_v2({
|
||||
api_cfg: api_cfg,
|
||||
obj_type: 'archive',
|
||||
for_obj_type: 'event',
|
||||
for_obj_id: archive_id,
|
||||
use_alt_tbl: true, // NOTE: We want to use the alt table for archive searching
|
||||
use_alt_mdl: false,
|
||||
use_alt_exp: false,
|
||||
enabled: enabled,
|
||||
hidden: hidden,
|
||||
order_by_li: order_by_li,
|
||||
limit: limit,
|
||||
offset: offset,
|
||||
params_json: params_json,
|
||||
params: params,
|
||||
log_lvl: log_lvl
|
||||
})
|
||||
.then(async function (archive_obj_li_get_result) {
|
||||
if (archive_obj_li_get_result) {
|
||||
if (try_cache) {
|
||||
// Process the results first
|
||||
const processed_obj_li = await process_ae_obj__archive_props({
|
||||
obj_li: archive_obj_li_get_result,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
if (log_lvl) {
|
||||
console.log('Processed object list:', processed_obj_li);
|
||||
}
|
||||
// Save the updated results list to the database
|
||||
if (log_lvl) {
|
||||
console.log('Saving to DB...');
|
||||
}
|
||||
await db_save_ae_obj_li__ae_obj({
|
||||
db_instance: db_archives,
|
||||
table_name: 'archive',
|
||||
obj_li: processed_obj_li,
|
||||
properties_to_save: properties_to_save,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
if (log_lvl) {
|
||||
console.log('DB save completed.');
|
||||
}
|
||||
}
|
||||
return archive_obj_li_get_result;
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
});
|
||||
|
||||
if (log_lvl) {
|
||||
console.log('ae_promises.load__archive_obj_li:', ae_promises.load__archive_obj_li);
|
||||
}
|
||||
return ae_promises.load__archive_obj_li;
|
||||
}
|
||||
|
||||
// // Updated 2024-09-25
|
||||
// export async function search__archive(
|
||||
// {
|
||||
// api_cfg,
|
||||
// account_id,
|
||||
// poc_agree = null,
|
||||
// fulltext_search_qry_str,
|
||||
// ft_content_search_qry_str,
|
||||
// like_search_qry_str = null,
|
||||
// file_count = false, // If true then only show those that have a file count
|
||||
// person_name = null,
|
||||
// params = {},
|
||||
// try_cache = true,
|
||||
// log_lvl = 0
|
||||
// }: {
|
||||
// api_cfg: any,
|
||||
// account_id: any,
|
||||
// poc_agree?: null|boolean,
|
||||
// fulltext_search_qry_str?: null|string,
|
||||
// ft_content_search_qry_str?: null|string,
|
||||
// like_search_qry_str?: null|string,
|
||||
// file_count?: boolean,
|
||||
// person_name?: null|string,
|
||||
// params?: any,
|
||||
// try_cache?: boolean,
|
||||
// log_lvl?: number
|
||||
// }
|
||||
// ) {
|
||||
// console.log(`*** search__archive() *** account_id=${account_id}`);
|
||||
|
||||
// let enabled: string = (params.qry__enabled ?? 'enabled'); // all, disabled, enabled
|
||||
// let hidden: string = (params.qry__hidden ?? 'not_hidden'); // all, hidden, not_hidden
|
||||
// let limit: number = (params.qry__limit ?? 25); // 99
|
||||
// let offset: number = (params.qry__offset ?? 0); // 0
|
||||
|
||||
// let params_json: key_val = {};
|
||||
|
||||
// // if (!fulltext_search_qry_str && !like_search_qry_str) {
|
||||
// // console.log('No search string provided!!!');
|
||||
// // return false; // Returning false instead of [] because no search was performed.
|
||||
// // }
|
||||
|
||||
// if (fulltext_search_qry_str || ft_content_search_qry_str) {
|
||||
// params_json['ft_qry'] = {};
|
||||
// if (fulltext_search_qry_str && fulltext_search_qry_str.length > 2) {
|
||||
// params_json['ft_qry']['default_qry_str'] = fulltext_search_qry_str;
|
||||
// }
|
||||
|
||||
// if (ft_content_search_qry_str && ft_content_search_qry_str.length > 2) {
|
||||
// params_json['ft_qry']['archive_content_li_qry_str'] = ft_content_search_qry_str;
|
||||
// }
|
||||
// }
|
||||
|
||||
// // Use the AND (AND LIKE) query
|
||||
// // if (like_search_qry_str || like_content_search_qry_str) {
|
||||
// // params_json['and_like'] = {};
|
||||
// // if (like_search_qry_str && like_search_qry_str.length > 2) {
|
||||
// // params_json['and_like']['default_qry_str'] = like_search_qry_str;
|
||||
// // }
|
||||
// // if (like_content_search_qry_str && like_content_search_qry_str.length > 2) {
|
||||
// // params_json['and_like']['archive_content_li_qry_str'] = like_content_search_qry_str;
|
||||
// // }
|
||||
// // }
|
||||
|
||||
// // Use the AND (OR LIKE) query
|
||||
// if (like_search_qry_str || like_content_search_qry_str || like_content_search_qry_str) {
|
||||
// params_json['or_like'] = {};
|
||||
// if (like_search_qry_str && like_search_qry_str.length > 2) {
|
||||
// params_json['or_like']['default_qry_str'] = like_search_qry_str;
|
||||
// }
|
||||
// if (like_content_search_qry_str && like_content_search_qry_str.length > 2) {
|
||||
// params_json['or_like']['archive_content_li_qry_str'] = like_content_search_qry_str;
|
||||
// }
|
||||
// if (like_content_search_qry_str && like_content_search_qry_str.length > 2) {
|
||||
// params_json['or_like']['archive_content_li_qry_str'] = like_content_search_qry_str;
|
||||
// }
|
||||
// }
|
||||
|
||||
// params_json['and_qry'] = {};
|
||||
|
||||
// if (poc_agree) {
|
||||
// params_json['and_qry']['poc_agree'] = poc_agree;
|
||||
// }
|
||||
|
||||
// if (file_count) {
|
||||
// params_json['and_qry']['file_count'] = file_count;
|
||||
// }
|
||||
|
||||
// // This should be using a like with surrounded by %'s
|
||||
// if (person_name) {
|
||||
// params_json['and_qry']['archive_full_name'] = person_name;
|
||||
// }
|
||||
|
||||
// let order_by_li = {'priority': 'DESC', 'sort': 'DESC', 'name': 'ASC', 'updated_on': 'DESC', 'created_on': 'DESC'};
|
||||
|
||||
// ae_promises.load__archive_obj_li = await api.get_ae_obj_li_for_obj_id_crud({
|
||||
// api_cfg: api_cfg,
|
||||
// obj_type: 'archive',
|
||||
// for_obj_type: 'account',
|
||||
// for_obj_id: account_id,
|
||||
// use_alt_table: true, // NOTE: We want to use the alt table for archive searching
|
||||
// use_alt_base: false,
|
||||
// enabled: enabled,
|
||||
// hidden: hidden,
|
||||
// order_by_li: order_by_li,
|
||||
// limit: limit,
|
||||
// offset: offset,
|
||||
// params_json: params_json,
|
||||
// params: params,
|
||||
// log_lvl: log_lvl
|
||||
// })
|
||||
// .then(function (archive_obj_li_get_result) {
|
||||
// if (archive_obj_li_get_result) {
|
||||
// if (try_cache) {
|
||||
// db_save_ae_obj_li__archive({
|
||||
// obj_type: 'archive',
|
||||
// obj_li: archive_obj_li_get_result
|
||||
// });
|
||||
// }
|
||||
// return archive_obj_li_get_result;
|
||||
// } else {
|
||||
// return [];
|
||||
// }
|
||||
// })
|
||||
// .catch(function (error: any) {
|
||||
// console.log('No results returned or failed.', error);
|
||||
// })
|
||||
// .finally(function () {
|
||||
// });
|
||||
|
||||
// if (log_lvl) {
|
||||
// console.log('ae_promises.load__archive_obj_li:', ae_promises.load__archive_obj_li);
|
||||
// }
|
||||
// return ae_promises.load__archive_obj_li;
|
||||
// }
|
||||
|
||||
// Updated 2025-06-04
|
||||
export const properties_to_save = [
|
||||
'id',
|
||||
'archive_id',
|
||||
// 'archive_id_random',
|
||||
|
||||
'code',
|
||||
|
||||
'account_id',
|
||||
// 'account_id_random',
|
||||
|
||||
'name',
|
||||
'description',
|
||||
|
||||
'original_datetime',
|
||||
'original_timezone',
|
||||
'original_location',
|
||||
|
||||
'original_url',
|
||||
'original_url_text',
|
||||
|
||||
'sort_by',
|
||||
'sort_by_desc',
|
||||
|
||||
'cfg_json',
|
||||
|
||||
'enable',
|
||||
'hide',
|
||||
'priority',
|
||||
'sort',
|
||||
'group',
|
||||
'notes',
|
||||
'created_on',
|
||||
'updated_on',
|
||||
|
||||
// Generated fields for sorting locally only
|
||||
'tmp_sort_1',
|
||||
'tmp_sort_2'
|
||||
// 'tmp_sort_a',
|
||||
// 'tmp_sort_b',
|
||||
|
||||
// From SQL view
|
||||
// 'archive_content_count',
|
||||
|
||||
// A key value list of the contents
|
||||
// 'archive_content_kv',
|
||||
// 'archive_content_li',
|
||||
];
|
||||
|
||||
/**
|
||||
* NON-EXPORTED LOCAL HELPER
|
||||
* Processes a list of Aether objects by applying common and specific transformations.
|
||||
*/
|
||||
async function _process_generic_props<T extends Record<string, any>>({
|
||||
obj_li,
|
||||
obj_type,
|
||||
log_lvl = 0,
|
||||
specific_processor
|
||||
}: {
|
||||
obj_li: T[];
|
||||
obj_type: string;
|
||||
log_lvl?: number;
|
||||
specific_processor?: (obj: T) => Promise<T> | T;
|
||||
}): Promise<T[]> {
|
||||
if (log_lvl > 0) {
|
||||
console.log(
|
||||
`*** _process_generic_props: Processing ${obj_li.length} objects of type "${obj_type}" ***`
|
||||
);
|
||||
}
|
||||
|
||||
if (!obj_li || obj_li.length === 0) {
|
||||
if (log_lvl > 0) console.log('No objects to process.');
|
||||
return [];
|
||||
}
|
||||
|
||||
const processed_obj_li: T[] = [];
|
||||
|
||||
for (const original_obj of obj_li) {
|
||||
let processed_obj = { ...original_obj };
|
||||
|
||||
// --- Common Transformations ---
|
||||
|
||||
// 1. Standardize ID and other '_random' fields
|
||||
// The API often returns fields like 'person_id_random', which need to be aliased to 'person_id'.
|
||||
for (const key in processed_obj) {
|
||||
if (key.endsWith('_random')) {
|
||||
const newKey = key.slice(0, -7); // Remove '_random' suffix
|
||||
processed_obj[newKey] = processed_obj[key];
|
||||
}
|
||||
}
|
||||
// Ensure 'id' is set from '[obj_type]_id_random'
|
||||
const randomIdKey = `${obj_type}_id_random`;
|
||||
if (processed_obj[randomIdKey]) {
|
||||
(processed_obj as any).id = processed_obj[randomIdKey];
|
||||
}
|
||||
|
||||
// 2. Create common computed properties for client-side sorting.
|
||||
const group = processed_obj.group ?? '0';
|
||||
const priority = processed_obj.priority ? 1 : 0;
|
||||
const sort = processed_obj.sort ?? '0';
|
||||
const updated = processed_obj.updated_on ?? processed_obj.created_on;
|
||||
const name = processed_obj.name ?? '';
|
||||
|
||||
(processed_obj as any).tmp_sort_1 = `${group}_${priority}_${sort}_${updated}`;
|
||||
(processed_obj as any).tmp_sort_2 = `${group}_${priority}_${sort}_${name}_${updated}`;
|
||||
|
||||
// --- Specific Transformations ---
|
||||
if (specific_processor) {
|
||||
processed_obj = await Promise.resolve(specific_processor(processed_obj));
|
||||
}
|
||||
|
||||
processed_obj_li.push(processed_obj as T);
|
||||
}
|
||||
|
||||
return processed_obj_li;
|
||||
}
|
||||
|
||||
// Updated 2025-06-04
|
||||
export async function process_ae_obj__archive_props({
|
||||
obj_li,
|
||||
log_lvl = 0
|
||||
}: {
|
||||
obj_li: any[];
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
return _process_generic_props({
|
||||
obj_li,
|
||||
obj_type: 'archive',
|
||||
log_lvl,
|
||||
specific_processor: (obj) => {
|
||||
// Archive-specific computed sort fields, overriding generic ones if needed
|
||||
obj.tmp_sort_1 = `${obj.group ?? ''}_${obj.priority ? '1' : '0'}_${
|
||||
obj.sort?.toString().padStart(3, '0') ?? ''
|
||||
}_${obj.updated_on ?? obj.created_on}`;
|
||||
obj.tmp_sort_2 = `${obj.group ?? ''}_${obj.priority ? '1' : '0'}_${
|
||||
obj.sort?.toString().padStart(3, '0') ?? ''
|
||||
}_${obj.updated_on}_${obj.created_on}`;
|
||||
|
||||
return obj;
|
||||
}
|
||||
});
|
||||
}
|
||||
577
src/lib/ae_archives/ae_archives__archive_content.ts
Normal file
577
src/lib/ae_archives/ae_archives__archive_content.ts
Normal file
@@ -0,0 +1,577 @@
|
||||
import type { key_val } from '$lib/stores/ae_stores';
|
||||
import { api } from '$lib/api/api';
|
||||
|
||||
import { db_save_ae_obj_li__ae_obj } from '$lib/ae_core/core__idb_dexie';
|
||||
import { db_archives } from '$lib/ae_archives/db_archives';
|
||||
|
||||
const ae_promises: key_val = {};
|
||||
|
||||
// TESTING NOTE: I changed these to all use async and await. Not sure if this helps or hurts things. Mainly this is related to the Dexie DB changes. 2024-11-08
|
||||
|
||||
// Updated 2024-09-25
|
||||
export async function load_ae_obj_id__archive_content({
|
||||
api_cfg,
|
||||
archive_content_id,
|
||||
// enabled = 'enabled',
|
||||
// hidden = 'not_hidden',
|
||||
// limit = 99,
|
||||
// offset = 0,
|
||||
params = {},
|
||||
try_cache = true,
|
||||
log_lvl = 0
|
||||
}: {
|
||||
api_cfg: any;
|
||||
archive_content_id: string;
|
||||
// enabled?: "enabled" | "all" | "not_enabled" | undefined,
|
||||
// hidden?: "hidden" | "all" | "not_hidden" | undefined,
|
||||
// limit?: number,
|
||||
// offset?: number,
|
||||
params?: key_val;
|
||||
try_cache?: boolean;
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
if (log_lvl) {
|
||||
console.log(
|
||||
`*** load_ae_obj_id__archive_content() *** archive_content_id=${archive_content_id}`
|
||||
);
|
||||
}
|
||||
|
||||
ae_promises.load__archive_content_obj = await api
|
||||
.get_ae_obj_id_crud({
|
||||
api_cfg: api_cfg,
|
||||
obj_type: 'archive_content',
|
||||
obj_id: archive_content_id,
|
||||
use_alt_table: false,
|
||||
use_alt_base: false,
|
||||
params: params,
|
||||
log_lvl: log_lvl
|
||||
})
|
||||
.then(async function (archive_content_obj_get_result) {
|
||||
if (archive_content_obj_get_result) {
|
||||
if (try_cache) {
|
||||
// Process the results first
|
||||
const processed_obj_li = await process_ae_obj__archive_content_props({
|
||||
obj_li: [archive_content_obj_get_result],
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
if (log_lvl) {
|
||||
console.log('Processed object list:', processed_obj_li);
|
||||
}
|
||||
// Save the updated results list to the database
|
||||
if (log_lvl) {
|
||||
console.log('Saving to DB...');
|
||||
}
|
||||
await db_save_ae_obj_li__ae_obj({
|
||||
db_instance: db_archives,
|
||||
table_name: 'content',
|
||||
obj_li: processed_obj_li,
|
||||
properties_to_save: properties_to_save,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
if (log_lvl) {
|
||||
console.log('DB save completed.');
|
||||
}
|
||||
|
||||
// // This is expecting a list
|
||||
// await db_save_ae_obj_li__archive_content({
|
||||
// obj_type: 'archive_content',
|
||||
// obj_li: [archive_content_obj_get_result]
|
||||
|
||||
// });
|
||||
}
|
||||
return archive_content_obj_get_result;
|
||||
} else {
|
||||
console.log('No results returned.');
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.catch(function (error: any) {
|
||||
console.log('No results returned or failed.', error);
|
||||
});
|
||||
|
||||
return ae_promises.load__archive_content_obj;
|
||||
}
|
||||
|
||||
// Updated 2024-11-20
|
||||
export async function load_ae_obj_li__archive_content({
|
||||
api_cfg,
|
||||
for_obj_type = 'archive',
|
||||
for_obj_id,
|
||||
enabled = 'enabled',
|
||||
hidden = 'not_hidden',
|
||||
limit = 99,
|
||||
offset = 0,
|
||||
order_by_li = {
|
||||
priority: 'DESC',
|
||||
sort: 'DESC',
|
||||
original_datetime: 'ASC',
|
||||
name: 'ASC',
|
||||
updated_on: 'DESC',
|
||||
created_on: 'DESC'
|
||||
},
|
||||
params = {},
|
||||
try_cache = true,
|
||||
log_lvl = 0
|
||||
}: {
|
||||
api_cfg: any;
|
||||
for_obj_type: string;
|
||||
for_obj_id: string;
|
||||
enabled?: 'enabled' | 'all' | 'not_enabled' | undefined;
|
||||
hidden?: 'hidden' | 'all' | 'not_hidden' | undefined;
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
order_by_li?: key_val;
|
||||
params?: key_val;
|
||||
try_cache?: boolean;
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
if (log_lvl) {
|
||||
console.log(
|
||||
`*** load_ae_obj_li__archive_content() *** for_obj_type=${for_obj_type} for_obj_id=${for_obj_id}`
|
||||
);
|
||||
}
|
||||
|
||||
const params_json: key_val = {};
|
||||
|
||||
// console('params_json:', params_json);
|
||||
|
||||
ae_promises.load__archive_content_obj_li = await api
|
||||
.get_ae_obj_li_for_obj_id_crud_v2({
|
||||
api_cfg: api_cfg,
|
||||
obj_type: 'archive_content',
|
||||
for_obj_type: for_obj_type,
|
||||
for_obj_id: for_obj_id,
|
||||
use_alt_tbl: false,
|
||||
use_alt_mdl: false,
|
||||
use_alt_exp: false,
|
||||
enabled: enabled,
|
||||
hidden: hidden,
|
||||
order_by_li: order_by_li,
|
||||
limit: limit,
|
||||
offset: offset,
|
||||
params_json: params_json,
|
||||
params: params,
|
||||
log_lvl: log_lvl
|
||||
})
|
||||
.then(async function (archive_content_obj_li_get_result) {
|
||||
if (archive_content_obj_li_get_result) {
|
||||
if (try_cache) {
|
||||
// Process the results first
|
||||
const processed_obj_li = await process_ae_obj__archive_content_props({
|
||||
obj_li: archive_content_obj_li_get_result,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
if (log_lvl) {
|
||||
console.log('Processed object list:', processed_obj_li);
|
||||
}
|
||||
// Save the updated results list to the database
|
||||
if (log_lvl) {
|
||||
console.log('Saving to DB...');
|
||||
}
|
||||
await db_save_ae_obj_li__ae_obj({
|
||||
db_instance: db_archives,
|
||||
table_name: 'content',
|
||||
obj_li: processed_obj_li,
|
||||
properties_to_save: properties_to_save,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
if (log_lvl) {
|
||||
console.log('DB save completed.');
|
||||
}
|
||||
|
||||
// await db_save_ae_obj_li__archive_content({
|
||||
// obj_type: 'archive_content', obj_li: archive_content_obj_li_get_result
|
||||
// });
|
||||
}
|
||||
return archive_content_obj_li_get_result;
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
})
|
||||
.catch(function (error: any) {
|
||||
console.log('No results returned or failed.', error);
|
||||
});
|
||||
|
||||
if (log_lvl) {
|
||||
console.log(
|
||||
'ae_promises.load__archive_content_obj_li:',
|
||||
ae_promises.load__archive_content_obj_li
|
||||
);
|
||||
}
|
||||
|
||||
return ae_promises.load__archive_content_obj_li;
|
||||
}
|
||||
|
||||
// Updated 2025-06-23
|
||||
export async function create_ae_obj__archive_content({
|
||||
api_cfg,
|
||||
archive_id,
|
||||
data_kv,
|
||||
params = {},
|
||||
try_cache = true,
|
||||
log_lvl = 0
|
||||
}: {
|
||||
api_cfg: any;
|
||||
archive_id: string;
|
||||
data_kv: key_val;
|
||||
params?: key_val;
|
||||
try_cache?: boolean;
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
if (log_lvl) {
|
||||
console.log(`*** create_ae_obj__archive_content() *** archive_id=${archive_id}`);
|
||||
}
|
||||
|
||||
if (!archive_id) {
|
||||
console.log(`ERROR: Archives - Content - archive_id required to create`);
|
||||
return false;
|
||||
}
|
||||
|
||||
ae_promises.create__archive_content = await api
|
||||
.create_ae_obj_crud({
|
||||
api_cfg: api_cfg,
|
||||
obj_type: 'archive_content',
|
||||
fields: {
|
||||
archive_id_random: archive_id,
|
||||
...data_kv
|
||||
},
|
||||
key: api_cfg.api_crud_super_key,
|
||||
params: params,
|
||||
return_obj: true,
|
||||
log_lvl: log_lvl
|
||||
})
|
||||
.then(async function (archive_content_obj_create_result) {
|
||||
if (archive_content_obj_create_result) {
|
||||
if (try_cache) {
|
||||
// Process the results first
|
||||
const processed_obj_li = await process_ae_obj__archive_content_props({
|
||||
obj_li: [archive_content_obj_create_result],
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
if (log_lvl) {
|
||||
console.log('Processed object list:', processed_obj_li);
|
||||
}
|
||||
// Save the updated results list to the database
|
||||
if (log_lvl) {
|
||||
console.log('Saving to DB...');
|
||||
}
|
||||
await db_save_ae_obj_li__ae_obj({
|
||||
db_instance: db_archives,
|
||||
table_name: 'content',
|
||||
obj_li: processed_obj_li,
|
||||
properties_to_save: properties_to_save,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
if (log_lvl) {
|
||||
console.log('DB save completed.');
|
||||
}
|
||||
|
||||
// await db_save_ae_obj_li__archive_content(
|
||||
// {
|
||||
// obj_type: 'archive_content',
|
||||
// obj_li: [archive_content_obj_create_result]
|
||||
// });
|
||||
}
|
||||
return archive_content_obj_create_result;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.catch(function (error: any) {
|
||||
console.log('No results returned or failed.', error);
|
||||
});
|
||||
|
||||
if (log_lvl) {
|
||||
console.log('ae_promises.create__archive_content:', ae_promises.create__archive_content);
|
||||
}
|
||||
return ae_promises.create__archive_content;
|
||||
}
|
||||
|
||||
// Updated 2024-11-08
|
||||
export async function delete_ae_obj_id__archive_content({
|
||||
api_cfg,
|
||||
archive_content_id,
|
||||
method = 'delete', // 'delete', 'disable', 'hide'
|
||||
params = {},
|
||||
try_cache = true,
|
||||
log_lvl = 0
|
||||
}: {
|
||||
api_cfg: any;
|
||||
archive_content_id: string;
|
||||
method?: string;
|
||||
params?: key_val;
|
||||
try_cache?: boolean;
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
if (log_lvl) {
|
||||
console.log(
|
||||
`*** delete_ae_obj_id__archive_content() *** archive_content_id=${archive_content_id}`
|
||||
);
|
||||
}
|
||||
|
||||
ae_promises.delete__archive_content_obj = await api
|
||||
.delete_ae_obj_id_crud({
|
||||
api_cfg: api_cfg,
|
||||
obj_type: 'archive_content',
|
||||
obj_id: archive_content_id,
|
||||
key: api_cfg.api_crud_super_key,
|
||||
params: params,
|
||||
method: method,
|
||||
log_lvl: log_lvl
|
||||
})
|
||||
.catch(function (error: any) {
|
||||
console.log('No results returned or failed.', error);
|
||||
})
|
||||
.finally(function () {
|
||||
if (try_cache) {
|
||||
if (log_lvl) {
|
||||
console.log(
|
||||
`Attempting to remove IDB entry for archive_content_id=${archive_content_id}`
|
||||
);
|
||||
}
|
||||
db_archives.content.delete(archive_content_id); // Delete from the DB no matter what.
|
||||
}
|
||||
});
|
||||
|
||||
if (log_lvl) {
|
||||
console.log(
|
||||
'ae_promises.delete__archive_content_obj:',
|
||||
ae_promises.delete__archive_content_obj
|
||||
);
|
||||
}
|
||||
|
||||
return ae_promises.delete__archive_content_obj;
|
||||
}
|
||||
|
||||
// Updated 2025-06-23
|
||||
export async function update_ae_obj__archive_content({
|
||||
api_cfg,
|
||||
archive_content_id,
|
||||
data_kv,
|
||||
params = {},
|
||||
try_cache = true,
|
||||
log_lvl = 0
|
||||
}: {
|
||||
api_cfg: any;
|
||||
archive_content_id: string;
|
||||
data_kv: key_val;
|
||||
params?: key_val;
|
||||
try_cache?: boolean;
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
if (log_lvl) {
|
||||
console.log(
|
||||
`*** update_ae_obj__archive_content() *** archive_content_id=${archive_content_id}`,
|
||||
data_kv
|
||||
);
|
||||
}
|
||||
|
||||
// Perform the API update
|
||||
const result = await api.update_ae_obj_id_crud({
|
||||
api_cfg: api_cfg,
|
||||
obj_type: 'archive_content',
|
||||
obj_id: archive_content_id,
|
||||
fields: data_kv,
|
||||
key: api_cfg.api_crud_super_key,
|
||||
params: params,
|
||||
return_obj: true,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
|
||||
// Handle the result
|
||||
if (result) {
|
||||
if (try_cache) {
|
||||
// Process the results first
|
||||
const processed_obj_li = await process_ae_obj__archive_content_props({
|
||||
obj_li: [result],
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
if (log_lvl) {
|
||||
console.log('Processed object list:', processed_obj_li);
|
||||
}
|
||||
// Save the updated results list to the database
|
||||
if (log_lvl) {
|
||||
console.log('Saving to DB...');
|
||||
}
|
||||
await db_save_ae_obj_li__ae_obj({
|
||||
db_instance: db_archives,
|
||||
table_name: 'content',
|
||||
obj_li: processed_obj_li,
|
||||
properties_to_save: properties_to_save,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
if (log_lvl) {
|
||||
console.log('DB save completed.');
|
||||
}
|
||||
|
||||
// await db_save_ae_obj_li__archive_content({
|
||||
// obj_type: 'archive_content',
|
||||
// obj_li: [result],
|
||||
// log_lvl: log_lvl,
|
||||
// });
|
||||
}
|
||||
return result;
|
||||
} else {
|
||||
console.error('Failed to update archive content.');
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Updated 2025-06-04
|
||||
export const properties_to_save = [
|
||||
'id',
|
||||
'archive_content_id',
|
||||
// 'archive_content_id_random',
|
||||
|
||||
'archive_id',
|
||||
// 'archive_id_random',
|
||||
|
||||
'archive_content_type',
|
||||
|
||||
'name',
|
||||
'description',
|
||||
|
||||
'content_html',
|
||||
'content_json',
|
||||
|
||||
'url',
|
||||
'url_text',
|
||||
|
||||
'hosted_file_id',
|
||||
'hosted_file_id_random',
|
||||
|
||||
'file_path',
|
||||
|
||||
'filename',
|
||||
'file_extension',
|
||||
|
||||
'original_datetime',
|
||||
'original_timezone',
|
||||
'original_location',
|
||||
'original_url',
|
||||
'original_url_text',
|
||||
|
||||
'enable_for_public',
|
||||
|
||||
'cfg_json',
|
||||
|
||||
'enable',
|
||||
'hide',
|
||||
'priority',
|
||||
'sort',
|
||||
'group',
|
||||
'notes',
|
||||
'created_on',
|
||||
'updated_on',
|
||||
|
||||
// Generated fields for sorting locally only
|
||||
'tmp_sort_1',
|
||||
'tmp_sort_2',
|
||||
// 'tmp_sort_a',
|
||||
// 'tmp_sort_b',
|
||||
|
||||
// From SQL view
|
||||
'archive_code',
|
||||
'archive_name',
|
||||
|
||||
'hash_sha256'
|
||||
];
|
||||
|
||||
/**
|
||||
* NON-EXPORTED LOCAL HELPER
|
||||
* Processes a list of Aether objects by applying common and specific transformations.
|
||||
*/
|
||||
async function _process_generic_props<T extends Record<string, any>>({
|
||||
obj_li,
|
||||
obj_type,
|
||||
log_lvl = 0,
|
||||
specific_processor
|
||||
}: {
|
||||
obj_li: T[];
|
||||
obj_type: string;
|
||||
log_lvl?: number;
|
||||
specific_processor?: (obj: T) => Promise<T> | T;
|
||||
}): Promise<T[]> {
|
||||
if (log_lvl > 0) {
|
||||
console.log(
|
||||
`*** _process_generic_props: Processing ${obj_li.length} objects of type "${obj_type}" ***`
|
||||
);
|
||||
}
|
||||
|
||||
if (!obj_li || obj_li.length === 0) {
|
||||
if (log_lvl > 0) console.log('No objects to process.');
|
||||
return [];
|
||||
}
|
||||
|
||||
const processed_obj_li: T[] = [];
|
||||
|
||||
for (const original_obj of obj_li) {
|
||||
let processed_obj = { ...original_obj };
|
||||
|
||||
// --- Common Transformations ---
|
||||
|
||||
// 1. Standardize ID and other '_random' fields
|
||||
// The API often returns fields like 'person_id_random', which need to be aliased to 'person_id'.
|
||||
for (const key in processed_obj) {
|
||||
if (key.endsWith('_random')) {
|
||||
const newKey = key.slice(0, -7); // Remove '_random' suffix
|
||||
processed_obj[newKey] = processed_obj[key];
|
||||
}
|
||||
}
|
||||
// Ensure 'id' is set from '[obj_type]_id_random'
|
||||
const randomIdKey = `${obj_type}_id_random`;
|
||||
if (processed_obj[randomIdKey]) {
|
||||
(processed_obj as any).id = processed_obj[randomIdKey];
|
||||
}
|
||||
|
||||
// 2. Create common computed properties for client-side sorting.
|
||||
const group = processed_obj.group ?? '0';
|
||||
const priority = processed_obj.priority ? 1 : 0;
|
||||
const sort = processed_obj.sort ?? '0';
|
||||
const updated = processed_obj.updated_on ?? processed_obj.created_on;
|
||||
const name = processed_obj.name ?? '';
|
||||
|
||||
(processed_obj as any).tmp_sort_1 = `${group}_${priority}_${sort}_${updated}`;
|
||||
(processed_obj as any).tmp_sort_2 = `${group}_${priority}_${sort}_${name}_${updated}`;
|
||||
|
||||
// --- Specific Transformations ---
|
||||
if (specific_processor) {
|
||||
processed_obj = await Promise.resolve(specific_processor(processed_obj));
|
||||
}
|
||||
|
||||
processed_obj_li.push(processed_obj as T);
|
||||
}
|
||||
|
||||
return processed_obj_li;
|
||||
}
|
||||
|
||||
// Updated 2025-06-04
|
||||
export async function process_ae_obj__archive_content_props({
|
||||
obj_li,
|
||||
log_lvl = 0
|
||||
}: {
|
||||
obj_li: any[];
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
return _process_generic_props({
|
||||
obj_li,
|
||||
obj_type: 'archive_content',
|
||||
log_lvl,
|
||||
specific_processor: (obj) => {
|
||||
// Archive content-specific computed sort fields, overriding generic ones if needed
|
||||
obj.tmp_sort_1 = `${obj.group ?? ''}_${obj.priority ? '1' : '0'}_${
|
||||
obj.sort?.toString().padStart(3, '0') ?? ''
|
||||
}_${obj.original_datetime ?? ''}`;
|
||||
obj.tmp_sort_2 = `${obj.group ?? ''}_${obj.original_datetime ?? ''}_${
|
||||
obj.priority ? '1' : '0'
|
||||
}_${obj.sort?.toString().padStart(3, '0') ?? ''}`;
|
||||
obj.tmp_sort_3 = `${obj.original_datetime ?? ''}_${obj.group ?? ''}_${
|
||||
obj.priority ? '1' : '0'
|
||||
}_${obj.sort?.toString().padStart(3, '0') ?? ''}`;
|
||||
|
||||
obj.hash_sha256 = obj.hosted_file_hash_sha256;
|
||||
|
||||
return obj;
|
||||
}
|
||||
});
|
||||
}
|
||||
32
src/lib/ae_archives/ae_archives_functions.ts
Normal file
32
src/lib/ae_archives/ae_archives_functions.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
// This file is used to export all the functions that are used for Aether Posts related functions.
|
||||
|
||||
import {
|
||||
load_ae_obj_id__archive,
|
||||
load_ae_obj_li__archive,
|
||||
create_ae_obj__archive,
|
||||
delete_ae_obj_id__archive,
|
||||
update_ae_obj__archive
|
||||
} from '$lib/ae_archives/ae_archives__archive';
|
||||
|
||||
import {
|
||||
load_ae_obj_id__archive_content,
|
||||
load_ae_obj_li__archive_content,
|
||||
create_ae_obj__archive_content,
|
||||
delete_ae_obj_id__archive_content,
|
||||
update_ae_obj__archive_content
|
||||
} from '$lib/ae_archives/ae_archives__archive_content';
|
||||
|
||||
const export_obj = {
|
||||
load_ae_obj_id__archive: load_ae_obj_id__archive,
|
||||
load_ae_obj_li__archive: load_ae_obj_li__archive,
|
||||
create_ae_obj__archive: create_ae_obj__archive,
|
||||
delete_ae_obj_id__archive: delete_ae_obj_id__archive,
|
||||
update_ae_obj__archive: update_ae_obj__archive,
|
||||
|
||||
load_ae_obj_id__archive_content: load_ae_obj_id__archive_content,
|
||||
load_ae_obj_li__archive_content: load_ae_obj_li__archive_content,
|
||||
create_ae_obj__archive_content: create_ae_obj__archive_content,
|
||||
delete_ae_obj_id__archive_content: delete_ae_obj_id__archive_content,
|
||||
update_ae_obj__archive_content: update_ae_obj__archive_content
|
||||
};
|
||||
export const archives_func = export_obj;
|
||||
165
src/lib/ae_archives/db_archives.ts
Normal file
165
src/lib/ae_archives/db_archives.ts
Normal file
@@ -0,0 +1,165 @@
|
||||
import Dexie, { type Table } from 'dexie';
|
||||
|
||||
import type { key_val } from '$lib/stores/ae_stores';
|
||||
|
||||
// li = list
|
||||
// kv = key value list
|
||||
|
||||
// Updated 2024-09-25
|
||||
export interface Archive {
|
||||
id: string;
|
||||
// id_random: string;
|
||||
archive_id: string;
|
||||
// archive_id_random: string;
|
||||
|
||||
code?: null | string;
|
||||
|
||||
account_id: string;
|
||||
// account_id_random: string;
|
||||
|
||||
// archive_type: string;
|
||||
|
||||
// type: string;
|
||||
name: string;
|
||||
// summary?: null|string;
|
||||
description?: null | string;
|
||||
|
||||
content_html?: null | string;
|
||||
content_json?: null | string;
|
||||
content_url?: null | string;
|
||||
content_url_text?: null | string;
|
||||
|
||||
original_datetime?: Date;
|
||||
original_timezone?: null | string;
|
||||
original_location?: null | string;
|
||||
|
||||
original_url?: null | string;
|
||||
original_url_text?: null | string;
|
||||
|
||||
// meta_data?: null|string;
|
||||
// access_key?: null|string; /// Rename this to "passcode" if used later
|
||||
|
||||
sort_by?: null | string;
|
||||
sort_by_desc?: null | string;
|
||||
|
||||
cfg_json?: null | key_val;
|
||||
|
||||
enable: null | boolean;
|
||||
hide?: null | boolean;
|
||||
priority?: null | boolean;
|
||||
sort?: null | number;
|
||||
group?: null | string;
|
||||
notes?: null | string;
|
||||
created_on: Date;
|
||||
updated_on?: null | Date;
|
||||
|
||||
// Generated fields for sorting locally only
|
||||
tmp_sort_1?: null | string;
|
||||
tmp_sort_2?: null | string;
|
||||
|
||||
// Additional fields for convenience (database views)
|
||||
// archive_content_count?: number;
|
||||
// archive_content_kv?: null|key_val;
|
||||
// archive_content_li?: null|[];
|
||||
}
|
||||
|
||||
// Updated 2024-09-25
|
||||
export interface Archive_Content {
|
||||
id: string;
|
||||
// id_random: string;
|
||||
archive_content_id: string;
|
||||
// archive_content_id_random: string;
|
||||
|
||||
archive_id: string;
|
||||
// archive_id_random: string;
|
||||
|
||||
archive_content_type: string;
|
||||
|
||||
name: string;
|
||||
description?: null | string;
|
||||
|
||||
content_html?: null | string;
|
||||
content_json?: null | string;
|
||||
|
||||
// linked_li_json?: null|string; // For future use? linked content list instead of one content item
|
||||
|
||||
url?: null | string;
|
||||
url_text?: null | string;
|
||||
|
||||
hosted_file_id?: string;
|
||||
|
||||
file_path?: null | string;
|
||||
|
||||
filename?: null | string;
|
||||
file_extension?: null | string;
|
||||
|
||||
original_datetime?: Date;
|
||||
original_timezone?: null | string;
|
||||
original_location?: null | string;
|
||||
original_url?: null | string;
|
||||
original_url_text?: null | string;
|
||||
|
||||
// meta_data?: null|string;
|
||||
// access_key?: null|string; /// Rename this to "passcode" if used later
|
||||
|
||||
enable_for_public?: boolean;
|
||||
|
||||
cfg_json?: null | key_val;
|
||||
|
||||
enable: null | boolean;
|
||||
hide?: null | boolean;
|
||||
priority?: null | boolean;
|
||||
sort?: null | number;
|
||||
group?: null | string;
|
||||
notes?: null | string;
|
||||
created_on: Date;
|
||||
updated_on?: null | Date;
|
||||
|
||||
// Generated fields for sorting locally only
|
||||
tmp_sort_1?: null | string;
|
||||
tmp_sort_2?: null | string;
|
||||
|
||||
// Additional fields for convenience (database views)
|
||||
archive_code?: null | string;
|
||||
archive_name?: null | string;
|
||||
|
||||
hash_sha256?: null | string;
|
||||
}
|
||||
|
||||
// Updated 2024-09-25
|
||||
export class MySubClassedDexie extends Dexie {
|
||||
// We just tell the typing system this is the case
|
||||
archive!: Table<Archive>;
|
||||
content!: Table<Archive_Content>;
|
||||
|
||||
constructor() {
|
||||
super('ae_archives_db');
|
||||
this.version(1).stores({
|
||||
archive: `
|
||||
id, archive_id,
|
||||
code,
|
||||
account_id,
|
||||
name,
|
||||
original_datetime, original_timezone, original_location,
|
||||
tmp_sort_1, tmp_sort_2,
|
||||
enable, hide, priority, sort, group, notes, created_on, updated_on`,
|
||||
content: `
|
||||
id, archive_content_id,
|
||||
archive_id,
|
||||
archive_content_type,
|
||||
name,
|
||||
hosted_file_id,
|
||||
original_datetime, original_timezone, original_location,
|
||||
[group+original_datetime],
|
||||
tmp_sort_1, tmp_sort_2,
|
||||
enable, hide, priority, sort, group, notes, created_on, updated_on, [group+priority+sort+updated_on]`
|
||||
});
|
||||
|
||||
// file_path,
|
||||
// filename, file_extension,
|
||||
// original_datetime, original_timezone, original_location, original_url, original_url_text,
|
||||
// enable_for_public,
|
||||
}
|
||||
}
|
||||
|
||||
export const db_archives = new MySubClassedDexie();
|
||||
424
src/lib/ae_core/ae_comp__hosted_files_clip_video.svelte
Normal file
424
src/lib/ae_core/ae_comp__hosted_files_clip_video.svelte
Normal file
@@ -0,0 +1,424 @@
|
||||
<script lang="ts">
|
||||
import { preventDefault } from 'svelte/legacy';
|
||||
|
||||
// Imports
|
||||
// Import components and elements
|
||||
// import Element_input_files_tbl from '$lib/element_input_files_tbl.svelte';
|
||||
|
||||
// Import storage, functions, and libraries
|
||||
import type { key_val } from '$lib/stores/ae_stores';
|
||||
|
||||
import { api } from '$lib/api/api';
|
||||
import { ae_util } from '$lib/ae_utils/ae_utils';
|
||||
import {
|
||||
ae_snip,
|
||||
ae_loc,
|
||||
ae_sess,
|
||||
ae_api,
|
||||
ae_trig,
|
||||
slct,
|
||||
slct_trigger
|
||||
} from '$lib/stores/ae_stores';
|
||||
|
||||
// Exports
|
||||
|
||||
// export let input_name = 'file_list';
|
||||
// export let multiple: boolean = true;
|
||||
// export let required: boolean = true;
|
||||
|
||||
// export let input_class_li: string[] = ['file_drop_area'];
|
||||
|
||||
interface Props {
|
||||
log_lvl?: number;
|
||||
// Expecting these for link_to_type: 'event', 'event_location', 'archive_content', etc
|
||||
link_to_type: string;
|
||||
link_to_id: string;
|
||||
// export let accept: string = 'audio/*, image/*, video/*, .bak, .cfg, .css, .csv, .doc, .docx, .gz, .htm, .html, .ini, .iso, .j2, .json, .key, .keynote, .md, .pdf, .ppt, .pptx, .rar, .rtf, .sql, .svelte, ttf, .txt, .xls, .xlsx, .xz, .zip, .bin, .dmg, .exe, .js, .msi, .php, .py, .sh';
|
||||
class_li_default?: string;
|
||||
class_li?: string;
|
||||
// export let table_class_li: string[] = ['table', 'table-sm', 'table-striped', 'table-hover' , 'text-sm'];
|
||||
clip_complete?: boolean;
|
||||
// export let upload_complete: boolean = false;
|
||||
submit_status?: null | string;
|
||||
// hosted_file_id_li?: string[];
|
||||
// hosted_file_obj_li?: any[];
|
||||
hosted_file_obj_kv?: key_val;
|
||||
video_clip_file_kv?: key_val;
|
||||
}
|
||||
|
||||
let {
|
||||
log_lvl = $bindable(0),
|
||||
link_to_type = $bindable(),
|
||||
link_to_id = $bindable(),
|
||||
class_li_default = 'flex flex-col gap-1 items-center justify-center w-full max-w-2xl mx-auto my-1',
|
||||
class_li = $bindable(''),
|
||||
clip_complete = $bindable(false),
|
||||
submit_status = $bindable(null),
|
||||
// hosted_file_id_li = [],
|
||||
// hosted_file_obj_li = [],
|
||||
hosted_file_obj_kv = $bindable({}),
|
||||
video_clip_file_kv = $bindable({})
|
||||
}: Props = $props();
|
||||
|
||||
// Local Variables
|
||||
let task_id = link_to_id;
|
||||
// let input_file_list: any = null;
|
||||
let ae_promises: key_val = $state({});
|
||||
// let ae_promises_clipping: key_val = {};
|
||||
// let ae_triggers: key_val = {};
|
||||
|
||||
// let input_element_id = 'ae_comp__hosted_files_upload__input';
|
||||
|
||||
// let form_kv: key_val = {
|
||||
// start_time: null,
|
||||
// end_time: null,
|
||||
// reencode: null,
|
||||
// video_file: null,
|
||||
// };
|
||||
// let download_clip_src: string;
|
||||
// let download_clip_filename: string;
|
||||
|
||||
$ae_sess.files.obj = {
|
||||
obj: null
|
||||
};
|
||||
|
||||
// *** Functions and Logic
|
||||
function handle_clip_video(event: Event) {
|
||||
console.log('*** handle_clip_video() ***');
|
||||
|
||||
submit_status = 'clipping';
|
||||
clip_complete = false;
|
||||
|
||||
let hosted_file_id = event.target.hosted_file_id.value;
|
||||
|
||||
$ae_sess.files.processed_file_kv[hosted_file_id] = {};
|
||||
$ae_sess.files.processed_file_kv[hosted_file_id].submit_status = 'clipping';
|
||||
$ae_sess.files.processed_file_kv[hosted_file_id].clip_complete = false;
|
||||
|
||||
// $ae_sess.files.disable_submit__hosted_file_obj = true;
|
||||
$ae_loc.files.processed_file_kv[hosted_file_id] = {};
|
||||
$ae_loc.files.processed_file_kv[hosted_file_id].submit_status = 'clipping';
|
||||
$ae_loc.files.processed_file_kv[hosted_file_id].start_time = event.target.start_time.value;
|
||||
$ae_loc.files.processed_file_kv[hosted_file_id].end_time = event.target.end_time.value;
|
||||
$ae_loc.files.processed_file_kv[hosted_file_id].reencode = event.target.reencode.value;
|
||||
$ae_loc.files.processed_file_kv[hosted_file_id].scale_down = event.target.scale_down.value;
|
||||
$ae_loc.files.processed_file_kv[hosted_file_id].new_filename =
|
||||
event.target.new_filename.value;
|
||||
$ae_loc.files.processed_file_kv[hosted_file_id].clip_complete = false;
|
||||
|
||||
let endpoint = `/hosted_file/${hosted_file_id}/clip_video`;
|
||||
|
||||
let params = {
|
||||
link_to_type: link_to_type,
|
||||
link_to_id: link_to_id,
|
||||
filename_no_ext: event.target.new_filename.value.replace('.mp4', ''),
|
||||
from_type: 'mp4', // Video file type being converted
|
||||
to_type: 'mp4', // Video file type to convert to
|
||||
start_time: event.target.start_time.value,
|
||||
end_time: event.target.end_time.value,
|
||||
reencode: event.target.reencode.value,
|
||||
scale_down: event.target.scale_down.value
|
||||
};
|
||||
|
||||
ae_promises[hosted_file_id] = {};
|
||||
// .convert__hosted_file_obj
|
||||
ae_promises[hosted_file_id] = api
|
||||
.get_object({
|
||||
api_cfg: $ae_api,
|
||||
endpoint: endpoint,
|
||||
params: params,
|
||||
timeout: 300000, // 5 minutes
|
||||
// return_blob: true,
|
||||
// filename: event.target.new_filename.value,
|
||||
// auto_download: false,
|
||||
task_id: task_id,
|
||||
log_lvl: log_lvl
|
||||
})
|
||||
.then(function (result) {
|
||||
console.log(result);
|
||||
|
||||
video_clip_file_kv[result.hosted_file_id_random] = {};
|
||||
video_clip_file_kv[result.hosted_file_id_random] = result;
|
||||
|
||||
// $ae_loc.files.video_clip_file_kv[result.hosted_file_id_random] = {};
|
||||
// $ae_loc.files.video_clip_file_kv[result.hosted_file_id_random] = result;
|
||||
|
||||
$ae_sess.files.processed_file_kv[hosted_file_id].submit_status = 'clipped';
|
||||
$ae_sess.files.processed_file_kv[hosted_file_id].clip_complete = true;
|
||||
|
||||
$ae_loc.files.processed_file_kv[hosted_file_id].submit_status = 'clipped';
|
||||
$ae_loc.files.processed_file_kv[hosted_file_id].clip_complete = true;
|
||||
|
||||
submit_status = 'clipped';
|
||||
clip_complete = true;
|
||||
|
||||
// let file_blob = new Blob([result.data]);
|
||||
// // console.log(file_blob);
|
||||
// let file_obj_url = window.URL.createObjectURL(file_blob); // The img src
|
||||
// // const url = window.URL.createObjectURL(new Blob([result.data]));
|
||||
// download_clip_src = file_obj_url;
|
||||
// // download_filename = file_obj_url;
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<section class="{class_li_default} {class_li}">
|
||||
<h3 class="h3">
|
||||
{Object.entries(hosted_file_obj_kv).length}× files uploaded
|
||||
</h3>
|
||||
|
||||
{#each Object.entries(hosted_file_obj_kv) as [hosted_file_id, hosted_file_obj]}
|
||||
<div class="border border-gray-300 rounded-lg p-2 m-2">
|
||||
<!-- {#if $ae_sess.files[hosted_file_id].upload_complete}
|
||||
<a href="/hosted_file/{hosted_file_id}/download?x_no_account_id_token=direct-download" download={$ae_sess.files[hosted_file_id].new_filename} class="ae_btn btn_lg btn_primary"><span class="fas fa-download"></span> Ready to Download</a>
|
||||
{/if} -->
|
||||
|
||||
<div class="flex flex-row flex-wrap gap-1 justify-center items-center w-full">
|
||||
<!-- Remove from uploaded file kv list -->
|
||||
<button
|
||||
type="button"
|
||||
onclick={() => {
|
||||
// This (uploaded_file_kv) is referenced by other AE components. Currently it is only used with the manage hosted file list and clip video components.
|
||||
console.log(
|
||||
`Removed hosted file ID: ${hosted_file_id}`,
|
||||
$ae_loc.files.uploaded_file_kv
|
||||
);
|
||||
// delete $ae_sess.files.uploaded_file_kv[hosted_file_id];
|
||||
delete $ae_loc.files.uploaded_file_kv[hosted_file_id];
|
||||
$ae_loc.files.uploaded_file_kv = { ...$ae_loc.files.uploaded_file_kv };
|
||||
delete hosted_file_obj_kv[hosted_file_id];
|
||||
hosted_file_obj_kv = { ...hosted_file_obj_kv };
|
||||
// delete $ae_loc.files.uploaded_file_kv[hosted_file_obj.hosted_file_id];
|
||||
console.log(
|
||||
`Removed hosted file ID: ${hosted_file_obj.hosted_file_id}`,
|
||||
$ae_loc.files.uploaded_file_kv
|
||||
);
|
||||
}}
|
||||
class="btn btn-sm preset-tonal-warning hover:preset-filled-warning-500"
|
||||
title={`Remove this file from list of videos:\n${hosted_file_obj.filename}\n[API] SHA256: ${hosted_file_obj?.hash_sha256?.slice(0, 10)}... Hosted ID: ${hosted_file_obj.hosted_file_id_random}`}
|
||||
>
|
||||
<span class="fas fa-minus-circle m-1"></span>
|
||||
<span class="">Remove</span>
|
||||
</button>
|
||||
|
||||
<!-- Download the file -->
|
||||
<button
|
||||
type="button"
|
||||
disabled={!$ae_loc.trusted_access}
|
||||
onclick={() => {
|
||||
ae_promises[hosted_file_id] = api.download_hosted_file({
|
||||
api_cfg: $ae_api,
|
||||
hosted_file_id: hosted_file_id,
|
||||
return_file: true,
|
||||
filename: hosted_file_obj.filename,
|
||||
auto_download: true,
|
||||
log_lvl: 0
|
||||
});
|
||||
|
||||
// window.postMessage({ type: 'download_event_file', hosted_file_id: idaa_archive_content_obj.hosted_file_id, filename: idaa_archive_content_obj.filename, auto_download: true }, '*');
|
||||
}}
|
||||
class:hidden={!$ae_loc.edit_mode}
|
||||
class="novi_btn btn btn-sm lg:btn-md preset-tonal-primary hover:preset-filled-primary-500 min-w-72 lg:min-w-96"
|
||||
title={`Download this file:\n${hosted_file_obj.filename}\n[API] SHA256: ${hosted_file_obj?.hash_sha256?.slice(0, 10)}... Hosted ID: ${hosted_file_obj.hosted_file_id_random}`}
|
||||
>
|
||||
{#await ae_promises[hosted_file_id]}
|
||||
<span class="fas fa-spinner fa-spin mx-1"></span>
|
||||
{#if submit_status == 'clipping'}
|
||||
<span class="">Clipping</span>
|
||||
{:else}
|
||||
<span class="">
|
||||
Downloading
|
||||
{#if $ae_sess.api_download_kv[hosted_file_id]}
|
||||
{$ae_sess.api_download_kv[hosted_file_id].percent_completed}%
|
||||
{/if}
|
||||
:
|
||||
</span>
|
||||
{/if}
|
||||
{:then}
|
||||
<span
|
||||
class="fas fa-{ae_util.file_extension_icon(
|
||||
hosted_file_obj?.file_extension
|
||||
)}"
|
||||
></span>
|
||||
{/await}
|
||||
|
||||
<span class="grow">
|
||||
{ae_util.shorten_filename({
|
||||
filename: hosted_file_obj?.filename,
|
||||
max_length: 30
|
||||
})}
|
||||
</span>
|
||||
</button>
|
||||
<span
|
||||
>{ae_util.shorten_filename({
|
||||
filename: hosted_file_obj?.filename,
|
||||
max_length: 30
|
||||
})}</span
|
||||
>
|
||||
<span>
|
||||
<span class="text-sm font-bold"> File ID: </span>
|
||||
{hosted_file_obj.hosted_file_id_random}</span
|
||||
>
|
||||
<span>
|
||||
<span class="text-sm font-bold"> Type: </span>
|
||||
{hosted_file_obj.extension}</span
|
||||
>
|
||||
<!-- <span>{hosted_file_obj.filename}</span> -->
|
||||
</div>
|
||||
|
||||
<form
|
||||
onsubmit={preventDefault(handle_clip_video)}
|
||||
class="{class_li_default} {class_li}"
|
||||
>
|
||||
<!-- {$ae_sess?.files[hosted_file_obj?.hosted_file_id_random ?? 'obj'].submit_status ?? 'not set'} -->
|
||||
|
||||
<input
|
||||
type="hidden"
|
||||
name="hosted_file_id"
|
||||
value={hosted_file_obj.hosted_file_id_random}
|
||||
/>
|
||||
|
||||
<div class="flex flex-row gap-1 justify-center items-center w-full">
|
||||
<span class="text-xs font-bold w-32">New Filename:</span>
|
||||
<input
|
||||
type="text"
|
||||
class="input w-full text-sm"
|
||||
name="new_filename"
|
||||
value={hosted_file_obj.filename}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="max-w-(--breakpoint-sm) flex flex-row gap-1 justify-center items-center w-full"
|
||||
>
|
||||
<label
|
||||
class="label w-48"
|
||||
title="The start time of the clip. This is the time in the video where the clip will start. You may need to subtract a few seconds to get the exact start time."
|
||||
>
|
||||
<span class="text-xs font-bold">Start time (HH:MM:SS)</span>
|
||||
<input
|
||||
type="text"
|
||||
name="start_time"
|
||||
value={$ae_loc.files.processed_file_kv &&
|
||||
$ae_loc.files.processed_file_kv[hosted_file_id] &&
|
||||
$ae_loc.files.processed_file_kv[hosted_file_id].start_time
|
||||
? $ae_loc.files.processed_file_kv[hosted_file_id].start_time
|
||||
: '00:00:00'}
|
||||
placeholder="HH:MM:SS (00:01:30)"
|
||||
class="input w-32"
|
||||
/>
|
||||
</label>
|
||||
|
||||
<label
|
||||
class="label w-48"
|
||||
title="The end time of the clip. This is the time in the video where the clip will end. You may need to add a few seconds to get the exact end time."
|
||||
>
|
||||
<span class="text-xs font-bold">End time (HH:MM:SS)</span>
|
||||
<input
|
||||
type="text"
|
||||
name="end_time"
|
||||
value={$ae_loc.files.processed_file_kv &&
|
||||
$ae_loc.files.processed_file_kv[hosted_file_id] &&
|
||||
$ae_loc.files.processed_file_kv[hosted_file_id].end_time
|
||||
? $ae_loc.files.processed_file_kv[hosted_file_id].end_time
|
||||
: '00:45:59'}
|
||||
placeholder="HH:MM:SS (01:05:25)"
|
||||
class="input w-32"
|
||||
/>
|
||||
</label>
|
||||
|
||||
<span
|
||||
class="flex flex-col gap-1 items-center justify-center"
|
||||
title="Re-encode the video file? This does cause some minor quality loss. Re-encoding is useful if the audio or video seems to be chopped off at the beginning or end of the clip. It can also help with partially corrupted files."
|
||||
>
|
||||
<span class="text-xs font-bold"> Re-encode? </span>
|
||||
<label class="inline-block">
|
||||
<input
|
||||
type="radio"
|
||||
name="reencode"
|
||||
value="true"
|
||||
class="radio"
|
||||
checked
|
||||
/>
|
||||
True
|
||||
</label>
|
||||
<label class="inline-block">
|
||||
<input type="radio" name="reencode" value="false" class="radio" />
|
||||
False
|
||||
</label>
|
||||
</span>
|
||||
|
||||
<span
|
||||
class="flex flex-col gap-1 items-center justify-center"
|
||||
title="Scale the video file down to 1920x1080? This does cause some minor quality loss. Re-encoding is useful if the audio or video seems to be chopped off at the beginning or end of the clip. It can also help with partially corrupted files."
|
||||
>
|
||||
<span class="text-xs font-bold"> Scale down? </span>
|
||||
<label class="inline-block">
|
||||
<input
|
||||
type="radio"
|
||||
name="scale_down"
|
||||
value="true"
|
||||
class="radio"
|
||||
checked
|
||||
/>
|
||||
True
|
||||
</label>
|
||||
<label class="inline-block">
|
||||
<input type="radio" name="scale_down" value="false" class="radio" />
|
||||
False
|
||||
</label>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-lg btn-primary preset-tonal-primary border border-primary-500"
|
||||
disabled={submit_status == 'clipping'}
|
||||
>
|
||||
<!-- {#await ae_promises[hosted_file_id]} -->
|
||||
{#if $ae_loc.files.processed_file_kv[hosted_file_id] && $ae_loc.files.processed_file_kv[hosted_file_id].submit_status == 'clipping'}
|
||||
<span class="fas fa-spinner fa-spin m-1"></span>
|
||||
<span class="highlight">Clipping...</span>
|
||||
{:else}
|
||||
<!-- {#if ae_promises[hosted_file_id]} -->
|
||||
{#if $ae_loc.files.processed_file_kv[hosted_file_id] && $ae_loc.files.processed_file_kv[hosted_file_id].submit_status == 'clipped'}
|
||||
<span class="fas fa-check m-1"></span>
|
||||
Clipped
|
||||
{:else}
|
||||
<span class="fas fa-cut m-1"></span>
|
||||
Clip Video
|
||||
{/if}
|
||||
{/if}
|
||||
<!-- <span class="fas fa-cut m-1"></span>
|
||||
Clip Video -->
|
||||
</button>
|
||||
</form>
|
||||
|
||||
{#await ae_promises[hosted_file_id]}
|
||||
<span class="fas fa-spinner fa-spin m-1"></span>
|
||||
<span class="highlight">Processing... This may take a few minutes.</span>
|
||||
{:then}
|
||||
{#if ae_promises[hosted_file_id]}
|
||||
<span class="fas fa-download"></span> Ready to download below!
|
||||
{:else}
|
||||
<!-- <p>Fill out the form and select the video file to clip.</p> -->
|
||||
{/if}
|
||||
{/await}
|
||||
</div>
|
||||
{/each}
|
||||
|
||||
<!-- <hr />
|
||||
|
||||
{#await ae_promises.upload__hosted_file_obj}
|
||||
<span class="fas fa-spinner fa-spin m-1"></span>
|
||||
<p class="highlight">Converting... This may take a few minutes.</p>
|
||||
{:then}
|
||||
{#if ae_promises.upload__hosted_file_obj}
|
||||
<a href={download_clip_src} download={download_clip_filename} class="ae_btn btn_lg btn_primary"><span class="fas fa-download"></span> Ready to Download</a>
|
||||
{:else}
|
||||
<p>Fill out the form and select the video file to clip.</p>
|
||||
{/if}
|
||||
{/await} -->
|
||||
</section>
|
||||
91
src/lib/ae_core/ae_comp__hosted_files_clip_video_li.svelte
Normal file
91
src/lib/ae_core/ae_comp__hosted_files_clip_video_li.svelte
Normal file
@@ -0,0 +1,91 @@
|
||||
<script lang="ts">
|
||||
// Imports
|
||||
// Import components and elements
|
||||
|
||||
// Import storage, functions, and libraries
|
||||
import type { key_val } from '$lib/stores/ae_stores';
|
||||
|
||||
import { api } from '$lib/api/api';
|
||||
import { ae_util } from '$lib/ae_utils/ae_utils';
|
||||
import {
|
||||
ae_snip,
|
||||
ae_loc,
|
||||
ae_sess,
|
||||
ae_api,
|
||||
ae_trig,
|
||||
slct,
|
||||
slct_trigger
|
||||
} from '$lib/stores/ae_stores';
|
||||
|
||||
// Exports
|
||||
|
||||
// export let hosted_file_id_li: string[] = [];
|
||||
// export let hosted_file_obj_li: any[] = [];
|
||||
|
||||
interface Props {
|
||||
log_lvl?: number;
|
||||
// export let hosted_file_obj_kv: key_val = {};
|
||||
video_clip_file_kv?: key_val;
|
||||
class_li_default?: string;
|
||||
class_li?: string;
|
||||
link_to_type: string;
|
||||
link_to_id: string;
|
||||
}
|
||||
|
||||
let {
|
||||
log_lvl = 0,
|
||||
video_clip_file_kv = $bindable({}),
|
||||
class_li_default = 'flex flex-row flex-wrap gap-2 items-center justify-center w-full max-w-2xl p-2 mx-auto my-1 border border-gray-300 rounded-lg',
|
||||
class_li = '',
|
||||
link_to_type,
|
||||
link_to_id
|
||||
}: Props = $props();
|
||||
|
||||
let ae_promises: key_val = $state({});
|
||||
</script>
|
||||
|
||||
<h3 class="h3">{Object.entries($ae_loc.files).length}× files clipped</h3>
|
||||
<div class="{class_li_default} {class_li} ">
|
||||
{#each Object.entries(video_clip_file_kv) as [hosted_file_id, hosted_file_obj]}
|
||||
<button
|
||||
type="button"
|
||||
disabled={!$ae_loc.trusted_access}
|
||||
onclick={() => {
|
||||
ae_promises[hosted_file_id] = api.download_hosted_file({
|
||||
api_cfg: $ae_api,
|
||||
hosted_file_id: hosted_file_id,
|
||||
return_file: true,
|
||||
filename: hosted_file_obj.filename,
|
||||
auto_download: true,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
|
||||
// window.postMessage({ type: 'download_event_file', hosted_file_id: idaa_archive_content_obj.hosted_file_id, filename: idaa_archive_content_obj.filename, auto_download: true }, '*');
|
||||
}}
|
||||
class="novi_btn btn btn-sm lg:btn-md preset-tonal-primary hover:preset-filled-primary-500 min-w-72 lg:min-w-96"
|
||||
title={`Download this file:\n${hosted_file_obj.filename}\n[API] SHA256: ${hosted_file_obj?.hash_sha256?.slice(0, 10)}... Hosted ID: ${hosted_file_obj.hosted_file_id_random}`}
|
||||
>
|
||||
{#await ae_promises[hosted_file_id]}
|
||||
<span class="fas fa-spinner fa-spin mx-1"></span>
|
||||
<span class="">
|
||||
Downloading
|
||||
{#if $ae_sess.api_download_kv[hosted_file_id]}
|
||||
{$ae_sess.api_download_kv[hosted_file_id].percent_completed}%
|
||||
{/if}
|
||||
:
|
||||
</span>
|
||||
{:then}
|
||||
<span class="fas fa-{ae_util.file_extension_icon(hosted_file_obj?.file_extension)}"
|
||||
></span>
|
||||
{/await}
|
||||
|
||||
<span class="grow">
|
||||
{ae_util.shorten_filename({ filename: hosted_file_obj?.filename, max_length: 30 })}
|
||||
</span>
|
||||
|
||||
<span class="shrink">
|
||||
{ae_util.format_bytes(hosted_file_obj?.size)}
|
||||
</span>
|
||||
</button>
|
||||
{/each}
|
||||
</div>
|
||||
423
src/lib/ae_core/ae_comp__hosted_files_clip_video_v1.svelte
Normal file
423
src/lib/ae_core/ae_comp__hosted_files_clip_video_v1.svelte
Normal file
@@ -0,0 +1,423 @@
|
||||
<script lang="ts">
|
||||
import { preventDefault } from 'svelte/legacy';
|
||||
|
||||
// Imports
|
||||
// Import components and elements
|
||||
import Element_input_files_tbl from '$lib/elements/element_input_files_tbl.svelte';
|
||||
|
||||
// Import storage, functions, and libraries
|
||||
import type { key_val } from '$lib/stores/ae_stores';
|
||||
|
||||
import { api } from '$lib/api/api';
|
||||
import {
|
||||
ae_snip,
|
||||
ae_loc,
|
||||
ae_sess,
|
||||
ae_api,
|
||||
ae_trig,
|
||||
slct,
|
||||
slct_trigger
|
||||
} from '$lib/stores/ae_stores';
|
||||
|
||||
// Exports
|
||||
|
||||
interface Props {
|
||||
log_lvl?: number;
|
||||
// Expecting these for link_to_type: 'event', 'event_location', 'archive_content', etc
|
||||
link_to_type: string;
|
||||
link_to_id: string;
|
||||
input_name?: string;
|
||||
multiple?: boolean;
|
||||
required?: boolean;
|
||||
accept?: string;
|
||||
class_li_default?: string;
|
||||
class_li?: string;
|
||||
input_class_li?: string[];
|
||||
table_class_li?: string[];
|
||||
upload_complete?: boolean;
|
||||
submit_status?: null | string;
|
||||
hosted_file_id_li?: string[];
|
||||
hosted_file_obj_li?: any[];
|
||||
label?: import('svelte').Snippet;
|
||||
}
|
||||
|
||||
let {
|
||||
log_lvl = 0,
|
||||
link_to_type,
|
||||
link_to_id,
|
||||
input_name = 'file_list',
|
||||
multiple = true,
|
||||
required = true,
|
||||
accept = 'audio/*, image/*, video/*, .bak, .cfg, .css, .csv, .doc, .docx, .gz, .htm, .html, .ini, .iso, .j2, .json, .key, .keynote, .md, .pdf, .ppt, .pptx, .rar, .rtf, .sql, .svelte, ttf, .txt, .xls, .xlsx, .xz, .zip, .bin, .dmg, .exe, .js, .msi, .php, .py, .sh',
|
||||
class_li_default = 'flex flex-col gap-1 items-center justify-center w-full max-w-2xl mx-auto my-1',
|
||||
class_li = '',
|
||||
input_class_li = ['file_drop_area'],
|
||||
table_class_li = ['table', 'table-sm', 'table-striped', '', 'text-sm'],
|
||||
upload_complete = $bindable(false),
|
||||
submit_status = $bindable(null),
|
||||
hosted_file_id_li = $bindable([]),
|
||||
hosted_file_obj_li = $bindable([]),
|
||||
label
|
||||
}: Props = $props();
|
||||
|
||||
// Local Variables
|
||||
let task_id = $state(link_to_id);
|
||||
let input_file_list: any = $state(null);
|
||||
let ae_promises: key_val = $state({}); // Promise<any>;
|
||||
let ae_triggers: key_val = {};
|
||||
|
||||
let input_element_id = 'ae_comp__hosted_files_upload__input';
|
||||
|
||||
let form_kv: key_val = {
|
||||
start_time: null,
|
||||
end_time: null,
|
||||
reencode: null,
|
||||
video_file: null
|
||||
};
|
||||
let download_clip_src: string = $state();
|
||||
let download_clip_filename: string;
|
||||
|
||||
// *** Functions and Logic
|
||||
async function handle_submit_form_files(event: SubmitEvent) {
|
||||
console.log('*** handle_submit_form() ***');
|
||||
|
||||
$ae_sess.files.disable_submit__hosted_file_obj = true;
|
||||
$ae_sess.files.submit_status = 'saving';
|
||||
submit_status = 'saving';
|
||||
upload_complete = false;
|
||||
|
||||
hosted_file_id_li = [];
|
||||
hosted_file_obj_li = [];
|
||||
|
||||
let hosted_file_results;
|
||||
|
||||
form_kv = {
|
||||
start_time: event.target.start_time.value,
|
||||
end_time: event.target.end_time.value,
|
||||
reencode: event.target.reencode.value,
|
||||
video_file: event.target.file_list.files[0]
|
||||
};
|
||||
|
||||
// const form_data = new FormData();
|
||||
|
||||
// form_data.append('start_time', event.target.start_time.value);
|
||||
// form_data.append('end_time', event.target.end_time.value);
|
||||
|
||||
// if (event.target.reencode.value == '1' || event.target.reencode.value == 'true') {
|
||||
// form_data.append('reencode', 'true');
|
||||
// } else {
|
||||
// form_data.append('reencode', 'false');
|
||||
// }
|
||||
// form_data.append('reencode', event.target.reencode.value);
|
||||
|
||||
// form_data.append(`video_file`, event.target.video_file.files[0]);
|
||||
|
||||
// let download_filename = `clipped_file_test.mp4`;
|
||||
|
||||
// let params = null;
|
||||
|
||||
// let endpoint = '/hosted_file/clip_video';
|
||||
|
||||
// console.log(form_data);
|
||||
|
||||
// params = null;
|
||||
|
||||
if (event.target[input_element_id].files.length > 0) {
|
||||
task_id = link_to_id; // Ideally this should be the file hash, but we may be uploading multiple files at once. This should be done with a loop instead?
|
||||
|
||||
// Loop through each file and upload them individually in event.target[input_element_id].files
|
||||
// The task_id should be the file hash.
|
||||
// processed_file_list[i] has the file hash_sha256, hash_sha256_match, warnings, uploaded, uploaded_bytes, filename, and file_size_bytes.
|
||||
for (let i = 0; i < event.target[input_element_id].files.length; i++) {
|
||||
let tmp_file = event.target[input_element_id].files[i];
|
||||
|
||||
task_id = $ae_sess.files.processed_file_list[i].hash_sha256;
|
||||
|
||||
hosted_file_results = await handle_input_upload_files([tmp_file], form_kv, task_id);
|
||||
|
||||
if (hosted_file_results) {
|
||||
console.log(`hosted_file_results:`, hosted_file_results);
|
||||
} else {
|
||||
console.log(`hosted_file_results:`, hosted_file_results);
|
||||
}
|
||||
}
|
||||
// hosted_file_results = await handle_input_upload_files(event.target[input_element_id].files, task_id);
|
||||
$ae_sess.files.processed_file_list = [];
|
||||
$ae_sess = $ae_sess;
|
||||
event.target.reset();
|
||||
// await tick();
|
||||
|
||||
if (log_lvl) {
|
||||
console.log(`hosted_file_id_li: ${hosted_file_id_li}`, hosted_file_id_li);
|
||||
} else if (log_lvl > 1) {
|
||||
console.log('hosted_file_results:', hosted_file_results);
|
||||
}
|
||||
}
|
||||
|
||||
$ae_sess.files.disable_submit__hosted_file_obj = false;
|
||||
$ae_sess.files.submit_status = 'saved';
|
||||
submit_status = 'saved';
|
||||
upload_complete = true;
|
||||
}
|
||||
|
||||
async function handle_input_upload_files(input_upload_files, form_kv, task_id) {
|
||||
console.log('*** handle_input_upload_files() ***');
|
||||
console.log(input_upload_files);
|
||||
console.log(form_kv);
|
||||
|
||||
const form_data = new FormData();
|
||||
|
||||
// form_data.append('account_id', $ae_loc.account_id);
|
||||
// form_data.append('link_to_type', link_to_type);
|
||||
// form_data.append('link_to_id', link_to_id);
|
||||
|
||||
form_data.append('start_time', form_kv.start_time);
|
||||
form_data.append('end_time', form_kv.end_time);
|
||||
|
||||
if (form_kv.reencode == '1' || form_kv.reencode == 'true') {
|
||||
form_data.append('reencode', 'true');
|
||||
} else {
|
||||
form_data.append('reencode', 'false');
|
||||
}
|
||||
|
||||
// There should really only be one file uploaded at a time for now.
|
||||
for (let i = 0; i < input_upload_files.length; i++) {
|
||||
form_data.append(`video_file`, input_upload_files[i]);
|
||||
}
|
||||
|
||||
// hash_sha256, uploaded, uploaded_bytes
|
||||
// $ae_sess.files.processed_file_list[i] = {
|
||||
// ...$ae_sess.files.processed_file_list[i],
|
||||
// uploaded: $ae_sess.api_upload_kv[link_to_id].percent_completed,
|
||||
// uploaded_bytes: $ae_sess.api_upload_kv[link_to_id].uploaded_bytes,
|
||||
// };
|
||||
|
||||
let params = null;
|
||||
|
||||
let endpoint = '/hosted_file/clip_video';
|
||||
|
||||
console.log(form_data);
|
||||
|
||||
params = null;
|
||||
|
||||
// Uncomment and the post_promise is not seen by the "await" below
|
||||
// post_promise = await api.post_object({api_cfg: $cfg.api, endpoint: endpoint, params: params, data:form_data});
|
||||
// Uncomment so that the post_promise is not seen by the "await" below
|
||||
ae_promises.upload__hosted_file_obj = api
|
||||
.post_object({
|
||||
api_cfg: $ae_api,
|
||||
endpoint: endpoint,
|
||||
params: params,
|
||||
form_data: form_data,
|
||||
return_blob: true,
|
||||
filename: 'clipped_video_test.mp4',
|
||||
auto_download: false,
|
||||
task_id: task_id,
|
||||
log_lvl: log_lvl
|
||||
// retry_count: 1,
|
||||
})
|
||||
.then(async function (result) {
|
||||
console.log(result);
|
||||
|
||||
let file_blob = new Blob([result.data]);
|
||||
// console.log(file_blob);
|
||||
let file_obj_url = window.URL.createObjectURL(file_blob); // The img src
|
||||
// const url = window.URL.createObjectURL(new Blob([result.data]));
|
||||
download_clip_src = file_obj_url;
|
||||
// download_filename = file_obj_url;
|
||||
|
||||
return true;
|
||||
|
||||
// // WARNING!!!! ONLY ONE FILE IS EXPECTED TO BE UPLOADED AT A TIME!!!
|
||||
// // NOTE: The /hosted_file/upload_files endpoint will always return a list of successful files uploaded. In this case we are only uploading one file and expecting a list of one item.
|
||||
// let x = 0;
|
||||
// console.log(result[x]);
|
||||
// let hosted_file_obj = result[x];
|
||||
|
||||
// let hosted_file_id = hosted_file_obj.hosted_file_id_random;
|
||||
|
||||
// hosted_file_id_li.push(hosted_file_id);
|
||||
// hosted_file_obj_li.push(hosted_file_obj);
|
||||
|
||||
// let hosted_file_data: key_val = {};
|
||||
// hosted_file_data['hosted_file_id_random'] = hosted_file_id;
|
||||
// hosted_file_data['for_type'] = link_to_type;
|
||||
// hosted_file_data['for_id_random'] = link_to_id;
|
||||
// hosted_file_data['filename'] = hosted_file_obj.filename;
|
||||
// hosted_file_data['extension'] = hosted_file_obj.extension;
|
||||
// hosted_file_data['enable'] = true;
|
||||
// console.log(hosted_file_data);
|
||||
|
||||
// return hosted_file_data;
|
||||
|
||||
// $ae_sess.files.new_upload_list[i].uploaded_bytes = 10; // fake 10 bytes at least...
|
||||
|
||||
// let event_file_id = await events_func.create_hosted_file_obj_from_hosted_file_async({
|
||||
// api_cfg: $ae_api,
|
||||
// hosted_file_id: hosted_file_id,
|
||||
// data: event_file_data,
|
||||
// log_lvl: log_lvl
|
||||
// })
|
||||
// .then(function (create_result) {
|
||||
// console.log(create_result); // NOTE: This should be the event_file_id string
|
||||
// // let event_file_id = create_result;
|
||||
// return create_result;
|
||||
// });
|
||||
|
||||
// return event_file_id;
|
||||
})
|
||||
// .then(function (hosted_file_data) {
|
||||
// return hosted_file_data;
|
||||
// })
|
||||
.catch(function (error: any) {
|
||||
console.log('Something went wrong.');
|
||||
console.log(error);
|
||||
return false;
|
||||
})
|
||||
.finally(function () {
|
||||
// $slct_trigger = 'load__hosted_file_obj_li';
|
||||
});
|
||||
|
||||
console.log(ae_promises.upload__hosted_file_obj);
|
||||
let hosted_file_result = ae_promises.upload__hosted_file_obj;
|
||||
|
||||
return hosted_file_result;
|
||||
}
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<!-- class:hidden={!$ae_loc.trusted_access} -->
|
||||
<form onsubmit={preventDefault(handle_submit_form_files)} class="{class_li_default} {class_li}">
|
||||
<label class="label"
|
||||
>Start time (HH:MM:SS) <input
|
||||
type="text"
|
||||
name="start_time"
|
||||
value="00:00:00"
|
||||
placeholder="HH:MM:SS (00:01:30)"
|
||||
class="input w-32"
|
||||
/></label
|
||||
>
|
||||
<label class="label"
|
||||
>End time (HH:MM:SS) <input
|
||||
type="text"
|
||||
name="end_time"
|
||||
value="00:01:15"
|
||||
placeholder="HH:MM:SS (01:05:25)"
|
||||
class="input w-32"
|
||||
/></label
|
||||
>
|
||||
|
||||
<label class="label"
|
||||
>Re-encode (true or false) <input
|
||||
type="text"
|
||||
name="reencode"
|
||||
value="false"
|
||||
placeholder="true"
|
||||
class="input w-32"
|
||||
/></label
|
||||
>
|
||||
|
||||
{#await ae_promises.upload__hosted_file_obj}
|
||||
<div class="text-lg flex flex-row gap-1 items-center justify-center">
|
||||
<span class="fas fa-spinner fa-spin m-1"></span>
|
||||
<span class="">
|
||||
Uploading
|
||||
{#if $ae_sess.api_upload_kv[task_id]}
|
||||
{$ae_sess.api_upload_kv[task_id].percent_completed}%
|
||||
{/if}
|
||||
</span>
|
||||
</div>
|
||||
{/await}
|
||||
|
||||
<label
|
||||
for="ae_comp__hosted_files_upload__input"
|
||||
class="svelte_input_file_label text-center"
|
||||
class:hidden={$ae_sess.files.disable_submit__hosted_file_obj}
|
||||
>
|
||||
{#if label}{@render label()}{:else}
|
||||
<div>
|
||||
<span class="fas fa-upload"></span>
|
||||
<!-- Select files to upload -->
|
||||
<!-- <span class="fas fa-file-archive"></span> -->
|
||||
<strong class="bg-blue-300 p-1">Upload files</strong>
|
||||
<!-- (drag and drop) -->
|
||||
</div>
|
||||
<span class="text-sm text-gray-600 dark:text-gray-400 italic">
|
||||
<strong>Video files only</strong><br />
|
||||
(mp4 or mkv)
|
||||
</span>
|
||||
{/if}
|
||||
</label>
|
||||
|
||||
<input
|
||||
id={input_element_id}
|
||||
type="file"
|
||||
bind:files={input_file_list}
|
||||
{multiple}
|
||||
{required}
|
||||
{accept}
|
||||
name={input_name}
|
||||
class="svelte_input_file_element file-dropzone-input block w-full text-lg text-gray-900 border border-gray-300 rounded-lg cursor-pointer bg-gray-50 dark:text-gray-400 focus:outline-hidden dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 {input_class_li.join(
|
||||
' '
|
||||
)}"
|
||||
class:hidden={$ae_sess.files.disable_submit__hosted_file_obj}
|
||||
/>
|
||||
|
||||
<Element_input_files_tbl
|
||||
bind:input_file_list
|
||||
bind:file_list_status={$ae_sess.files.status__file_list}
|
||||
bind:processed_file_list={$ae_sess.files.processed_file_list}
|
||||
{table_class_li}
|
||||
/>
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-lg btn-primary preset-tonal-primary border border-primary-500 hover:preset-tonal-success border border-success-500 w-54"
|
||||
disabled={$ae_sess.files.disable_submit__hosted_file_obj ||
|
||||
$ae_sess.files.status__file_list != 'ready'}
|
||||
>
|
||||
{#await ae_promises.upload__hosted_file_obj}
|
||||
<span class="fas fa-spinner fa-spin m-1"></span>
|
||||
<span class="">
|
||||
Uploading
|
||||
{#if $ae_sess.api_upload_kv[task_id]}
|
||||
{$ae_sess.api_upload_kv[task_id].percent_completed}%
|
||||
{/if}
|
||||
</span>
|
||||
{:then}
|
||||
<span class="fas fa-upload m-1"></span>
|
||||
<span class="text-sm"> Upload? </span>
|
||||
<!-- <span class="fas fa-save m-1"></span> -->
|
||||
<span class="grow font-bold">
|
||||
{#if $ae_sess.files.processed_file_list?.length > 0}
|
||||
|
||||
{$ae_sess.files.processed_file_list.length == 1
|
||||
? `${$ae_sess.files.processed_file_list.length} file`
|
||||
: `${$ae_sess.files.processed_file_list.length} files`}
|
||||
{:else}
|
||||
<span class="text-xs"> No files selected </span>
|
||||
{/if}
|
||||
<!-- Files -->
|
||||
</span>
|
||||
{/await}
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<hr />
|
||||
|
||||
{#await ae_promises.upload__hosted_file_obj}
|
||||
<span class="fas fa-spinner fa-spin m-1"></span>
|
||||
<p class="highlight">Converting... This may take a few minutes.</p>
|
||||
{:then}
|
||||
{#if ae_promises.upload__hosted_file_obj}
|
||||
<a
|
||||
href={download_clip_src}
|
||||
download={download_clip_filename}
|
||||
class="ae_btn btn_lg btn_primary"
|
||||
><span class="fas fa-download"></span> Ready to Download</a
|
||||
>
|
||||
{:else}
|
||||
<p>Fill out the form and select the video file to clip.</p>
|
||||
{/if}
|
||||
{/await}
|
||||
</div>
|
||||
156
src/lib/ae_core/ae_comp__hosted_files_download_button.svelte
Normal file
156
src/lib/ae_core/ae_comp__hosted_files_download_button.svelte
Normal file
@@ -0,0 +1,156 @@
|
||||
<script lang="ts">
|
||||
// *** Import Svelte specific
|
||||
|
||||
// Eventually this should use Lucide icons instead of FontAwesome
|
||||
// import {
|
||||
// ArrowDown01, ArrowDown10, ArrowDownUp,
|
||||
// BookHeart, BriefcaseBusiness,
|
||||
// CalendarClock, CalendarOff, Clock, CodeXml, Copy,
|
||||
// Eye, EyeOff,
|
||||
// Flag, FlagOff, FileX, Fingerprint,
|
||||
// Globe, Group,
|
||||
// Hash, History,
|
||||
// LockKeyhole, LockKeyholeOpen,
|
||||
// MessageSquareWarning, Menu, Minus,
|
||||
// NotebookPen, NotebookText, NotepadTextDashed,
|
||||
// Pencil, PenLine, Plus,
|
||||
// RemoveFormatting,
|
||||
// Search, Settings,
|
||||
// Shapes, Share2, ShieldCheck, ShieldMinus, Siren, Skull,
|
||||
// SquareLibrary,
|
||||
// Tags, Trash2, TypeOutline,
|
||||
// X
|
||||
// } from '@lucide/svelte';
|
||||
|
||||
// *** Import Aether specific variables and functions
|
||||
import type { key_val } from '$lib/stores/ae_stores';
|
||||
import { ae_util } from '$lib/ae_utils/ae_utils';
|
||||
import { api } from '$lib/api/api';
|
||||
import {
|
||||
ae_snip,
|
||||
ae_loc,
|
||||
ae_sess,
|
||||
ae_api,
|
||||
ae_trig,
|
||||
slct,
|
||||
slct_trigger
|
||||
} from '$lib/stores/ae_stores';
|
||||
|
||||
interface Props {
|
||||
log_lvl?: number;
|
||||
hosted_file_id: null | string;
|
||||
hosted_file_obj: null | key_val;
|
||||
filename?: null | string;
|
||||
max_length?: number;
|
||||
auto_download?: boolean;
|
||||
linked_to_type?: null | string;
|
||||
linked_to_id?: null | string;
|
||||
download_complete?: null | boolean;
|
||||
download_percent?: number;
|
||||
download_status_msg?: string;
|
||||
classes?: string;
|
||||
}
|
||||
|
||||
let {
|
||||
log_lvl = 0,
|
||||
hosted_file_id,
|
||||
hosted_file_obj,
|
||||
filename = $bindable(null),
|
||||
max_length = $bindable(30),
|
||||
auto_download = true,
|
||||
linked_to_type = $bindable(null),
|
||||
linked_to_id = $bindable(null),
|
||||
download_complete = $bindable(),
|
||||
download_percent = $bindable(),
|
||||
download_status_msg = $bindable('Not started'),
|
||||
classes = 'btn btn-sm lg:btn-md preset-tonal-tertiary border border-tertiary-500 hover:preset-filled-tertiary-500 min-w-48'
|
||||
}: Props = $props();
|
||||
|
||||
if (log_lvl) {
|
||||
console.log(
|
||||
`ae_comp__hosted_files_download_button.svelte hosted_file_id=${hosted_file_id}`,
|
||||
hosted_file_obj
|
||||
);
|
||||
}
|
||||
|
||||
let ae_promises: key_val = $state({});
|
||||
|
||||
$effect(() => {
|
||||
if ($ae_sess?.api_download_kv[hosted_file_obj?.hosted_file_id_random]?.percent_completed) {
|
||||
download_percent =
|
||||
$ae_sess.api_download_kv[hosted_file_obj?.hosted_file_id_random].percent_completed;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
{#if hosted_file_id && hosted_file_obj}
|
||||
<button
|
||||
type="button"
|
||||
disabled={!$ae_loc.trusted_access}
|
||||
class={classes ?? 'btn'}
|
||||
onclick={() => {
|
||||
download_complete = false;
|
||||
download_status_msg = 'Downloading...';
|
||||
ae_promises[hosted_file_obj.hosted_file_id_random] = api
|
||||
.download_hosted_file({
|
||||
api_cfg: $ae_api,
|
||||
hosted_file_id: hosted_file_obj.hosted_file_id_random,
|
||||
return_file: true,
|
||||
filename: filename ?? hosted_file_obj.filename,
|
||||
auto_download: auto_download,
|
||||
log_lvl: log_lvl
|
||||
})
|
||||
.then((result) => {
|
||||
if (result === null) {
|
||||
console.log('File not found (404)');
|
||||
download_complete = null;
|
||||
download_status_msg = 'File not found';
|
||||
} else if (result === false) {
|
||||
console.log(
|
||||
'Possible error with API server (check network and server status)'
|
||||
);
|
||||
download_complete = false;
|
||||
download_status_msg = 'Failed to download';
|
||||
} else {
|
||||
// console.log('File found and downloaded');
|
||||
download_complete = true;
|
||||
download_status_msg = 'File downloaded';
|
||||
}
|
||||
return result;
|
||||
});
|
||||
}}
|
||||
title={`Download this file:\n${filename ?? hosted_file_obj?.filename}\n[API] SHA256: ${hosted_file_obj?.hash_sha256?.slice(0, 10)}...\nHosted ID: ${hosted_file_obj?.hosted_file_id_random}\n Linked to: ${linked_to_type} ID: ${linked_to_id}`}
|
||||
>
|
||||
{#await ae_promises[hosted_file_obj.hosted_file_id_random]}
|
||||
<span class="fas fa-spinner fa-spin mx-1"></span>
|
||||
<span class="">
|
||||
Downloading
|
||||
{#if $ae_sess.api_download_kv[hosted_file_obj.hosted_file_id_random]}
|
||||
{$ae_sess.api_download_kv[hosted_file_obj.hosted_file_id_random]
|
||||
.percent_completed}%
|
||||
{/if}
|
||||
:
|
||||
</span>
|
||||
{:then}
|
||||
<span class="fas fa-{ae_util.file_extension_icon(hosted_file_obj?.extension)}"></span>
|
||||
{/await}
|
||||
|
||||
{#if download_complete === null}
|
||||
<span class="text-red-800 dark:text-red-200">File not found</span>
|
||||
{:else if download_complete === false}
|
||||
<span class="text-red-800 dark:text-red-200">Failed to download!</span>
|
||||
{/if}
|
||||
|
||||
<span class="grow">
|
||||
{ae_util.shorten_filename({
|
||||
filename: filename ?? hosted_file_obj?.filename,
|
||||
max_length: max_length
|
||||
})}
|
||||
</span>
|
||||
</button>
|
||||
{:else}
|
||||
<button type="button" disabled class={classes ?? 'btn'} title="No file selected">
|
||||
<span class="fas fa-{ae_util.file_extension_icon(hosted_file_obj?.extension)}"></span>
|
||||
<span class="grow"> No file info </span>
|
||||
</button>
|
||||
{/if}
|
||||
349
src/lib/ae_core/ae_comp__hosted_files_upload.svelte
Normal file
349
src/lib/ae_core/ae_comp__hosted_files_upload.svelte
Normal file
@@ -0,0 +1,349 @@
|
||||
<script lang="ts">
|
||||
import { preventDefault } from 'svelte/legacy';
|
||||
|
||||
// Imports
|
||||
// Import components and elements
|
||||
import Element_input_files_tbl from '$lib/elements/element_input_files_tbl.svelte';
|
||||
|
||||
// Import storage, functions, and libraries
|
||||
import type { key_val } from '$lib/stores/ae_stores';
|
||||
|
||||
import { api } from '$lib/api/api';
|
||||
import {
|
||||
ae_snip,
|
||||
ae_loc,
|
||||
ae_sess,
|
||||
ae_api,
|
||||
ae_trig,
|
||||
slct,
|
||||
slct_trigger
|
||||
} from '$lib/stores/ae_stores';
|
||||
|
||||
// Exports
|
||||
|
||||
interface Props {
|
||||
log_lvl?: number;
|
||||
// Expecting these for link_to_type: 'event', 'event_location', 'archive_content', etc
|
||||
link_to_type: string;
|
||||
link_to_id: string;
|
||||
input_name?: string;
|
||||
multiple?: boolean;
|
||||
required?: boolean;
|
||||
accept?: string;
|
||||
class_li_default?: string;
|
||||
class_li?: string;
|
||||
input_class_li?: string[];
|
||||
table_class_li?: string[];
|
||||
upload_complete?: boolean;
|
||||
submit_status?: null | string;
|
||||
hosted_file_id_li?: string[];
|
||||
hosted_file_obj_li?: any[];
|
||||
hosted_file_obj_kv?: key_val;
|
||||
label?: import('svelte').Snippet;
|
||||
}
|
||||
|
||||
let {
|
||||
log_lvl = 0,
|
||||
link_to_type,
|
||||
link_to_id,
|
||||
input_name = 'file_list',
|
||||
multiple = true,
|
||||
required = true,
|
||||
accept = 'audio/*, image/*, video/*, .bak, .cfg, .css, .csv, .doc, .docx, .gz, .htm, .html, .ini, .iso, .j2, .json, .key, .keynote, .md, .pdf, .ppt, .pptx, .rar, .rtf, .sql, .svelte, ttf, .txt, .xls, .xlsx, .xz, .zip, .bin, .dmg, .exe, .js, .msi, .php, .py, .sh',
|
||||
class_li_default = 'flex flex-col gap-1 items-center justify-center w-full max-w-2xl mx-auto my-1',
|
||||
class_li = '',
|
||||
input_class_li = ['file_drop_area'],
|
||||
table_class_li = ['table', 'table-sm', 'table-striped', '', 'text-sm'],
|
||||
upload_complete = $bindable(false),
|
||||
submit_status = $bindable(null),
|
||||
hosted_file_id_li = $bindable([]),
|
||||
hosted_file_obj_li = $bindable([]),
|
||||
hosted_file_obj_kv = $bindable({}),
|
||||
label
|
||||
}: Props = $props();
|
||||
|
||||
// Local Variables
|
||||
let task_id = $state(link_to_id);
|
||||
let input_file_list: any = $state(null);
|
||||
let ae_promises: key_val = $state({}); // Promise<any>;
|
||||
let ae_triggers: key_val = {};
|
||||
|
||||
let input_element_id = 'ae_comp__hosted_files_upload__input';
|
||||
|
||||
// *** Functions and Logic
|
||||
async function handle_submit_form_files(event: SubmitEvent) {
|
||||
console.log('*** handle_submit_form() ***');
|
||||
|
||||
if (!event) {
|
||||
return;
|
||||
}
|
||||
|
||||
$ae_sess.files.disable_submit__hosted_file_obj = true;
|
||||
$ae_sess.files.submit_status = 'saving';
|
||||
submit_status = 'saving';
|
||||
upload_complete = false;
|
||||
|
||||
hosted_file_id_li = [];
|
||||
hosted_file_obj_li = [];
|
||||
hosted_file_obj_kv = {};
|
||||
|
||||
let hosted_file_results;
|
||||
|
||||
const target = event.target as HTMLFormElement;
|
||||
if (
|
||||
target &&
|
||||
target[input_element_id] &&
|
||||
(target[input_element_id] as HTMLInputElement)?.files &&
|
||||
(target[input_element_id] as HTMLInputElement).files.length > 0
|
||||
) {
|
||||
task_id = link_to_id; // Ideally this should be the file hash, but we may be uploading multiple files at once. This should be done with a loop instead?
|
||||
|
||||
// Loop through each file and upload them individually in event.target[input_element_id].files
|
||||
// The task_id should be the file hash.
|
||||
// processed_file_list[i] has the file hash_sha256, hash_sha256_match, warnings, uploaded, uploaded_bytes, filename, and file_size_bytes.
|
||||
for (let i = 0; i < event.target[input_element_id].files.length; i++) {
|
||||
let tmp_file = event.target[input_element_id].files[i];
|
||||
|
||||
task_id = $ae_sess.files.processed_file_list[i].hash_sha256;
|
||||
|
||||
// hosted_file_results = await handle_input_upload_files([tmp_file], task_id);
|
||||
hosted_file_results = await handle_input_upload_files({
|
||||
input_upload_files: [tmp_file],
|
||||
task_id: task_id
|
||||
});
|
||||
|
||||
if (hosted_file_results) {
|
||||
console.log(`hosted_file_results:`, hosted_file_results);
|
||||
} else {
|
||||
console.log(`hosted_file_results:`, hosted_file_results);
|
||||
}
|
||||
}
|
||||
// hosted_file_results = await handle_input_upload_files(event.target[input_element_id].files, task_id);
|
||||
$ae_sess.files.processed_file_list = [];
|
||||
$ae_sess = $ae_sess; // Is this needed? 2025-03-17
|
||||
event.target.reset();
|
||||
// await tick();
|
||||
|
||||
if (log_lvl) {
|
||||
console.log(`hosted_file_id_li: ${hosted_file_id_li}`, hosted_file_id_li);
|
||||
} else if (log_lvl > 1) {
|
||||
console.log('hosted_file_results:', hosted_file_results);
|
||||
}
|
||||
}
|
||||
|
||||
$ae_sess.files.disable_submit__hosted_file_obj = false;
|
||||
$ae_sess.files.submit_status = 'saved';
|
||||
submit_status = 'saved';
|
||||
upload_complete = true;
|
||||
}
|
||||
|
||||
async function handle_input_upload_files({
|
||||
input_upload_files,
|
||||
task_id
|
||||
}: {
|
||||
input_upload_files: any[];
|
||||
task_id: string;
|
||||
}) {
|
||||
console.log('*** handle_input_upload_files() ***');
|
||||
|
||||
const form_data = new FormData();
|
||||
|
||||
form_data.append('account_id', $ae_loc.account_id);
|
||||
form_data.append('link_to_type', link_to_type);
|
||||
form_data.append('link_to_id', link_to_id);
|
||||
|
||||
for (let i = 0; i < input_upload_files.length; i++) {
|
||||
form_data.append(`file_list`, input_upload_files[i]);
|
||||
}
|
||||
|
||||
// hash_sha256, uploaded, uploaded_bytes
|
||||
// $ae_sess.files.processed_file_list[i] = {
|
||||
// ...$ae_sess.files.processed_file_list[i],
|
||||
// uploaded: $ae_sess.api_upload_kv[link_to_id].percent_completed,
|
||||
// uploaded_bytes: $ae_sess.api_upload_kv[link_to_id].uploaded_bytes,
|
||||
// };
|
||||
|
||||
let params = null;
|
||||
|
||||
let endpoint = '/hosted_file/upload_files';
|
||||
|
||||
console.log(form_data);
|
||||
|
||||
params = null;
|
||||
|
||||
// Uncomment and the post_promise is not seen by the "await" below
|
||||
// post_promise = await api.post_object({api_cfg: $cfg.api, endpoint: endpoint, params: params, data:form_data});
|
||||
// Uncomment so that the post_promise is not seen by the "await" below
|
||||
ae_promises.upload__hosted_file_obj = api
|
||||
.post_object({
|
||||
api_cfg: $ae_api,
|
||||
endpoint: endpoint,
|
||||
// params: params,
|
||||
form_data: form_data,
|
||||
task_id: task_id,
|
||||
log_lvl: log_lvl
|
||||
// retry_count: 1,
|
||||
})
|
||||
.then(async function (result) {
|
||||
// WARNING!!!! ONLY ONE FILE IS EXPECTED TO BE UPLOADED AT A TIME!!!
|
||||
// NOTE: The /hosted_file/upload_files endpoint will always return a list of successful files uploaded. In this case we are only uploading one file and expecting a list of one item.
|
||||
let x = 0;
|
||||
console.log(result[x]);
|
||||
let hosted_file_obj = result[x];
|
||||
|
||||
let hosted_file_id = hosted_file_obj.hosted_file_id_random;
|
||||
|
||||
hosted_file_id_li.push(hosted_file_id);
|
||||
hosted_file_obj_li.push(hosted_file_obj);
|
||||
|
||||
let hosted_file_data: key_val = {};
|
||||
hosted_file_data['id'] = hosted_file_id;
|
||||
hosted_file_data['hosted_file_id'] = hosted_file_id;
|
||||
hosted_file_data['hosted_file_id_random'] = hosted_file_id;
|
||||
hosted_file_data['for_type'] = link_to_type;
|
||||
hosted_file_data['for_id'] = link_to_id;
|
||||
hosted_file_data['for_id_random'] = link_to_id;
|
||||
hosted_file_data['hash_sha256'] = hosted_file_obj.hash_sha256;
|
||||
hosted_file_data['filename'] = hosted_file_obj.filename;
|
||||
hosted_file_data['extension'] = hosted_file_obj.extension;
|
||||
hosted_file_data['content_type'] = hosted_file_obj.content_type;
|
||||
hosted_file_data['size'] = hosted_file_obj.size;
|
||||
hosted_file_data['enable'] = true;
|
||||
hosted_file_data['created_on'] = hosted_file_obj.created_on;
|
||||
hosted_file_data['updated_on'] = hosted_file_obj.updated_on;
|
||||
console.log(hosted_file_data);
|
||||
|
||||
hosted_file_obj_kv[hosted_file_id] = hosted_file_data;
|
||||
|
||||
return hosted_file_data;
|
||||
|
||||
// $ae_sess.files.new_upload_list[i].uploaded_bytes = 10; // fake 10 bytes at least...
|
||||
|
||||
// let event_file_id = await events_func.create_hosted_file_obj_from_hosted_file_async({
|
||||
// api_cfg: $ae_api,
|
||||
// hosted_file_id: hosted_file_id,
|
||||
// data: event_file_data,
|
||||
// log_lvl: log_lvl
|
||||
// })
|
||||
// .then(function (create_result) {
|
||||
// console.log(create_result); // NOTE: This should be the event_file_id string
|
||||
// // let event_file_id = create_result;
|
||||
// return create_result;
|
||||
// });
|
||||
|
||||
// return event_file_id;
|
||||
})
|
||||
.then(function (hosted_file_data) {
|
||||
return hosted_file_data;
|
||||
})
|
||||
.catch(function (error: any) {
|
||||
console.log('Something went wrong.');
|
||||
console.log(error);
|
||||
return false;
|
||||
})
|
||||
.finally(function () {
|
||||
$slct_trigger = 'load__hosted_file_obj_li';
|
||||
});
|
||||
|
||||
console.log(ae_promises.upload__hosted_file_obj);
|
||||
let hosted_file_result = ae_promises.upload__hosted_file_obj;
|
||||
|
||||
return hosted_file_result;
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- class:hidden={!$ae_loc.trusted_access} -->
|
||||
<form onsubmit={preventDefault(handle_submit_form_files)} class="{class_li_default} {class_li}">
|
||||
{#await ae_promises.upload__hosted_file_obj}
|
||||
<div class="text-lg flex flex-row gap-1 items-center justify-center">
|
||||
<span class="fas fa-spinner fa-spin m-1"></span>
|
||||
<span class="">
|
||||
Uploading
|
||||
{#if $ae_sess.api_upload_kv[task_id]}
|
||||
{$ae_sess.api_upload_kv[task_id].percent_completed}%
|
||||
{/if}
|
||||
</span>
|
||||
</div>
|
||||
{/await}
|
||||
|
||||
<label
|
||||
for="ae_comp__hosted_files_upload__input"
|
||||
class="svelte_input_file_label text-center"
|
||||
class:hidden={$ae_sess.files.disable_submit__hosted_file_obj}
|
||||
>
|
||||
{#if label}{@render label()}{:else}
|
||||
<div>
|
||||
<span class="fas fa-upload"></span>
|
||||
<!-- Select files to upload -->
|
||||
<!-- <span class="fas fa-file-archive"></span> -->
|
||||
<strong class="bg-blue-300 p-1">Upload files</strong>
|
||||
<!-- (drag and drop) -->
|
||||
</div>
|
||||
<span class="text-sm text-gray-600 dark:text-gray-400 italic">
|
||||
<strong>Presentation related files only</strong><br />
|
||||
(PowerPoint, Keynote, PDF, mp4, Word Doc, Excel, txt, etc)
|
||||
</span>
|
||||
{/if}
|
||||
</label>
|
||||
|
||||
<input
|
||||
id={input_element_id}
|
||||
type="file"
|
||||
bind:files={input_file_list}
|
||||
{multiple}
|
||||
{required}
|
||||
{accept}
|
||||
name={input_name}
|
||||
class="
|
||||
svelte_input_file_element
|
||||
file-dropzone-input
|
||||
px-1
|
||||
block w-full text-lg
|
||||
text-gray-900
|
||||
border border-gray-300 rounded-lg
|
||||
cursor-pointer b
|
||||
g-gray-50 dark:text-gray-400 focus:outline-hidden dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400
|
||||
{input_class_li.join(' ')}
|
||||
"
|
||||
class:hidden={$ae_sess.files.disable_submit__hosted_file_obj}
|
||||
/>
|
||||
|
||||
<Element_input_files_tbl
|
||||
bind:input_file_list
|
||||
bind:file_list_status={$ae_sess.files.status__file_list}
|
||||
bind:processed_file_list={$ae_sess.files.processed_file_list}
|
||||
{table_class_li}
|
||||
/>
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-lg btn-primary preset-tonal-primary border border-primary-500 hover:preset-tonal-success border border-success-500 w-54"
|
||||
disabled={$ae_sess.files.disable_submit__hosted_file_obj ||
|
||||
$ae_sess.files.status__file_list != 'ready'}
|
||||
>
|
||||
{#await ae_promises.upload__hosted_file_obj}
|
||||
<span class="fas fa-spinner fa-spin m-1"></span>
|
||||
<span class="">
|
||||
Uploading
|
||||
{#if $ae_sess.api_upload_kv[task_id]}
|
||||
{$ae_sess.api_upload_kv[task_id].percent_completed}%
|
||||
{/if}
|
||||
</span>
|
||||
{:then}
|
||||
<span class="fas fa-upload m-1"></span>
|
||||
<span class="text-sm"> Upload? </span>
|
||||
<!-- <span class="fas fa-save m-1"></span> -->
|
||||
<span class="grow font-bold">
|
||||
{#if $ae_sess.files.processed_file_list?.length > 0}
|
||||
|
||||
{$ae_sess.files.processed_file_list.length == 1
|
||||
? `${$ae_sess.files.processed_file_list.length} file`
|
||||
: `${$ae_sess.files.processed_file_list.length} files`}
|
||||
{:else}
|
||||
<span class="text-xs"> No files selected </span>
|
||||
{/if}
|
||||
<!-- Files -->
|
||||
</span>
|
||||
{/await}
|
||||
</button>
|
||||
</form>
|
||||
687
src/lib/ae_core/ae_core_functions.ts
Normal file
687
src/lib/ae_core/ae_core_functions.ts
Normal file
@@ -0,0 +1,687 @@
|
||||
import { browser } from '$app/environment';
|
||||
import type { key_val } from '$lib/stores/ae_stores';
|
||||
import { api } from '$lib/api/api';
|
||||
|
||||
import {
|
||||
load_ae_obj_id__activity_log,
|
||||
load_ae_obj_li__activity_log,
|
||||
create_ae_obj__activity_log,
|
||||
update_ae_obj__activity_log
|
||||
// db_save_ae_obj_li__activity_log
|
||||
} from '$lib/ae_core/core__activity_log';
|
||||
|
||||
import {
|
||||
load_ae_obj_id__person,
|
||||
load_ae_obj_li__person,
|
||||
create_ae_obj__person,
|
||||
delete_ae_obj_id__person,
|
||||
update_ae_obj__person
|
||||
// db_save_ae_obj_li__person
|
||||
} from '$lib/ae_core/core__person';
|
||||
|
||||
import {
|
||||
auth_ae_obj__username_password,
|
||||
auth_ae_obj__user_id_user_auth_key,
|
||||
send_email_auth_ae_obj__user_id,
|
||||
qry_ae_obj_li__user_email,
|
||||
auth_ae_obj__user_id_change_password
|
||||
// handle_load_ae_obj_id__user,
|
||||
// handle_load_ae_obj_li__user,
|
||||
// handle_create_ae_obj__user,
|
||||
// handle_update_ae_obj__user,
|
||||
// handle_db_save_ae_obj_li__user
|
||||
} from '$lib/ae_core/core__user';
|
||||
|
||||
import { generate_qr_code, js_generate_qr_code } from '$lib/ae_core/core__qr_code';
|
||||
|
||||
import { check_hosted_file_obj_w_hash } from '$lib/ae_core/core__check_hosted_file_obj_w_hash';
|
||||
|
||||
import { load_ae_obj_li__time_zone } from '$lib/ae_core/core__time_zones';
|
||||
|
||||
import { load_ae_obj_li__country } from '$lib/ae_core/core__countries';
|
||||
|
||||
import { load_ae_obj_li__country_subdivision } from '$lib/ae_core/core__country_subdivisions';
|
||||
|
||||
import {
|
||||
load_ae_obj_id__hosted_file,
|
||||
load_ae_obj_li__hosted_file,
|
||||
delete_ae_obj_id__hosted_file,
|
||||
db_save_ae_obj_li__hosted_file,
|
||||
db_update_ae_obj_id__hosted_file
|
||||
} from '$lib/ae_core/core__hosted_files';
|
||||
|
||||
// This has more generic general purpose functions that can eventually replace the custom ones per object type.
|
||||
import { db_save_ae_obj_li__ae_obj } from '$lib/ae_core/core__idb_dexie';
|
||||
|
||||
import { add_url_params, clean_headers } from '$lib/ae_core/core__api_helpers';
|
||||
|
||||
const ae_promises: key_val = {}; // Promise<any>;
|
||||
|
||||
// Updated 2024-03-29
|
||||
async function load_ae_obj_id__site_domain({
|
||||
api_cfg,
|
||||
fqdn,
|
||||
try_cache = false,
|
||||
timeout = 7000,
|
||||
log_lvl = 0
|
||||
}: {
|
||||
api_cfg: any;
|
||||
fqdn: string;
|
||||
try_cache?: boolean;
|
||||
timeout?: number;
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
if (log_lvl) {
|
||||
console.log(
|
||||
`*** load_ae_obj_id__site_domain() *** api.base_url=${api_cfg.base_url}, fqdn=${fqdn}, timeout=${timeout}`
|
||||
);
|
||||
}
|
||||
|
||||
let no_account_id = false;
|
||||
if (!api_cfg.account_id) {
|
||||
no_account_id = true;
|
||||
// api_cfg.headers['x_account_id'] = 'nothing here';
|
||||
}
|
||||
no_account_id = true;
|
||||
|
||||
const params = {};
|
||||
|
||||
// ae_sess.hub.site_domain_id_qry_status = 'loading';
|
||||
ae_promises.load__site_domain_obj = api
|
||||
.get_ae_obj_id_crud({
|
||||
api_cfg: api_cfg,
|
||||
no_account_id: no_account_id,
|
||||
obj_type: 'site_domain',
|
||||
obj_id: fqdn, // NOTE: This is the FQDN, not normally the ID.
|
||||
use_alt_table: true, // NOTE: This will use the table_name_alt value (v_site_domain_fqdn_id) instead of the table_name value in the API config.
|
||||
use_alt_base: true, // NOTE: This will use the base_name_alt value (Site_Domain_FQDN_ID_Base) instead of the base_name value in the API config.
|
||||
params: params,
|
||||
timeout: timeout,
|
||||
log_lvl: log_lvl
|
||||
})
|
||||
.then(function (site_domain_obj_get_result) {
|
||||
if (site_domain_obj_get_result) {
|
||||
// slct.site_domain_obj = site_domain_obj_get_result;
|
||||
// console.log(`site_domain object:`, get(slct).site_domain_obj);
|
||||
|
||||
// ae_loc.account_id = $slct.site_domain_obj.account_id_random;
|
||||
// ae_loc.site_id = $slct.site_domain_obj.site_id_random;
|
||||
// ae_loc.site_domain_id = $slct.site_domain_obj.site_domain_id_random;
|
||||
return site_domain_obj_get_result;
|
||||
} else {
|
||||
console.log('No results returned.');
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.catch(function (error: any) {
|
||||
console.log('No results returned or failed.', error);
|
||||
});
|
||||
|
||||
return ae_promises.load__site_domain_obj;
|
||||
}
|
||||
|
||||
// Updated 2024-03-29
|
||||
async function load_ae_obj_code__data_store({
|
||||
api_cfg,
|
||||
code,
|
||||
data_type = 'text',
|
||||
for_type = null,
|
||||
for_id = null,
|
||||
try_cache = true,
|
||||
save_idb = false,
|
||||
timeout = 9000,
|
||||
log_lvl = 0
|
||||
}: {
|
||||
api_cfg: any;
|
||||
code: string;
|
||||
data_type?: string;
|
||||
for_type?: string | null;
|
||||
for_id?: string | null;
|
||||
try_cache?: boolean;
|
||||
save_idb?: boolean;
|
||||
timeout?: number;
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
if (log_lvl) {
|
||||
console.log(`*** load_ae_obj_code__data_store() *** code=${code}`);
|
||||
}
|
||||
|
||||
if (!code) {
|
||||
console.log(`*ae_func* No code provided!`);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!api_cfg.account_id) {
|
||||
console.log(`*ae_func* No account_id found in API config!`);
|
||||
return false;
|
||||
}
|
||||
|
||||
ae_promises.load__data_store_obj = api
|
||||
.get_data_store_obj_w_code({
|
||||
api_cfg: api_cfg,
|
||||
data_store_code: code,
|
||||
data_type: data_type,
|
||||
timeout: timeout,
|
||||
log_lvl: log_lvl
|
||||
})
|
||||
.then(function (get_ds_result) {
|
||||
let return_this = null;
|
||||
if (get_ds_result) {
|
||||
if (log_lvl) {
|
||||
console.log(`*ae_func* Got a result for code ${code}`);
|
||||
}
|
||||
|
||||
if (!get_ds_result.data_store_id_random) {
|
||||
console.log('*ae_func* Something went wrong? No data store ID found.');
|
||||
return false;
|
||||
}
|
||||
|
||||
// let ae_ds_tmp: key_val = {};
|
||||
const ds_code_obj = {
|
||||
id: null,
|
||||
account_id: null,
|
||||
code: code,
|
||||
name: null,
|
||||
type: data_type,
|
||||
for_type: null, // for_type
|
||||
for_id: null, // for_id
|
||||
access_read: null, // 'super', 'administrator', 'trusted', 'anonymous'
|
||||
access_write: null, // 'super', 'administrator', 'trusted', 'anonymous'
|
||||
access_delete: null, // 'super', 'administrator', 'trusted', 'anonymous'
|
||||
html: null,
|
||||
json: null,
|
||||
md: null,
|
||||
text: null,
|
||||
updated_on: null,
|
||||
chk_account_id: api_cfg.account_id,
|
||||
loaded_on: new Date().toISOString()
|
||||
};
|
||||
let val_json: key_val;
|
||||
let val_html: key_val;
|
||||
let val_md: key_val;
|
||||
let val_sql: key_val;
|
||||
let val_text: string;
|
||||
|
||||
// Set the loaded_on datetime to the current time for reference later. This will be used to determine if the data store is stale.
|
||||
// ds_code_obj.loaded_on = new Date().toISOString();
|
||||
// Set the chk_account_id as a backup check to make sure the data store belongs to the account for the current site. This should not be needed, but here we are...
|
||||
// ds_code_obj.chk_account_id = api_cfg.account_id;
|
||||
|
||||
ds_code_obj.id = get_ds_result.data_store_id_random;
|
||||
ds_code_obj.account_id = get_ds_result.account_id_random;
|
||||
ds_code_obj.code = get_ds_result.code; // This will overwrite whatever was passed in.
|
||||
ds_code_obj.name = get_ds_result.name;
|
||||
ds_code_obj.type = get_ds_result.type; // This will overwrite whatever was passed in.
|
||||
if (data_type == 'html') {
|
||||
ds_code_obj.html = get_ds_result.text;
|
||||
val_html = get_ds_result.text;
|
||||
return_this = get_ds_result.html;
|
||||
} else if (data_type == 'json') {
|
||||
ds_code_obj.json = get_ds_result.json;
|
||||
val_json = get_ds_result.json;
|
||||
return_this = get_ds_result.json;
|
||||
} else if (data_type == 'md') {
|
||||
ds_code_obj.text = get_ds_result.text;
|
||||
val_md = get_ds_result.text;
|
||||
return_this = get_ds_result.text;
|
||||
} else if (data_type == 'sql') {
|
||||
ds_code_obj.text = get_ds_result.text;
|
||||
val_sql = get_ds_result.text;
|
||||
return_this = get_ds_result.text;
|
||||
} else {
|
||||
ds_code_obj.text = get_ds_result.text;
|
||||
val_text = get_ds_result.text;
|
||||
return_this = get_ds_result.text;
|
||||
}
|
||||
|
||||
// if (data_type == 'text') {
|
||||
// // console.log(get_ds_result.text);
|
||||
// return_this = get_ds_result.text;
|
||||
// } else if (data_type == 'json') {
|
||||
// // console.log(get_ds_result.json);
|
||||
// return_this = get_ds_result.json;
|
||||
// }
|
||||
|
||||
if (save_idb) {
|
||||
if (browser) {
|
||||
const key_prefix = 'ae_ds__';
|
||||
if (log_lvl) {
|
||||
console.log(
|
||||
`*ae_func* localStorage key: ${code}, value:`,
|
||||
get_ds_result
|
||||
);
|
||||
}
|
||||
localStorage.setItem(`${key_prefix}${code}`, JSON.stringify(get_ds_result));
|
||||
} else {
|
||||
if (log_lvl) {
|
||||
console.log(
|
||||
'*ae_func* No browser! Can not use localStorage to save data store object.'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.log('*ae_func* No results returned.');
|
||||
return_this = null;
|
||||
}
|
||||
return return_this;
|
||||
})
|
||||
.catch(function (error: any) {
|
||||
console.log('*ae_func* No results returned or failed.', error);
|
||||
});
|
||||
|
||||
return ae_promises.load__data_store_obj;
|
||||
}
|
||||
|
||||
// Updated 2024-03-27
|
||||
async function update_ae_obj_id_crud({
|
||||
api_cfg,
|
||||
object_type,
|
||||
object_id,
|
||||
object_reload = false,
|
||||
field_name,
|
||||
new_field_value,
|
||||
params = {},
|
||||
try_cache = false,
|
||||
log_lvl = 0
|
||||
}: {
|
||||
api_cfg: any;
|
||||
object_type: string;
|
||||
object_id: string;
|
||||
object_reload?: boolean;
|
||||
field_name: string;
|
||||
new_field_value: any;
|
||||
params: any | key_val;
|
||||
try_cache: boolean;
|
||||
log_lvl: number;
|
||||
}) {
|
||||
let patch_result: any = null;
|
||||
|
||||
ae_promises.api_update__ae_obj = api
|
||||
.update_ae_obj_id_crud({
|
||||
api_cfg: api_cfg,
|
||||
obj_type: object_type,
|
||||
obj_id: object_id,
|
||||
field_name: field_name,
|
||||
field_value: new_field_value,
|
||||
// fields: data,
|
||||
key: api_cfg.api_crud_super_key,
|
||||
// jwt: null,
|
||||
// params: params,
|
||||
// data: patch_data,
|
||||
log_lvl: log_lvl
|
||||
})
|
||||
.then(function (results) {
|
||||
console.log('PATCH Promise', results);
|
||||
|
||||
if (results) {
|
||||
console.log(
|
||||
`Patched - Field Name: ${field_name} with new Field Value: ${new_field_value}`
|
||||
);
|
||||
patch_result = 'PATCH complete';
|
||||
} else {
|
||||
console.log(
|
||||
`Not Patched - Field Name: ${field_name} with new Field Value: ${new_field_value}; Account ID: ${api_cfg.account_id}`
|
||||
);
|
||||
patch_result = 'PATCH failed';
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
})
|
||||
.catch(function (error: any) {
|
||||
console.log('Something went wrong patching the record.');
|
||||
console.log(error);
|
||||
return false;
|
||||
})
|
||||
.finally(function () {
|
||||
console.log('PATCH Promise finally');
|
||||
});
|
||||
|
||||
return ae_promises.api_update__ae_obj;
|
||||
}
|
||||
|
||||
// Core - Already imported above
|
||||
// import { load_ae_obj_id__person } from "$lib/ae_core/core__person";
|
||||
// import { load_ae_obj_id__user } from "$lib/ae_core/core__user";
|
||||
|
||||
// Additional Modules
|
||||
import { load_ae_obj_id__archive } from '$lib/ae_archives/ae_archives__archive';
|
||||
import { load_ae_obj_id__archive_content } from '$lib/ae_archives/ae_archives__archive_content';
|
||||
|
||||
import { load_ae_obj_id__event } from '$lib/ae_events/ae_events__event';
|
||||
// import { load_ae_obj_id__event_badge } from "$lib/ae_events/ae_events__event_badge";
|
||||
import { load_ae_obj_id__event_device } from '$lib/ae_events/ae_events__event_device';
|
||||
// import { load_ae_obj_id__event_exhibit } from "$lib/ae_events/ae_events__event_exhibit";
|
||||
import { load_ae_obj_id__event_file } from '$lib/ae_events/ae_events__event_file';
|
||||
import { load_ae_obj_id__event_location } from '$lib/ae_events/ae_events__event_location';
|
||||
import { load_ae_obj_id__event_presentation } from '$lib/ae_events/ae_events__event_presentation';
|
||||
import { load_ae_obj_id__event_presenter } from '$lib/ae_events/ae_events__event_presenter';
|
||||
import { load_ae_obj_id__event_session } from '$lib/ae_events/ae_events__event_session';
|
||||
|
||||
import { load_ae_obj_id__journal } from '$lib/ae_journals/ae_journals__journal';
|
||||
import { load_ae_obj_id__journal_entry } from '$lib/ae_journals/ae_journals__journal_entry';
|
||||
|
||||
import { load_ae_obj_id__post } from '$lib/ae_posts/ae_posts__post';
|
||||
import { load_ae_obj_id__post_comment } from '$lib/ae_posts/ae_posts__post_comment';
|
||||
|
||||
// Updated 2025-09-30
|
||||
async function update_ae_obj_id_crud_v2({
|
||||
api_cfg,
|
||||
object_type,
|
||||
object_id,
|
||||
object_reload = false,
|
||||
field_name,
|
||||
new_field_value,
|
||||
params = {},
|
||||
try_cache = false,
|
||||
log_lvl = 0
|
||||
}: {
|
||||
api_cfg: any;
|
||||
object_type: string;
|
||||
object_id: string;
|
||||
object_reload?: boolean;
|
||||
field_name: string;
|
||||
new_field_value: any;
|
||||
params?: any | key_val;
|
||||
try_cache?: boolean;
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
if (log_lvl) {
|
||||
console.log(
|
||||
`*** update_ae_obj_id_crud_v2() *** object_type=${object_type}, object_id=${object_id}, object_reload=${object_reload}, field_name=${field_name}, new_field_value=`,
|
||||
new_field_value
|
||||
);
|
||||
}
|
||||
let patch_result: any = null;
|
||||
|
||||
ae_promises.api_update__ae_obj = await api
|
||||
.update_ae_obj_id_crud({
|
||||
api_cfg: api_cfg,
|
||||
obj_type: object_type,
|
||||
obj_id: object_id,
|
||||
field_name: field_name,
|
||||
field_value: new_field_value,
|
||||
// fields: data,
|
||||
key: api_cfg.api_crud_super_key,
|
||||
// jwt: null,
|
||||
// params: params,
|
||||
// data: patch_data,
|
||||
log_lvl: log_lvl
|
||||
})
|
||||
.then(function (results) {
|
||||
console.log('PATCH Promise', results);
|
||||
|
||||
if (results) {
|
||||
console.log(
|
||||
`Patched - Field Name: ${field_name} with new Field Value: ${new_field_value}`
|
||||
);
|
||||
patch_result = 'PATCH complete';
|
||||
|
||||
if (object_reload) {
|
||||
if (log_lvl) {
|
||||
console.log(`Reloading the object after patching...`);
|
||||
}
|
||||
// Reload the object to get the latest data. There is a special case for each type.
|
||||
if (object_type == 'person') {
|
||||
const load_person_obj = load_ae_obj_id__person({
|
||||
api_cfg: api_cfg,
|
||||
person_id: object_id,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
return load_person_obj;
|
||||
}
|
||||
// if (object_type == 'user') {
|
||||
// let load_user_obj = load_ae_obj_id__user({
|
||||
// api_cfg: api_cfg,
|
||||
// user_id: object_id,
|
||||
// log_lvl: log_lvl
|
||||
// });
|
||||
// return load_user_obj;
|
||||
// }
|
||||
|
||||
if (object_type == 'archive') {
|
||||
const load_archive_obj = load_ae_obj_id__archive({
|
||||
api_cfg: api_cfg,
|
||||
archive_id: object_id,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
return load_archive_obj;
|
||||
}
|
||||
if (object_type == 'archive_content') {
|
||||
const load_archive_content_obj = load_ae_obj_id__archive_content({
|
||||
api_cfg: api_cfg,
|
||||
archive_content_id: object_id,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
return load_archive_content_obj;
|
||||
}
|
||||
|
||||
if (object_type == 'journal') {
|
||||
const load_journal_obj = load_ae_obj_id__journal({
|
||||
api_cfg: api_cfg,
|
||||
journal_id: object_id,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
return load_journal_obj;
|
||||
}
|
||||
if (object_type == 'journal_entry') {
|
||||
const load_journal_entry_obj = load_ae_obj_id__journal_entry({
|
||||
api_cfg: api_cfg,
|
||||
journal_entry_id: object_id,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
return load_journal_entry_obj;
|
||||
}
|
||||
|
||||
if (object_type == 'event') {
|
||||
const load_event_obj = load_ae_obj_id__event({
|
||||
api_cfg: api_cfg,
|
||||
event_id: object_id,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
return load_event_obj;
|
||||
}
|
||||
if (object_type == 'event_device') {
|
||||
const load_event_device_obj = load_ae_obj_id__event_device({
|
||||
api_cfg: api_cfg,
|
||||
event_device_id: object_id,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
return load_event_device_obj;
|
||||
}
|
||||
if (object_type == 'event_file') {
|
||||
const load_event_file_obj = load_ae_obj_id__event_file({
|
||||
api_cfg: api_cfg,
|
||||
event_file_id: object_id,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
return load_event_file_obj;
|
||||
}
|
||||
if (object_type == 'event_location') {
|
||||
const load_event_location_obj = load_ae_obj_id__event_location({
|
||||
api_cfg: api_cfg,
|
||||
event_location_id: object_id,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
return load_event_location_obj;
|
||||
}
|
||||
if (object_type == 'event_presentation') {
|
||||
const load_event_presentation_obj = load_ae_obj_id__event_presentation({
|
||||
api_cfg: api_cfg,
|
||||
event_presentation_id: object_id,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
return load_event_presentation_obj;
|
||||
}
|
||||
if (object_type == 'event_presenter') {
|
||||
const load_event_presenter_obj = load_ae_obj_id__event_presenter({
|
||||
api_cfg: api_cfg,
|
||||
event_presenter_id: object_id,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
return load_event_presenter_obj;
|
||||
}
|
||||
if (object_type == 'event_session') {
|
||||
const load_event_session_obj = load_ae_obj_id__event_session({
|
||||
api_cfg: api_cfg,
|
||||
event_session_id: object_id,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
return load_event_session_obj;
|
||||
}
|
||||
|
||||
if (object_type == 'post') {
|
||||
const load_post_obj = load_ae_obj_id__post({
|
||||
api_cfg: api_cfg,
|
||||
post_id: object_id,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
return load_post_obj;
|
||||
}
|
||||
if (object_type == 'post_comment') {
|
||||
const load_post_comment_obj = load_ae_obj_id__post_comment({
|
||||
api_cfg: api_cfg,
|
||||
post_comment_id: object_id,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
return load_post_comment_obj;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.log(
|
||||
`Not Patched - Field Name: ${field_name} with new Field Value: ${new_field_value}; Account ID: ${api_cfg.account_id}`
|
||||
);
|
||||
patch_result = 'PATCH failed';
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
})
|
||||
.catch(function (error: any) {
|
||||
console.log('Something went wrong patching the record.');
|
||||
console.log(error);
|
||||
return false;
|
||||
})
|
||||
.finally(function () {
|
||||
console.log('PATCH Promise finally');
|
||||
});
|
||||
|
||||
return ae_promises.api_update__ae_obj;
|
||||
}
|
||||
|
||||
async function download_export__obj_type({
|
||||
api_cfg,
|
||||
get_obj_type, // The type of object to return: event_badge, event_presenter, sponsorship, etc.
|
||||
for_obj_type, // Usually for an account, event, event_exhibit, or sponsorship_cfg
|
||||
for_obj_id, // The ID of the object
|
||||
exp_alt = null, // Export name (idaa, other, not 'default')
|
||||
file_type = 'CSV', // 'CSV' or 'Excel'
|
||||
return_file = true,
|
||||
filename = 'no_filename.csv',
|
||||
auto_download = false,
|
||||
limit = 5000,
|
||||
params = {}, // key value object is expected
|
||||
log_lvl = 0
|
||||
}: {
|
||||
api_cfg: any;
|
||||
get_obj_type: string;
|
||||
for_obj_type: string;
|
||||
for_obj_id: string;
|
||||
exp_alt?: null | string;
|
||||
file_type?: string;
|
||||
return_file?: boolean;
|
||||
filename?: string;
|
||||
auto_download?: boolean;
|
||||
limit?: number;
|
||||
params?: key_val;
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
console.log('*** ae_core_functions.js: download_export__obj_type() ***');
|
||||
|
||||
const task_id = for_obj_id;
|
||||
|
||||
const endpoint = `/v2/crud/${get_obj_type}/list`;
|
||||
params['for_obj_type'] = for_obj_type;
|
||||
params['for_obj_id'] = for_obj_id;
|
||||
|
||||
if (file_type == 'CSV' || file_type == 'Excel') {
|
||||
params['file_type'] = file_type;
|
||||
}
|
||||
params['return_file'] = true;
|
||||
|
||||
params['mdl_alt'] = 'out';
|
||||
|
||||
if (exp_alt) {
|
||||
params['exp_alt'] = exp_alt;
|
||||
}
|
||||
|
||||
// let clean_filename = filename.replace(/[^a-z0-9]/gi, '_');
|
||||
// let clean_filename = filename.replace(/[^a-z0-9\[\]-]/gi, '_');
|
||||
const clean_filename = filename.replace(/[^a-zA-Z0-9\[\]-_.]/gi, '_');
|
||||
// let clean_filename = filename.replace(/[^a-zA-Z0-9\[\]-\._ ]/gi, '_');
|
||||
|
||||
if (limit >= 0) {
|
||||
params['limit'] = limit;
|
||||
}
|
||||
|
||||
ae_promises.download__export_file = await api.get_object({
|
||||
api_cfg: api_cfg,
|
||||
endpoint: endpoint,
|
||||
params: params,
|
||||
timeout: 90000, // Seems to timeout sometimes with the default of 60 seconds
|
||||
return_blob: return_file,
|
||||
filename: clean_filename,
|
||||
auto_download: auto_download,
|
||||
task_id: task_id,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
|
||||
console.log('ae_promises.download__export_file:', ae_promises.download__export_file);
|
||||
return ae_promises.download__export_file;
|
||||
}
|
||||
|
||||
const export_obj = {
|
||||
check_hosted_file_obj_w_hash: check_hosted_file_obj_w_hash,
|
||||
|
||||
load_ae_obj_li__time_zone: load_ae_obj_li__time_zone,
|
||||
|
||||
load_ae_obj_li__country: load_ae_obj_li__country,
|
||||
load_ae_obj_li__country_subdivision: load_ae_obj_li__country_subdivision,
|
||||
|
||||
load_ae_obj_id__hosted_file: load_ae_obj_id__hosted_file,
|
||||
load_ae_obj_li__hosted_file: load_ae_obj_li__hosted_file,
|
||||
delete_ae_obj_id__hosted_file: delete_ae_obj_id__hosted_file,
|
||||
db_save_ae_obj_li__hosted_file: db_save_ae_obj_li__hosted_file,
|
||||
db_update_ae_obj_id__hosted_file: db_update_ae_obj_id__hosted_file,
|
||||
|
||||
db_save_ae_obj_li__ae_obj: db_save_ae_obj_li__ae_obj,
|
||||
|
||||
add_url_params: add_url_params,
|
||||
clean_headers: clean_headers,
|
||||
|
||||
load_ae_obj_id__site_domain: load_ae_obj_id__site_domain,
|
||||
load_ae_obj_code__data_store: load_ae_obj_code__data_store,
|
||||
|
||||
load_ae_obj_id__activity_log: load_ae_obj_id__activity_log,
|
||||
load_ae_obj_li__activity_log: load_ae_obj_li__activity_log,
|
||||
create_ae_obj__activity_log: create_ae_obj__activity_log,
|
||||
update_ae_obj__activity_log: update_ae_obj__activity_log,
|
||||
|
||||
load_ae_obj_id__person: load_ae_obj_id__person,
|
||||
load_ae_obj_li__person: load_ae_obj_li__person,
|
||||
create_ae_obj__person: create_ae_obj__person,
|
||||
delete_ae_obj_id__person: delete_ae_obj_id__person,
|
||||
update_ae_obj__person: update_ae_obj__person,
|
||||
|
||||
auth_ae_obj__username_password: auth_ae_obj__username_password,
|
||||
auth_ae_obj__user_id_user_auth_key: auth_ae_obj__user_id_user_auth_key,
|
||||
send_email_auth_ae_obj__user_id: send_email_auth_ae_obj__user_id,
|
||||
qry_ae_obj_li__user_email: qry_ae_obj_li__user_email,
|
||||
auth_ae_obj__user_id_change_password: auth_ae_obj__user_id_change_password,
|
||||
|
||||
update_ae_obj_id_crud: update_ae_obj_id_crud,
|
||||
update_ae_obj_id_crud_v2: update_ae_obj_id_crud_v2,
|
||||
download_export__obj_type: download_export__obj_type,
|
||||
generate_qr_code: generate_qr_code,
|
||||
js_generate_qr_code: js_generate_qr_code
|
||||
};
|
||||
export const core_func = export_obj;
|
||||
23
src/lib/ae_core/core__account.ts
Normal file
23
src/lib/ae_core/core__account.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
export interface Account {
|
||||
id: string;
|
||||
// id_random: string;
|
||||
account_id: string;
|
||||
account_id_random: string;
|
||||
|
||||
code?: string;
|
||||
name: string;
|
||||
short_name?: null | string;
|
||||
description?: null | string;
|
||||
|
||||
enable: null | boolean;
|
||||
enable_from?: null | Date;
|
||||
enable_to?: null | Date;
|
||||
|
||||
hide?: null | boolean;
|
||||
priority?: null | boolean;
|
||||
sort?: null | number;
|
||||
group?: null | string;
|
||||
notes?: null | string;
|
||||
created_on: Date;
|
||||
updated_on?: null | Date;
|
||||
}
|
||||
372
src/lib/ae_core/core__activity_log.ts
Normal file
372
src/lib/ae_core/core__activity_log.ts
Normal file
@@ -0,0 +1,372 @@
|
||||
import type { key_val } from '$lib/stores/ae_stores';
|
||||
import { api } from '$lib/api/api';
|
||||
|
||||
const ae_promises: key_val = {};
|
||||
|
||||
// Updated 2024-10-23
|
||||
export async function load_ae_obj_id__activity_log({
|
||||
api_cfg,
|
||||
activity_log_id,
|
||||
// inc_other_li = false,
|
||||
try_cache = false,
|
||||
log_lvl = 0
|
||||
}: {
|
||||
api_cfg: any;
|
||||
activity_log_id: string;
|
||||
// inc_other_li?: boolean,
|
||||
try_cache?: boolean;
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
console.log(`*** load_ae_obj_id__activity_log() *** activity_log_id=${activity_log_id}`);
|
||||
|
||||
const params = {};
|
||||
|
||||
ae_promises.load__activity_log_obj = await api
|
||||
.get_ae_obj_id_crud({
|
||||
api_cfg: api_cfg,
|
||||
obj_type: 'activity_log',
|
||||
obj_id: activity_log_id, // NOTE: This is the FQDN, not normally the ID.
|
||||
use_alt_table: true, // NOTE: This will use the table_name_alt value instead of the table_name value in the API config.
|
||||
use_alt_base: false, // NOTE: This will use the base_name_alt value instead of the base_name value in the API config.
|
||||
params: params,
|
||||
log_lvl: log_lvl
|
||||
})
|
||||
.then(function (activity_log_obj_get_result) {
|
||||
if (activity_log_obj_get_result) {
|
||||
// if (try_cache) {
|
||||
// // This is expecting a list
|
||||
// db_save_ae_obj_li__activity_log({
|
||||
// obj_type: 'activity_log',
|
||||
// obj_li: [activity_log_obj_get_result]
|
||||
// });
|
||||
// }
|
||||
return activity_log_obj_get_result;
|
||||
} else {
|
||||
console.log('No results returned.');
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.catch(function (error: any) {
|
||||
console.log('No results returned or failed.', error);
|
||||
});
|
||||
|
||||
if (log_lvl) {
|
||||
console.log('ae_promises.load__activity_log_obj:', ae_promises.load__activity_log_obj);
|
||||
}
|
||||
|
||||
return ae_promises.load__activity_log_obj;
|
||||
}
|
||||
|
||||
// Updated 2024-10-23
|
||||
export async function load_ae_obj_li__activity_log({
|
||||
api_cfg,
|
||||
for_obj_type = 'account',
|
||||
for_obj_id,
|
||||
// inc_other_li = false,
|
||||
order_by_li = {
|
||||
priority: 'DESC',
|
||||
sort: 'DESC',
|
||||
name: 'ASC',
|
||||
updated_on: 'DESC',
|
||||
created_on: 'DESC'
|
||||
},
|
||||
params = {},
|
||||
try_cache = false,
|
||||
log_lvl = 0
|
||||
}: {
|
||||
api_cfg: any;
|
||||
for_obj_type: string;
|
||||
for_obj_id: string;
|
||||
// inc_other_li?: boolean,
|
||||
order_by_li?: key_val;
|
||||
params?: key_val;
|
||||
try_cache?: boolean;
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
console.log(
|
||||
`*** load_ae_obj_li__activity_log() *** for_obj_type=${for_obj_type} for_obj_id=${for_obj_id}`
|
||||
);
|
||||
|
||||
const enabled: string = params.qry__enabled ?? 'enabled'; // all, disabled, enabled
|
||||
const hidden: string = params.qry__hidden ?? 'not_hidden'; // all, hidden, not_hidden
|
||||
const limit: number = params.qry__limit ?? 99; // 99
|
||||
const offset: number = params.qry__offset ?? 0; // 0
|
||||
|
||||
const params_json: key_val = {};
|
||||
|
||||
// console.log('params_json:', params_json);
|
||||
|
||||
ae_promises.load__activity_log_obj_li = await api
|
||||
.get_ae_obj_li_for_obj_id_crud({
|
||||
api_cfg: api_cfg,
|
||||
obj_type: 'activity_log',
|
||||
for_obj_type: for_obj_type,
|
||||
for_obj_id: for_obj_id,
|
||||
use_alt_table: true, // NOTE: This will use the table_name_alt value instead of the table_name value in the API config.
|
||||
use_alt_base: false, // NOTE: This will use the base_name_alt value instead of the base_name value
|
||||
enabled: enabled,
|
||||
hidden: hidden,
|
||||
order_by_li: order_by_li,
|
||||
limit: limit,
|
||||
offset: offset,
|
||||
params_json: params_json,
|
||||
params: params,
|
||||
log_lvl: log_lvl
|
||||
})
|
||||
.then(function (activity_log_obj_li_get_result) {
|
||||
if (activity_log_obj_li_get_result) {
|
||||
// if (try_cache) {
|
||||
// db_save_ae_obj_li__activity_log({
|
||||
// obj_type: 'activity_log',
|
||||
// obj_li: activity_log_obj_li_get_result
|
||||
// });
|
||||
// }
|
||||
return activity_log_obj_li_get_result;
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
})
|
||||
.catch(function (error: any) {
|
||||
console.log('No results returned or failed.', error);
|
||||
});
|
||||
|
||||
if (log_lvl) {
|
||||
console.log(
|
||||
'ae_promises.load__activity_log_obj_li:',
|
||||
ae_promises.load__activity_log_obj_li
|
||||
);
|
||||
}
|
||||
|
||||
return ae_promises.load__activity_log_obj_li;
|
||||
}
|
||||
|
||||
// Updated 2024-10-23
|
||||
export async function create_ae_obj__activity_log({
|
||||
api_cfg,
|
||||
account_id,
|
||||
data_kv,
|
||||
params = {},
|
||||
log_lvl = 0
|
||||
}: {
|
||||
api_cfg: any;
|
||||
account_id: string;
|
||||
data_kv: key_val;
|
||||
params?: key_val;
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
console.log(`*** create_ae_obj__activity_log() *** account_id=${account_id}`);
|
||||
|
||||
ae_promises.create__activity_log = await api
|
||||
.create_ae_obj_crud({
|
||||
api_cfg: api_cfg,
|
||||
obj_type: 'activity_log',
|
||||
fields: {
|
||||
account_id_random: account_id,
|
||||
...data_kv
|
||||
},
|
||||
key: api_cfg.api_crud_super_key,
|
||||
params: params,
|
||||
return_obj: true,
|
||||
log_lvl: log_lvl
|
||||
})
|
||||
.then(function (activity_log_obj_create_result) {
|
||||
if (activity_log_obj_create_result) {
|
||||
// db_save_ae_obj_li__activity_log(
|
||||
// {
|
||||
// obj_type: 'activity_log',
|
||||
// obj_li: [activity_log_obj_create_result]
|
||||
// });
|
||||
return activity_log_obj_create_result;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.catch(function (error: any) {
|
||||
console.log('No results returned or failed.', error);
|
||||
})
|
||||
.finally(function () {});
|
||||
|
||||
if (log_lvl) {
|
||||
console.log('ae_promises.create__activity_log:', ae_promises.create__activity_log);
|
||||
}
|
||||
return ae_promises.create__activity_log;
|
||||
}
|
||||
|
||||
// Updated 2024-10-23
|
||||
export async function update_ae_obj__activity_log({
|
||||
api_cfg,
|
||||
activity_log_id,
|
||||
data_kv,
|
||||
params = {},
|
||||
try_cache = false,
|
||||
log_lvl = 0
|
||||
}: {
|
||||
api_cfg: any;
|
||||
activity_log_id: string;
|
||||
data_kv: key_val;
|
||||
params?: key_val;
|
||||
try_cache?: boolean;
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
if (log_lvl) {
|
||||
console.log(
|
||||
`*** update_ae_obj__activity_log() *** activity_log_id=${activity_log_id}`,
|
||||
data_kv
|
||||
);
|
||||
}
|
||||
ae_promises.update__activity_log_obj = await api
|
||||
.update_ae_obj_id_crud({
|
||||
api_cfg: api_cfg,
|
||||
obj_type: 'activity_log',
|
||||
obj_id: activity_log_id,
|
||||
fields: data_kv,
|
||||
key: api_cfg.api_crud_super_key,
|
||||
params: params,
|
||||
return_obj: true,
|
||||
log_lvl: log_lvl
|
||||
})
|
||||
.then(function (activity_log_obj_update_result) {
|
||||
if (activity_log_obj_update_result) {
|
||||
// if (try_cache) {
|
||||
// db_save_ae_obj_li__activity_log({
|
||||
// obj_type: 'activity_log', obj_li: [activity_log_obj_update_result]
|
||||
// });
|
||||
// }
|
||||
return activity_log_obj_update_result;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.catch(function (error: any) {
|
||||
console.log('No results returned or failed.', error);
|
||||
})
|
||||
.finally(function () {});
|
||||
|
||||
if (log_lvl) {
|
||||
console.log('ae_promises.update__activity_log_obj:', ae_promises.update__activity_log_obj);
|
||||
}
|
||||
return ae_promises.update__activity_log_obj;
|
||||
}
|
||||
|
||||
// This new function is using CRUD v2. This should allow for more flexibility in the queries.
|
||||
// Updated 2024-10-23
|
||||
export async function qry__activity_log({
|
||||
api_cfg,
|
||||
activity_log_id,
|
||||
qry_str,
|
||||
qry_files,
|
||||
qry_start_datetime, // Example greater than: '2024-10-24'
|
||||
enabled = 'enabled',
|
||||
hidden = 'not_hidden',
|
||||
limit = 50,
|
||||
offset = 0,
|
||||
params = {},
|
||||
try_cache = false,
|
||||
log_lvl = 0
|
||||
}: {
|
||||
api_cfg: any;
|
||||
activity_log_id: any;
|
||||
qry_str?: string;
|
||||
qry_files?: null | boolean;
|
||||
qry_start_datetime?: null | string; // Greater than this datetime
|
||||
enabled?: 'enabled' | 'all' | 'not_enabled' | undefined; // all, disabled, enabled
|
||||
hidden?: 'hidden' | 'all' | 'not_hidden' | undefined; // all, hidden, not_hidden
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
params?: any;
|
||||
try_cache?: boolean;
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
console.log(
|
||||
`*** qry__activity_log() *** activity_log_id=${activity_log_id} qry_str=${qry_str}`
|
||||
);
|
||||
|
||||
// let enabled: string = (params.qry__enabled ?? 'enabled'); // all, disabled, enabled
|
||||
// let hidden: string = (params.qry__hidden ?? 'not_hidden'); // all, hidden, not_hidden
|
||||
// let limit: number = (params.qry__limit ?? 25); // 99
|
||||
// let offset: number = (params.qry__offset ?? 0); // 0
|
||||
|
||||
const params_json: key_val = {};
|
||||
|
||||
// if (qry_str && qry_str.length > 2) {
|
||||
// params_json['ft_qry'] = {};
|
||||
// params_json['ft_qry']['default_qry_str'] = qry_str;
|
||||
// }
|
||||
|
||||
params_json['qry'] = [];
|
||||
|
||||
if (qry_files === true) {
|
||||
const qry_param = {
|
||||
type: 'AND',
|
||||
field: 'file_count_all',
|
||||
operator: '>',
|
||||
value: 0
|
||||
};
|
||||
params_json['qry'].push(qry_param);
|
||||
} else if (qry_files === false) {
|
||||
const qry_param = {
|
||||
type: 'AND',
|
||||
field: 'file_count_all',
|
||||
operator: 'IS',
|
||||
value: null
|
||||
};
|
||||
params_json['qry'].push(qry_param);
|
||||
}
|
||||
|
||||
if (qry_start_datetime) {
|
||||
const qry_param = {
|
||||
type: 'AND',
|
||||
field: 'start_datetime',
|
||||
operator: '>',
|
||||
value: qry_start_datetime
|
||||
};
|
||||
params_json['qry'].push(qry_param);
|
||||
}
|
||||
|
||||
const order_by_li: { [key: string]: 'ASC' | 'DESC' }[] = [
|
||||
{ priority: 'DESC' },
|
||||
{ sort: 'DESC' },
|
||||
{ start_datetime: 'ASC' },
|
||||
{ name: 'ASC' },
|
||||
{ updated_on: 'DESC' },
|
||||
{ created_on: 'DESC' }
|
||||
];
|
||||
|
||||
ae_promises.load__activity_log_obj_li = await api
|
||||
.get_ae_obj_li_for_obj_id_crud_v2({
|
||||
api_cfg: api_cfg,
|
||||
obj_type: 'activity_log',
|
||||
for_obj_type: 'account',
|
||||
for_obj_id: activity_log_id,
|
||||
use_alt_tbl: true, // NOTE: We want to use the alt table for activity_log searching
|
||||
use_alt_mdl: false,
|
||||
use_alt_exp: false,
|
||||
enabled: enabled,
|
||||
hidden: hidden,
|
||||
order_by_li: order_by_li,
|
||||
limit: limit,
|
||||
offset: offset,
|
||||
params_json: params_json,
|
||||
params: params,
|
||||
log_lvl: log_lvl
|
||||
})
|
||||
.then(function (activity_log_obj_li_get_result) {
|
||||
if (activity_log_obj_li_get_result) {
|
||||
// db_save_ae_obj_li__activity_log({
|
||||
// obj_type: 'activity_log',
|
||||
// obj_li: activity_log_obj_li_get_result
|
||||
// });
|
||||
return activity_log_obj_li_get_result;
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
});
|
||||
|
||||
if (log_lvl) {
|
||||
console.log(
|
||||
'ae_promises.load__activity_log_obj_li:',
|
||||
ae_promises.load__activity_log_obj_li
|
||||
);
|
||||
}
|
||||
return ae_promises.load__activity_log_obj_li;
|
||||
}
|
||||
57
src/lib/ae_core/core__api_helpers.ts
Normal file
57
src/lib/ae_core/core__api_helpers.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
import type { key_val } from '$lib/stores/ae_stores';
|
||||
|
||||
// Updated 2025-01-28
|
||||
export function add_url_params({
|
||||
base_url = '',
|
||||
endpoint,
|
||||
params,
|
||||
log_lvl = 0
|
||||
}: {
|
||||
base_url?: string;
|
||||
endpoint: string;
|
||||
params: key_val;
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
if (log_lvl) {
|
||||
console.log(`*** add_url_params() *** base_url=${base_url} endpoint=${endpoint}`, params);
|
||||
}
|
||||
|
||||
const url_obj = new URL(endpoint, base_url);
|
||||
|
||||
Object.keys(params).forEach((key) => url_obj.searchParams.append(key, params[key]));
|
||||
|
||||
if (log_lvl) {
|
||||
console.log('New URL:', url_obj.toString());
|
||||
}
|
||||
|
||||
return url_obj.toString();
|
||||
// return 'test';
|
||||
}
|
||||
|
||||
// This is used to clean the header property names. Not underscores allowed in the header names.
|
||||
// Updated 2025-01-28
|
||||
export function clean_headers({ headers, log_lvl = 0 }: { headers: any; log_lvl?: number }) {
|
||||
if (log_lvl) {
|
||||
console.log(`*** clean_headers() ***`, headers);
|
||||
}
|
||||
|
||||
const headers_cleaned: key_val = {};
|
||||
for (const prop in headers) {
|
||||
const prop_cleaned = prop.replaceAll('_', '-');
|
||||
if (typeof headers[prop] != 'string') {
|
||||
headers[prop] = JSON.stringify(headers[prop]);
|
||||
}
|
||||
headers_cleaned[prop_cleaned] = headers[prop];
|
||||
if (log_lvl > 1) {
|
||||
console.log(`${prop_cleaned}: ${headers_cleaned[prop_cleaned]}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Object.keys(headers).forEach(key => {
|
||||
// if (headers[key]) {
|
||||
// headers_cleaned[key] = headers[key];
|
||||
// }
|
||||
// });
|
||||
|
||||
return headers_cleaned;
|
||||
}
|
||||
34
src/lib/ae_core/core__check_hosted_file_obj_w_hash.ts
Normal file
34
src/lib/ae_core/core__check_hosted_file_obj_w_hash.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import type { key_val } from '$lib/stores/ae_stores';
|
||||
import { api } from '$lib/api/api';
|
||||
|
||||
// Updated 2024-10-02
|
||||
export async function check_hosted_file_obj_w_hash({
|
||||
api_cfg,
|
||||
hosted_file_hash,
|
||||
check_for_local = true, // Forces a check on the host server for the file.
|
||||
params = {},
|
||||
return_meta = false,
|
||||
log_lvl = 0
|
||||
}: {
|
||||
api_cfg: any;
|
||||
hosted_file_hash: string;
|
||||
check_for_local?: boolean;
|
||||
params?: key_val;
|
||||
return_meta?: boolean;
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
console.log('*** stores_event_api.js: check_hosted_file_obj_w_hash() ***');
|
||||
|
||||
const endpoint = `/hosted_file/hash/${hosted_file_hash}`;
|
||||
if (check_for_local) {
|
||||
params['check_for_local'] = true;
|
||||
}
|
||||
const check_hosted_file_obj_w_hash_get_promise = await api.get_object({
|
||||
api_cfg: api_cfg,
|
||||
endpoint: endpoint,
|
||||
params: params,
|
||||
return_meta: return_meta,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
return check_hosted_file_obj_w_hash_get_promise;
|
||||
}
|
||||
71
src/lib/ae_core/core__countries.ts
Normal file
71
src/lib/ae_core/core__countries.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
import type { key_val } from '$lib/stores/ae_stores';
|
||||
import { api } from '$lib/api/api';
|
||||
|
||||
import { db_core } from '$lib/ae_core/db_core';
|
||||
|
||||
const ae_promises: key_val = {};
|
||||
|
||||
// Updated 2024-10-14
|
||||
export async function load_ae_obj_li__country({
|
||||
api_cfg,
|
||||
// account_id,
|
||||
enabled = 'enabled',
|
||||
hidden = 'not_hidden',
|
||||
limit = 299,
|
||||
offset = 0,
|
||||
order_by_li = { sort: 'DESC', english_short_name: 'ASC', alpha_2_code: 'ASC' },
|
||||
params = {},
|
||||
try_cache = true,
|
||||
log_lvl = 0
|
||||
}: {
|
||||
api_cfg: any;
|
||||
// account_id: string,
|
||||
enabled?: 'enabled' | 'all' | 'not_enabled' | undefined;
|
||||
hidden?: 'hidden' | 'all' | 'not_hidden' | undefined;
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
order_by_li?: key_val;
|
||||
params?: key_val;
|
||||
try_cache?: boolean;
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
if (log_lvl) {
|
||||
console.log(`*** load_ae_obj_li__country() ***`);
|
||||
}
|
||||
|
||||
const params_json: key_val = {};
|
||||
|
||||
// console.log('params_json:', params_json);
|
||||
|
||||
ae_promises.load__country_li = await api
|
||||
.get_ae_obj_li_for_obj_id_crud_v2({
|
||||
api_cfg: api_cfg,
|
||||
obj_type: 'lu',
|
||||
for_obj_type: 'country',
|
||||
// for_obj_id: account_id,
|
||||
use_alt_tbl: false,
|
||||
use_alt_mdl: false,
|
||||
enabled: enabled,
|
||||
hidden: hidden,
|
||||
order_by_li: order_by_li,
|
||||
limit: limit,
|
||||
offset: offset,
|
||||
params_json: params_json,
|
||||
params: params,
|
||||
log_lvl: log_lvl
|
||||
})
|
||||
.then(function (country_li_get_result) {
|
||||
if (country_li_get_result) {
|
||||
// handle_db_save_ae_obj_li__country({obj_type: 'country', obj_li: country_li_get_result});
|
||||
return country_li_get_result;
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
})
|
||||
.catch(function (error: any) {
|
||||
console.log('No results returned or failed.', error);
|
||||
});
|
||||
|
||||
console.log('ae_promises.load__country_li:', ae_promises.load__country_li);
|
||||
return ae_promises.load__country_li;
|
||||
}
|
||||
74
src/lib/ae_core/core__country_subdivisions.ts
Normal file
74
src/lib/ae_core/core__country_subdivisions.ts
Normal file
@@ -0,0 +1,74 @@
|
||||
import type { key_val } from '$lib/stores/ae_stores';
|
||||
import { api } from '$lib/api/api';
|
||||
|
||||
import { db_core } from '$lib/ae_core/db_core';
|
||||
|
||||
const ae_promises: key_val = {};
|
||||
|
||||
// Updated 2024-10-14
|
||||
export async function load_ae_obj_li__country_subdivision({
|
||||
api_cfg,
|
||||
// account_id,
|
||||
enabled = 'enabled',
|
||||
hidden = 'not_hidden',
|
||||
limit = 399,
|
||||
offset = 0,
|
||||
order_by_li = { sort: 'DESC', name: 'ASC', code: 'ASC' },
|
||||
params = {},
|
||||
try_cache = true,
|
||||
log_lvl = 0
|
||||
}: {
|
||||
api_cfg: any;
|
||||
// account_id: string,
|
||||
enabled?: 'enabled' | 'all' | 'not_enabled' | undefined;
|
||||
hidden?: 'hidden' | 'all' | 'not_hidden' | undefined;
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
order_by_li?: key_val;
|
||||
params?: key_val;
|
||||
try_cache?: boolean;
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
if (log_lvl) {
|
||||
console.log(`*** load_ae_obj_li__country_subdivision() ***`);
|
||||
}
|
||||
|
||||
const params_json: key_val = {};
|
||||
|
||||
// console.log('params_json:', params_json);
|
||||
|
||||
ae_promises.load__country_subdivision_li = await api
|
||||
.get_ae_obj_li_for_obj_id_crud_v2({
|
||||
api_cfg: api_cfg,
|
||||
obj_type: 'lu',
|
||||
for_obj_type: 'country_subdivision',
|
||||
// for_obj_id: account_id,
|
||||
use_alt_tbl: false,
|
||||
use_alt_mdl: false,
|
||||
enabled: enabled,
|
||||
hidden: hidden,
|
||||
order_by_li: order_by_li,
|
||||
limit: limit,
|
||||
offset: offset,
|
||||
params_json: params_json,
|
||||
params: params,
|
||||
log_lvl: log_lvl
|
||||
})
|
||||
.then(function (country_subdivision_li_get_result) {
|
||||
if (country_subdivision_li_get_result) {
|
||||
// handle_db_save_ae_obj_li__country_subdivision({obj_type: 'country_subdivision', obj_li: country_subdivision_li_get_result});
|
||||
return country_subdivision_li_get_result;
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
})
|
||||
.catch(function (error: any) {
|
||||
console.log('No results returned or failed.', error);
|
||||
});
|
||||
|
||||
console.log(
|
||||
'ae_promises.load__country_subdivision_li:',
|
||||
ae_promises.load__country_subdivision_li
|
||||
);
|
||||
return ae_promises.load__country_subdivision_li;
|
||||
}
|
||||
335
src/lib/ae_core/core__crud_generic.ts
Normal file
335
src/lib/ae_core/core__crud_generic.ts
Normal file
@@ -0,0 +1,335 @@
|
||||
import { marked } from 'marked';
|
||||
|
||||
import type { key_val } from '$lib/stores/ae_stores';
|
||||
import { api } from '$lib/api/api';
|
||||
|
||||
import { db_save_ae_obj_li__ae_obj } from '$lib/ae_core/core__idb_dexie';
|
||||
|
||||
// Define generic CRUD args
|
||||
export interface GenericCrudArgs {
|
||||
api_cfg: any;
|
||||
obj_type: string;
|
||||
obj_id?: string;
|
||||
for_obj_type?: string;
|
||||
for_obj_id?: string;
|
||||
|
||||
db_instance?: any; // Optional DB instance for caching
|
||||
db_field_li?: string[]; // Optional list of fields to save in DB
|
||||
|
||||
// Flags to include related core object models
|
||||
inc_account_li?: boolean;
|
||||
inc_address_li?: boolean;
|
||||
inc_contact_li?: boolean;
|
||||
inc_person_li?: boolean;
|
||||
inc_site_li?: boolean;
|
||||
inc_site_domain_li?: boolean;
|
||||
inc_user_li?: boolean;
|
||||
|
||||
// Flags to include related other object models
|
||||
inc_archive_li?: boolean;
|
||||
inc_archive_entry_li?: boolean;
|
||||
inc_event_li?: boolean;
|
||||
inc_event_session_li?: boolean;
|
||||
inc_post_li?: boolean;
|
||||
inc_post_comment_li?: boolean;
|
||||
inc_journal_li?: boolean;
|
||||
inc_journal_entry_li?: boolean;
|
||||
|
||||
inc_obj_type_li?: string[]; // Optional list of object types to include
|
||||
|
||||
data_kv?: key_val;
|
||||
enabled?: 'enabled' | 'disabled' | 'all';
|
||||
hidden?: 'not_hidden' | 'hidden' | 'all';
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
order_by_li?: key_val;
|
||||
params?: key_val;
|
||||
try_cache?: boolean;
|
||||
log_lvl?: number;
|
||||
}
|
||||
|
||||
// Generic function: Load single object by ID
|
||||
export async function load_ae_obj_id(args: GenericCrudArgs): Promise<any> {
|
||||
const { api_cfg, obj_type, obj_id, log_lvl = 0 } = args;
|
||||
|
||||
if (log_lvl) {
|
||||
console.log(`*** load_ae_obj_id() *** obj_type=${obj_type} obj_id=${obj_id}`);
|
||||
}
|
||||
|
||||
const result = await api.get_ae_obj_id_crud({
|
||||
api_cfg,
|
||||
obj_type,
|
||||
obj_id,
|
||||
params: {},
|
||||
log_lvl
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Generic function: Load list of objects
|
||||
export async function load_ae_obj_li(args: GenericCrudArgs): Promise<any> {
|
||||
const {
|
||||
api_cfg,
|
||||
obj_type,
|
||||
for_obj_type = '',
|
||||
for_obj_id,
|
||||
inc_obj_type_li,
|
||||
enabled = 'enabled',
|
||||
hidden = 'not_hidden',
|
||||
limit = 99,
|
||||
offset = 0,
|
||||
order_by_li = {},
|
||||
params = {},
|
||||
try_cache = true,
|
||||
log_lvl = 0
|
||||
} = args;
|
||||
|
||||
if (log_lvl) {
|
||||
console.log(
|
||||
`*** load_ae_obj_li() *** obj_type=${obj_type} for_obj_type=${for_obj_type} for_obj_id=${for_obj_id}`
|
||||
);
|
||||
}
|
||||
|
||||
const params_json: key_val = {};
|
||||
|
||||
const result = await api.get_ae_obj_li_for_obj_id_crud_v2({
|
||||
api_cfg,
|
||||
obj_type,
|
||||
for_obj_type,
|
||||
for_obj_id,
|
||||
enabled,
|
||||
hidden,
|
||||
order_by_li,
|
||||
limit,
|
||||
offset,
|
||||
params_json: {},
|
||||
params,
|
||||
log_lvl
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Generic function: Create object
|
||||
export async function create_ae_obj(args: GenericCrudArgs): Promise<any> {
|
||||
const { api_cfg, obj_type, data_kv, log_lvl = 0 } = args;
|
||||
|
||||
if (log_lvl) {
|
||||
console.log(`*** create_ae_obj() *** obj_type=${obj_type}`, data_kv);
|
||||
}
|
||||
|
||||
const result = await api.create_ae_obj_crud({
|
||||
api_cfg,
|
||||
obj_type,
|
||||
fields: data_kv,
|
||||
key: api_cfg.api_crud_super_key,
|
||||
params: {},
|
||||
return_obj: true,
|
||||
log_lvl
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Generic function: Update object
|
||||
export async function update_ae_obj(args: GenericCrudArgs): Promise<any> {
|
||||
const { api_cfg, obj_type, obj_id, data_kv, log_lvl = 0 } = args;
|
||||
|
||||
if (log_lvl) {
|
||||
console.log(`*** update_ae_obj() *** obj_type=${obj_type} obj_id=${obj_id}`, data_kv);
|
||||
}
|
||||
|
||||
const result = await api.update_ae_obj_id_crud({
|
||||
api_cfg,
|
||||
obj_type,
|
||||
obj_id,
|
||||
fields: data_kv,
|
||||
key: api_cfg.api_crud_super_key,
|
||||
params: {},
|
||||
return_obj: true,
|
||||
log_lvl
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Generic function: Delete object
|
||||
export async function delete_ae_obj_id(args: GenericCrudArgs): Promise<any> {
|
||||
const { api_cfg, obj_type, obj_id, method = 'delete', log_lvl = 0 } = args;
|
||||
|
||||
if (log_lvl) {
|
||||
console.log(`*** delete_ae_obj_id() *** obj_type=${obj_type} obj_id=${obj_id}`);
|
||||
}
|
||||
|
||||
const result = await api.delete_ae_obj_id_crud({
|
||||
api_cfg,
|
||||
obj_type,
|
||||
obj_id,
|
||||
key: api_cfg.api_crud_super_key,
|
||||
params: {},
|
||||
method,
|
||||
log_lvl
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Additional Modules that might be needed for reloads
|
||||
import { load_ae_obj_id__archive } from '$lib/ae_archives/ae_archives__archive';
|
||||
import { load_ae_obj_id__archive_content } from '$lib/ae_archives/ae_archives__archive_content';
|
||||
import { load_ae_obj_id__event } from '$lib/ae_events/ae_events__event';
|
||||
import { load_ae_obj_id__event_device } from '$lib/ae_events/ae_events__event_device';
|
||||
import { load_ae_obj_id__event_file } from '$lib/ae_events/ae_events__event_file';
|
||||
import { load_ae_obj_id__event_location } from '$lib/ae_events/ae_events__event_location';
|
||||
import { load_ae_obj_id__event_presentation } from '$lib/ae_events/ae_events__event_presentation';
|
||||
import { load_ae_obj_id__event_presenter } from '$lib/ae_events/ae_events__event_presenter';
|
||||
import { load_ae_obj_id__event_session } from '$lib/ae_events/ae_events__event_session';
|
||||
import { load_ae_obj_id__journal } from '$lib/ae_journals/ae_journals__journal';
|
||||
import { load_ae_obj_id__journal_entry } from '$lib/ae_journals/ae_journals__journal_entry';
|
||||
import { load_ae_obj_id__post } from '$lib/ae_posts/ae_posts__post';
|
||||
import { load_ae_obj_id__post_comment } from '$lib/ae_posts/ae_posts__post_comment';
|
||||
import { load_ae_obj_id__person } from '$lib/ae_core/core__person';
|
||||
|
||||
export async function update_ae_obj_id_crud_v2({
|
||||
api_cfg,
|
||||
object_type,
|
||||
object_id,
|
||||
object_reload = false,
|
||||
field_name,
|
||||
new_field_value,
|
||||
log_lvl = 0
|
||||
}: {
|
||||
api_cfg: any;
|
||||
object_type: string;
|
||||
object_id: string;
|
||||
object_reload?: boolean;
|
||||
field_name: string;
|
||||
new_field_value: any;
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
if (log_lvl) {
|
||||
console.log(
|
||||
`*** update_ae_obj_id_crud_v2() *** object_type=${object_type}, object_id=${object_id}, object_reload=${object_reload}, field_name=${field_name}, new_field_value=`,
|
||||
new_field_value
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
const results = await api.update_ae_obj_id_crud({
|
||||
api_cfg: api_cfg,
|
||||
obj_type: object_type,
|
||||
obj_id: object_id,
|
||||
field_name: field_name,
|
||||
field_value: new_field_value,
|
||||
key: api_cfg.api_crud_super_key,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
|
||||
if (!results) {
|
||||
console.log(
|
||||
`Not Patched - Field Name: ${field_name} with new Field Value: ${new_field_value}; Account ID: ${api_cfg.account_id}`
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
console.log(`Patched - Field Name: ${field_name} with new Field Value: ${new_field_value}`);
|
||||
|
||||
if (object_reload) {
|
||||
if (log_lvl) console.log(`Reloading the object after patching...`);
|
||||
|
||||
const reload_fns: { [key: string]: (args: any) => Promise<any> } = {
|
||||
person: load_ae_obj_id__person,
|
||||
archive: load_ae_obj_id__archive,
|
||||
archive_content: load_ae_obj_id__archive_content,
|
||||
journal: load_ae_obj_id__journal,
|
||||
journal_entry: load_ae_obj_id__journal_entry,
|
||||
event: load_ae_obj_id__event,
|
||||
event_device: load_ae_obj_id__event_device,
|
||||
event_file: load_ae_obj_id__event_file,
|
||||
event_location: load_ae_obj_id__event_location,
|
||||
event_presentation: load_ae_obj_id__event_presentation,
|
||||
event_presenter: load_ae_obj_id__event_presenter,
|
||||
event_session: load_ae_obj_id__event_session,
|
||||
post: load_ae_obj_id__post,
|
||||
post_comment: load_ae_obj_id__post_comment
|
||||
};
|
||||
|
||||
const reload_fn = reload_fns[object_type];
|
||||
if (reload_fn) {
|
||||
const id_key = `${object_type}_id`;
|
||||
return await reload_fn({ api_cfg, [id_key]: object_id, log_lvl });
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.log('Something went wrong patching the record.', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export async function download_export_li({
|
||||
api_cfg,
|
||||
get_obj_type,
|
||||
for_obj_type,
|
||||
for_obj_id,
|
||||
exp_alt = null,
|
||||
file_type = 'CSV',
|
||||
return_file = true,
|
||||
filename = 'no_filename.csv',
|
||||
auto_download = false,
|
||||
limit = 5000,
|
||||
params = {},
|
||||
log_lvl = 0
|
||||
}: {
|
||||
api_cfg: any;
|
||||
get_obj_type: string;
|
||||
for_obj_type: string;
|
||||
for_obj_id: string;
|
||||
exp_alt?: null | string;
|
||||
file_type?: string;
|
||||
return_file?: boolean;
|
||||
filename?: string;
|
||||
auto_download?: boolean;
|
||||
limit?: number;
|
||||
params?: key_val;
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
if (log_lvl) console.log('*** download_export_li() ***');
|
||||
|
||||
const endpoint = `/v2/crud/${get_obj_type}/list`;
|
||||
params['for_obj_type'] = for_obj_type;
|
||||
params['for_obj_id'] = for_obj_id;
|
||||
|
||||
if (file_type === 'CSV' || file_type === 'Excel') {
|
||||
params['file_type'] = file_type;
|
||||
}
|
||||
params['return_file'] = true;
|
||||
params['mdl_alt'] = 'out';
|
||||
|
||||
if (exp_alt) {
|
||||
params['exp_alt'] = exp_alt;
|
||||
}
|
||||
|
||||
const clean_filename = filename.replace(/[^a-zA-Z0-9\[\]-_.]/gi, '_');
|
||||
|
||||
if (limit >= 0) {
|
||||
params['limit'] = limit;
|
||||
}
|
||||
|
||||
const download_result = await api.get_object({
|
||||
api_cfg: api_cfg,
|
||||
endpoint: endpoint,
|
||||
params: params,
|
||||
timeout: 90000,
|
||||
return_blob: return_file,
|
||||
filename: clean_filename,
|
||||
auto_download: auto_download,
|
||||
task_id: for_obj_id,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
|
||||
if (log_lvl) console.log('download_result:', download_result);
|
||||
return download_result;
|
||||
}
|
||||
112
src/lib/ae_core/core__data_store.ts
Normal file
112
src/lib/ae_core/core__data_store.ts
Normal file
@@ -0,0 +1,112 @@
|
||||
import { browser } from '$app/environment';
|
||||
import type { key_val } from '$lib/stores/ae_stores';
|
||||
import { api } from '$lib/api/api';
|
||||
|
||||
export interface Data_Store {
|
||||
id: string;
|
||||
account_id: string;
|
||||
code: string;
|
||||
name: string;
|
||||
type: string;
|
||||
for_type?: string | null;
|
||||
for_id?: string | null;
|
||||
access_read?: string | null;
|
||||
access_write?: string | null;
|
||||
access_delete?: string | null;
|
||||
html?: string | null;
|
||||
json?: key_val | null;
|
||||
md?: string | null;
|
||||
text?: string | null;
|
||||
updated_on?: string | null;
|
||||
chk_account_id?: string;
|
||||
loaded_on?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches a data_store object by its unique code.
|
||||
*
|
||||
* @param api_cfg - The API configuration object.
|
||||
* @param code - The code of the data store to fetch.
|
||||
* @param data_type - The expected data type ('text', 'json', 'html', 'md', 'sql').
|
||||
* @param save_idb - Whether to save the fetched data to localStorage.
|
||||
* @param timeout - The request timeout in milliseconds.
|
||||
* @param log_lvl - The logging level.
|
||||
* @returns The data from the data store (e.g., text content or JSON object).
|
||||
*/
|
||||
export async function load_ae_obj_by_code__data_store({
|
||||
api_cfg,
|
||||
code,
|
||||
data_type = 'text',
|
||||
save_idb = false,
|
||||
timeout = 9000,
|
||||
log_lvl = 0
|
||||
}: {
|
||||
api_cfg: any;
|
||||
code: string;
|
||||
data_type?: string;
|
||||
save_idb?: boolean;
|
||||
timeout?: number;
|
||||
log_lvl?: number;
|
||||
}): Promise<any> {
|
||||
if (log_lvl) {
|
||||
console.log(`*** load_ae_obj_by_code__data_store() *** code=${code}`);
|
||||
}
|
||||
|
||||
if (!code) {
|
||||
console.log(`*ae_func* No code provided!`);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!api_cfg.account_id) {
|
||||
console.log(`*ae_func* No account_id found in API config!`);
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
const get_ds_result = await api.get_data_store_obj_w_code({
|
||||
api_cfg: api_cfg,
|
||||
data_store_code: code,
|
||||
data_type: data_type,
|
||||
timeout: timeout,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
|
||||
if (!get_ds_result) {
|
||||
console.log('*ae_func* No results returned.');
|
||||
return null;
|
||||
}
|
||||
|
||||
if (log_lvl) {
|
||||
console.log(`*ae_func* Got a result for code ${code}`);
|
||||
}
|
||||
|
||||
if (!get_ds_result.data_store_id_random) {
|
||||
console.log('*ae_func* Something went wrong? No data store ID found.');
|
||||
return null;
|
||||
}
|
||||
|
||||
let return_this: any = null;
|
||||
|
||||
// Simplified data extraction
|
||||
if (data_type === 'html') {
|
||||
return_this = get_ds_result.html;
|
||||
} else if (data_type === 'json') {
|
||||
return_this = get_ds_result.json;
|
||||
} else {
|
||||
return_this = get_ds_result.text;
|
||||
}
|
||||
|
||||
if (save_idb && browser) {
|
||||
const key_prefix = 'ae_ds__';
|
||||
if (log_lvl) {
|
||||
console.log(`*ae_func* localStorage key: ${code}, value:`, get_ds_result);
|
||||
}
|
||||
localStorage.setItem(`${key_prefix}${code}`, JSON.stringify(get_ds_result));
|
||||
}
|
||||
|
||||
return return_this;
|
||||
} catch (error) {
|
||||
console.log('*ae_func* No results returned or failed.', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
362
src/lib/ae_core/core__hosted_files.ts
Normal file
362
src/lib/ae_core/core__hosted_files.ts
Normal file
@@ -0,0 +1,362 @@
|
||||
import type { key_val } from '$lib/stores/ae_stores';
|
||||
import { api } from '$lib/api/api';
|
||||
|
||||
import { db_core } from '$lib/ae_core/db_core';
|
||||
|
||||
const ae_promises: key_val = {};
|
||||
|
||||
// Updated 2024-06-14
|
||||
export async function load_ae_obj_id__hosted_file({
|
||||
api_cfg,
|
||||
hosted_file_id,
|
||||
try_cache = false,
|
||||
log_lvl = 0
|
||||
}: {
|
||||
api_cfg: any;
|
||||
hosted_file_id: string;
|
||||
try_cache?: boolean;
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
if (log_lvl) {
|
||||
console.log(`*** load_ae_obj_id__hosted_file() *** hosted_file_id=${hosted_file_id}`);
|
||||
}
|
||||
|
||||
const params = {};
|
||||
|
||||
ae_promises.load__hosted_file_obj = await api
|
||||
.get_ae_obj_id_crud({
|
||||
api_cfg: api_cfg,
|
||||
obj_type: 'hosted_file',
|
||||
obj_id: hosted_file_id, // NOTE: This is the FQDN, not normally the ID.
|
||||
use_alt_table: false, // NOTE: This will use the table_name_alt value instead of the table_name value in the API config.
|
||||
use_alt_base: false, // NOTE: This will use the base_name_alt value instead of the base_name value
|
||||
params: params,
|
||||
log_lvl: log_lvl
|
||||
})
|
||||
.then(function (hosted_file_obj_get_result) {
|
||||
if (hosted_file_obj_get_result) {
|
||||
// This is expecting a list
|
||||
db_save_ae_obj_li__hosted_file({
|
||||
obj_type: 'hosted_file',
|
||||
obj_li: [hosted_file_obj_get_result]
|
||||
});
|
||||
return hosted_file_obj_get_result;
|
||||
} else {
|
||||
console.log('No results returned.');
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.catch(function (error: any) {
|
||||
console.log('No results returned or failed.', error);
|
||||
});
|
||||
|
||||
return ae_promises.load__hosted_file_obj;
|
||||
}
|
||||
|
||||
// Updated 2024-07-03
|
||||
export async function load_ae_obj_li__hosted_file({
|
||||
api_cfg,
|
||||
for_obj_type,
|
||||
for_obj_id,
|
||||
enabled = 'enabled',
|
||||
hidden = 'not_hidden',
|
||||
limit = 99,
|
||||
offset = 0,
|
||||
order_by_li = { priority: 'DESC', sort: 'DESC', updated_on: 'DESC', created_on: 'DESC' },
|
||||
params = {},
|
||||
try_cache = true,
|
||||
log_lvl = 0
|
||||
}: {
|
||||
api_cfg: any;
|
||||
for_obj_type: string;
|
||||
for_obj_id: string;
|
||||
enabled?: 'enabled' | 'all' | 'not_enabled' | undefined;
|
||||
hidden?: 'hidden' | 'all' | 'not_hidden' | undefined;
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
order_by_li?: key_val;
|
||||
params?: key_val;
|
||||
try_cache?: boolean;
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
if (log_lvl) {
|
||||
console.log(
|
||||
`*** load_ae_obj_li__hosted_file() *** for_obj_type=${for_obj_type} for_obj_id=${for_obj_id}`
|
||||
);
|
||||
}
|
||||
|
||||
// Check if for_obj_type is in the list of valid Aether object types:
|
||||
const valid_for_obj_types = [
|
||||
'account',
|
||||
'archive',
|
||||
'archive_content',
|
||||
'event',
|
||||
'event_session',
|
||||
'event_presentation',
|
||||
'event_presenter',
|
||||
'event_location',
|
||||
'journal',
|
||||
'journal_entry',
|
||||
'post',
|
||||
'post_comment'
|
||||
];
|
||||
if (!valid_for_obj_types.includes(for_obj_type)) {
|
||||
console.log(`Invalid for_obj_type: ${for_obj_type}`);
|
||||
return [];
|
||||
}
|
||||
|
||||
// let enabled: string = (params.qry__enabled ?? 'enabled'); // all, disabled, enabled
|
||||
// let hidden: string = (params.qry__hidden ?? 'all'); // all, hidden, not_hidden
|
||||
// let limit: number = (params.qry__limit ?? 99); // 99
|
||||
// let offset: number = (params.qry__offset ?? 0); // 0
|
||||
|
||||
const params_json: key_val = {};
|
||||
|
||||
// console.log('params_json:', params_json);
|
||||
|
||||
ae_promises.load__hosted_file_obj_li = await api
|
||||
.get_ae_obj_li_for_obj_id_crud_v2({
|
||||
api_cfg: api_cfg,
|
||||
obj_type: 'hosted_file',
|
||||
for_obj_type: for_obj_type,
|
||||
for_obj_id: for_obj_id,
|
||||
use_alt_tbl: false,
|
||||
use_alt_mdl: false,
|
||||
use_alt_exp: false,
|
||||
enabled: enabled,
|
||||
hidden: hidden,
|
||||
order_by_li: order_by_li,
|
||||
limit: limit,
|
||||
offset: offset,
|
||||
params_json: params_json,
|
||||
params: params,
|
||||
log_lvl: log_lvl
|
||||
})
|
||||
.then(function (hosted_file_obj_li_get_result) {
|
||||
if (hosted_file_obj_li_get_result) {
|
||||
if (try_cache) {
|
||||
db_save_ae_obj_li__hosted_file({
|
||||
obj_type: 'hosted_file',
|
||||
obj_li: hosted_file_obj_li_get_result,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
}
|
||||
return hosted_file_obj_li_get_result;
|
||||
} else {
|
||||
console.log('No results returned.');
|
||||
return [];
|
||||
}
|
||||
})
|
||||
.catch(function (error: any) {
|
||||
console.log('No results returned or failed.', error);
|
||||
});
|
||||
|
||||
if (log_lvl) {
|
||||
console.log('ae_promises.load__hosted_file_obj_li:', ae_promises.load__hosted_file_obj_li);
|
||||
}
|
||||
return ae_promises.load__hosted_file_obj_li;
|
||||
}
|
||||
|
||||
// Updated 2024-11-07
|
||||
export async function delete_ae_obj_id__hosted_file({
|
||||
api_cfg,
|
||||
hosted_file_id,
|
||||
link_to_type, // Ideally this should be required...
|
||||
link_to_id, // Ideally this should be required...
|
||||
rm_orphan = false,
|
||||
fake_delete = false, // Fake the delete result to "true"
|
||||
params = {},
|
||||
try_cache = true,
|
||||
log_lvl = 0
|
||||
}: {
|
||||
api_cfg: any;
|
||||
hosted_file_id: string;
|
||||
link_to_type: string;
|
||||
link_to_id: string;
|
||||
rm_orphan?: boolean;
|
||||
fake_delete?: boolean;
|
||||
params?: key_val;
|
||||
try_cache?: boolean;
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
if (log_lvl) {
|
||||
console.log(`*** delete_ae_obj_id__hosted_file() *** hosted_file_id=${hosted_file_id}`);
|
||||
}
|
||||
|
||||
const endpoint = `/hosted_file/${hosted_file_id}`;
|
||||
|
||||
params['link_to_type'] = link_to_type;
|
||||
params['link_to_id'] = link_to_id;
|
||||
params['rm_orphan'] = rm_orphan; // This is what actually allows the hosted file to be deleted from the server.
|
||||
if (log_lvl) {
|
||||
console.log(`delete_ae_obj_id__hosted_file() params=`, params);
|
||||
}
|
||||
|
||||
if (fake_delete) {
|
||||
console.log(`*** FAKE DELETE!!! ***`);
|
||||
ae_promises.delete__hosted_file_obj = true;
|
||||
return ae_promises.delete__hosted_file_obj;
|
||||
}
|
||||
|
||||
ae_promises.delete__hosted_file_obj = await api
|
||||
.delete_object({
|
||||
api_cfg: api_cfg,
|
||||
endpoint: endpoint,
|
||||
params: params,
|
||||
// return_meta: return_meta,
|
||||
log_lvl: log_lvl
|
||||
})
|
||||
.then(function (hosted_file_obj_li_get_result) {
|
||||
if (hosted_file_obj_li_get_result) {
|
||||
if (try_cache) {
|
||||
if (log_lvl) {
|
||||
console.log(
|
||||
`Attempting to remove IDB entry for hosted_file_id=${hosted_file_id}`
|
||||
);
|
||||
}
|
||||
db_core.file.delete(hosted_file_id); // Delete from the DB no matter what.
|
||||
}
|
||||
return hosted_file_obj_li_get_result;
|
||||
} else {
|
||||
console.log('No results returned.');
|
||||
return [];
|
||||
}
|
||||
})
|
||||
.catch(function (error: any) {
|
||||
console.log('No results returned or failed.', error);
|
||||
});
|
||||
|
||||
if (log_lvl) {
|
||||
console.log('ae_promises.delete__hosted_file_obj:', ae_promises.delete__hosted_file_obj);
|
||||
}
|
||||
|
||||
return ae_promises.delete__hosted_file_obj;
|
||||
}
|
||||
|
||||
// This function will loop through the hosted_file_obj_li and save each one to the DB.
|
||||
// Updated 2025-01-07
|
||||
export function db_save_ae_obj_li__hosted_file({
|
||||
obj_type,
|
||||
obj_li,
|
||||
log_lvl = 0
|
||||
}: {
|
||||
obj_type: string;
|
||||
obj_li: any;
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
if (log_lvl) {
|
||||
console.log(`*** db_save_ae_obj_li__hosted_file() ***`);
|
||||
}
|
||||
|
||||
if (obj_li && obj_li.length) {
|
||||
obj_li.forEach(async function (obj: any) {
|
||||
if (log_lvl) {
|
||||
console.log(`ae_obj ${obj_type}:`, obj);
|
||||
}
|
||||
|
||||
try {
|
||||
const id_random = await db_core.file.put({
|
||||
id: obj.hosted_file_id_random,
|
||||
id_random: obj.hosted_file_id_random,
|
||||
hosted_file_id: obj.hosted_file_id_random,
|
||||
hosted_file_id_random: obj.hosted_file_id_random,
|
||||
|
||||
hash_sha256: obj.hash_sha256, // Renamed with alias in FastAPI model
|
||||
|
||||
for_type: obj.for_type,
|
||||
for_id: obj.for_id_id_random,
|
||||
for_id_random: obj.for_id_random,
|
||||
|
||||
account_id: obj.account_id_random,
|
||||
|
||||
filename: obj.filename,
|
||||
extension: obj.extension,
|
||||
content_type: obj.content_type,
|
||||
size: obj.size,
|
||||
|
||||
enable: obj.enable,
|
||||
hide: obj.hide,
|
||||
// priority: obj.priority,
|
||||
// sort: obj.sort,
|
||||
group: obj.group,
|
||||
notes: obj.notes,
|
||||
created_on: obj.created_on,
|
||||
updated_on: obj.updated_on,
|
||||
|
||||
filename_no_ext: obj.filename_no_ext,
|
||||
filename_w_ext: obj.filename_w_ext
|
||||
});
|
||||
// console.log(`Put obj with ID: ${obj.hosted_file_id_random} or ${id_random}`);
|
||||
} catch (error) {
|
||||
const status = `Failed to put ${obj.hosted_file_id_random}: ${error}`;
|
||||
console.log(status);
|
||||
}
|
||||
|
||||
// const id_random = await db_core.file.put(obj);
|
||||
// console.log(`Put obj with ID: ${obj.hosted_file_id_random}`);
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Updated 2025-01-07
|
||||
export function db_update_ae_obj_id__hosted_file({
|
||||
obj_type,
|
||||
obj_id,
|
||||
data_kv,
|
||||
log_lvl = 0
|
||||
}: {
|
||||
obj_type: string;
|
||||
obj_id: string;
|
||||
data_kv: key_val;
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
if (log_lvl) {
|
||||
console.log(`*** db_update_ae_obj_id__hosted_file() ***`);
|
||||
}
|
||||
|
||||
if (obj_id) {
|
||||
console.log(`ae_obj ${obj_type}:`, obj_id);
|
||||
|
||||
try {
|
||||
// db_core.file.update(obj_id, data_kv);
|
||||
db_core.file.update(obj_id, {
|
||||
// for_type: data_kv.for_type,
|
||||
// for_id: data_kv.for_id_id_random,
|
||||
// for_id_random: data_kv.for_id_random,
|
||||
|
||||
filename: data_kv.filename,
|
||||
extension: data_kv.extension,
|
||||
content_type: data_kv.content_type,
|
||||
size: data_kv.size,
|
||||
|
||||
// enable: data_kv.enable,
|
||||
// hide: data_kv.hide,
|
||||
// priority: data_kv.priority,
|
||||
// sort: data_kv.sort,
|
||||
// group: data_kv.group,
|
||||
// notes: data_kv.notes,
|
||||
// created_on: data_kv.created_on,
|
||||
// updated_on: data_kv.updated_on,
|
||||
|
||||
filename_no_ext: data_kv.filename_no_ext,
|
||||
filename_w_ext: data_kv.filename_w_ext
|
||||
// hosted_file_content_type: data_kv.hosted_file_content_type,
|
||||
// file_size: data_kv.file_size,
|
||||
// hosted_file_size: data_kv.hosted_file_size,
|
||||
});
|
||||
|
||||
console.log(`Update obj with ID: ${obj_id}`);
|
||||
} catch (error) {
|
||||
const status = `Failed to update ${obj_id}: ${error}`;
|
||||
console.log(status);
|
||||
}
|
||||
|
||||
// const id_random = await db_core.file.put(obj);
|
||||
// console.log(`Put obj with ID: ${data_kv.hosted_file_id_random}`);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
123
src/lib/ae_core/core__idb_dexie.ts
Normal file
123
src/lib/ae_core/core__idb_dexie.ts
Normal file
@@ -0,0 +1,123 @@
|
||||
import type { Dexie, Table } from 'dexie';
|
||||
|
||||
/**
|
||||
* Extracts the primary key from an object using a prioritized list of possible key names.
|
||||
* @param obj The object to extract the ID from.
|
||||
* @param table_name The name of the table, used to construct legacy key names.
|
||||
* @param log_lvl The logging level.
|
||||
* @returns The found ID, or undefined if no ID could be found.
|
||||
*/
|
||||
function find_object_id(
|
||||
obj: any,
|
||||
table_name: string,
|
||||
log_lvl: number
|
||||
): string | number | undefined {
|
||||
const potential_keys = ['id', `${table_name}_id`, `${table_name}_id_random`];
|
||||
|
||||
for (const key of potential_keys) {
|
||||
if (obj[key]) {
|
||||
if (key !== 'id' && log_lvl > 0) {
|
||||
console.warn(
|
||||
`Found legacy ID key "${key}" for table "${table_name}". Consider standardizing to "id".`,
|
||||
obj
|
||||
);
|
||||
}
|
||||
return obj[key];
|
||||
}
|
||||
}
|
||||
|
||||
console.error(
|
||||
`Object is missing a valid ID for table "${table_name}". It will be skipped.`,
|
||||
obj
|
||||
);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves an array of objects to a Dexie database table using bulkPut.
|
||||
* This function handles both creating new records and updating existing ones.
|
||||
*
|
||||
* @param db_instance The Dexie database instance.
|
||||
* @param table_name The name of the table in the database.
|
||||
* @param obj_li The array of objects to save.
|
||||
* @param properties_to_save The list of property names to include in the saved object.
|
||||
* @param log_lvl The logging level for debugging.
|
||||
* @returns A promise that resolves with the keys of the saved objects.
|
||||
* @throws An error if the database operation fails.
|
||||
*
|
||||
* @version 2.0.0
|
||||
* @since 2025-11-13
|
||||
*/
|
||||
export async function db_save_ae_obj_li__ae_obj<T extends Record<string, any>>({
|
||||
db_instance,
|
||||
table_name,
|
||||
obj_li,
|
||||
properties_to_save,
|
||||
log_lvl = 0
|
||||
}: {
|
||||
db_instance: Dexie;
|
||||
table_name: string;
|
||||
obj_li: T[];
|
||||
properties_to_save: (keyof T)[];
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
if (log_lvl > 0) {
|
||||
console.log(
|
||||
`*** db_save_ae_obj_li__ae_obj: Attempting to save ${obj_li.length} objects to table "${table_name}" ***`
|
||||
);
|
||||
}
|
||||
|
||||
if (!obj_li || obj_li.length === 0) {
|
||||
if (log_lvl > 0) console.log('No objects to save.');
|
||||
return [];
|
||||
}
|
||||
|
||||
const db_table: Table<T> = db_instance.table(table_name);
|
||||
if (!db_table) {
|
||||
const error_msg = `Table not found in Dexie instance: ${table_name}`;
|
||||
console.error(error_msg);
|
||||
throw new Error(error_msg);
|
||||
}
|
||||
|
||||
const data_to_save = obj_li
|
||||
.map((obj) => {
|
||||
const record: Partial<T> = {};
|
||||
|
||||
// Extract only the specified properties to save.
|
||||
for (const prop of properties_to_save) {
|
||||
record[prop] = obj[prop];
|
||||
}
|
||||
|
||||
// Ensure the primary key is included, attempting to find it from various legacy keys.
|
||||
const id = find_object_id(obj, table_name, log_lvl);
|
||||
|
||||
if (id === undefined) {
|
||||
return null; // Skip objects without a valid ID.
|
||||
}
|
||||
|
||||
const primary_key_name = db_table.schema.primKey.name;
|
||||
(record as any)[primary_key_name] = id;
|
||||
return record;
|
||||
})
|
||||
.filter(Boolean) as T[];
|
||||
|
||||
if (data_to_save.length === 0) {
|
||||
if (log_lvl > 0) {
|
||||
console.warn('All objects were skipped, likely due to missing IDs.');
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
try {
|
||||
// bulkPut efficiently handles both inserts and updates.
|
||||
const keys = await db_table.bulkPut(data_to_save);
|
||||
if (log_lvl > 0) {
|
||||
console.log(`Successfully saved ${keys.length} objects to "${table_name}".`);
|
||||
}
|
||||
return keys;
|
||||
} catch (error) {
|
||||
console.error(`Failed to save objects to "${table_name}":`, error);
|
||||
// Re-throw the error to let the caller handle it.
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
736
src/lib/ae_core/core__person.ts
Normal file
736
src/lib/ae_core/core__person.ts
Normal file
@@ -0,0 +1,736 @@
|
||||
import type { key_val } from '$lib/stores/ae_stores';
|
||||
import { api } from '$lib/api/api';
|
||||
|
||||
import { db_save_ae_obj_li__ae_obj } from '$lib/ae_core/core__idb_dexie';
|
||||
import { db_core } from '$lib/ae_core/db_core';
|
||||
|
||||
const ae_promises: key_val = {};
|
||||
|
||||
// Updated 2025-06-10
|
||||
export async function load_ae_obj_id__person({
|
||||
api_cfg,
|
||||
person_id,
|
||||
params = {},
|
||||
try_cache = false,
|
||||
log_lvl = 0
|
||||
}: {
|
||||
api_cfg: any;
|
||||
person_id: string;
|
||||
params?: key_val;
|
||||
try_cache?: boolean;
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
if (log_lvl) {
|
||||
console.log(`*** load_ae_obj_id__person() *** person_id=${person_id}`);
|
||||
}
|
||||
|
||||
ae_promises.load__person_obj = await api
|
||||
.get_ae_obj_id_crud({
|
||||
api_cfg: api_cfg,
|
||||
obj_type: 'person',
|
||||
obj_id: person_id,
|
||||
use_alt_table: false,
|
||||
use_alt_base: false,
|
||||
params: params,
|
||||
log_lvl: log_lvl
|
||||
})
|
||||
.then(async function (person_obj_get_result) {
|
||||
if (person_obj_get_result) {
|
||||
if (try_cache) {
|
||||
// Process the results first
|
||||
const processed_obj_li = await process_ae_obj__person_props({
|
||||
obj_li: [person_obj_get_result],
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
if (log_lvl) {
|
||||
console.log('Processed object list:', processed_obj_li);
|
||||
}
|
||||
// Save the updated results list to the database
|
||||
if (log_lvl) {
|
||||
console.log('Saving to DB...');
|
||||
}
|
||||
await db_save_ae_obj_li__ae_obj({
|
||||
db_instance: db_core,
|
||||
table_name: 'person',
|
||||
obj_li: processed_obj_li,
|
||||
properties_to_save: properties_to_save,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
if (log_lvl) {
|
||||
console.log('DB save completed.');
|
||||
}
|
||||
|
||||
// // This is expecting a list
|
||||
// db_save_ae_obj_li__person({
|
||||
// obj_type: 'person',
|
||||
// obj_li: [person_obj_get_result],
|
||||
// log_lvl: log_lvl
|
||||
// });
|
||||
}
|
||||
return person_obj_get_result;
|
||||
} else {
|
||||
console.log('No results returned.');
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.catch(function (error: any) {
|
||||
console.log('No results returned or failed.', error);
|
||||
});
|
||||
|
||||
if (log_lvl) {
|
||||
console.log('ae_promises.load__person_obj:', ae_promises.load__person_obj);
|
||||
}
|
||||
|
||||
return ae_promises.load__person_obj;
|
||||
}
|
||||
|
||||
// Updated 2025-06-10
|
||||
export async function load_ae_obj_li__person({
|
||||
api_cfg,
|
||||
for_obj_type = 'account',
|
||||
for_obj_id,
|
||||
qry_email = null,
|
||||
qry_user_id = null,
|
||||
enabled = 'enabled',
|
||||
hidden = 'not_hidden',
|
||||
limit = 99,
|
||||
offset = 0,
|
||||
order_by_li = [
|
||||
{ family_name: 'ASC' },
|
||||
{ given_name: 'ASC' },
|
||||
{ updated_on: 'DESC' },
|
||||
{ created_on: 'DESC' }
|
||||
],
|
||||
// params_json = {},
|
||||
params = {},
|
||||
try_cache = true,
|
||||
log_lvl = 0
|
||||
}: {
|
||||
api_cfg: any;
|
||||
for_obj_type: string;
|
||||
for_obj_id: string;
|
||||
qry_email?: string | null;
|
||||
qry_user_id?: string | null;
|
||||
enabled?: 'enabled' | 'all' | 'not_enabled' | undefined; // all, disabled, enabled
|
||||
hidden?: 'hidden' | 'all' | 'not_hidden' | undefined; // all, hidden, not_hidden
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
order_by_li?: { [key: string]: 'ASC' | 'DESC' }[] | null;
|
||||
// params_json?: null|key_val,
|
||||
params?: key_val;
|
||||
try_cache?: boolean;
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
if (log_lvl) {
|
||||
console.log(
|
||||
`*** load_ae_obj_li__person() *** for_obj_type=${for_obj_type} for_obj_id=${for_obj_id} enabled=${enabled} hidden=${hidden} limit=${limit} offset=${offset}`
|
||||
);
|
||||
}
|
||||
|
||||
const params_json: key_val = {};
|
||||
|
||||
// console.log('params_json:', params_json);
|
||||
if (qry_user_id) {
|
||||
// params_json['and_qry'] = {};
|
||||
// params_json['and_qry']['user_id_random'] = qry_user_id;
|
||||
|
||||
params_json['qry'] = [];
|
||||
|
||||
const qry_param = {
|
||||
type: 'AND',
|
||||
field: 'user_id_random',
|
||||
operator: '=',
|
||||
value: qry_user_id
|
||||
};
|
||||
params_json['qry'].push(qry_param);
|
||||
}
|
||||
|
||||
if (log_lvl) {
|
||||
console.log('params_json:', params_json);
|
||||
}
|
||||
|
||||
ae_promises.load__person_obj_li = await api
|
||||
.get_ae_obj_li_for_obj_id_crud_v2({
|
||||
api_cfg: api_cfg,
|
||||
obj_type: 'person',
|
||||
for_obj_type: for_obj_type,
|
||||
for_obj_id: for_obj_id,
|
||||
use_alt_tbl: false,
|
||||
use_alt_mdl: false,
|
||||
use_alt_exp: false,
|
||||
enabled: enabled,
|
||||
hidden: hidden,
|
||||
order_by_li: order_by_li,
|
||||
limit: limit,
|
||||
offset: offset,
|
||||
params_json: params_json,
|
||||
params: params,
|
||||
log_lvl: log_lvl
|
||||
})
|
||||
.then(async function (person_obj_li_get_result) {
|
||||
if (person_obj_li_get_result) {
|
||||
if (try_cache) {
|
||||
// Process the results first
|
||||
const processed_obj_li = await process_ae_obj__person_props({
|
||||
obj_li: person_obj_li_get_result,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
if (log_lvl) {
|
||||
console.log('Processed object list:', processed_obj_li);
|
||||
}
|
||||
// Save the updated results list to the database
|
||||
if (log_lvl) {
|
||||
console.log('Saving to DB...');
|
||||
}
|
||||
await db_save_ae_obj_li__ae_obj({
|
||||
db_instance: db_core,
|
||||
table_name: 'person',
|
||||
obj_li: processed_obj_li,
|
||||
properties_to_save: properties_to_save,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
if (log_lvl) {
|
||||
console.log('DB save completed.');
|
||||
}
|
||||
|
||||
// db_save_ae_obj_li__person({
|
||||
// obj_type: 'person',
|
||||
// obj_li: person_obj_li_get_result,
|
||||
// log_lvl: log_lvl
|
||||
// });
|
||||
}
|
||||
return person_obj_li_get_result;
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
})
|
||||
.catch(function (error: any) {
|
||||
console.log('No results returned or failed.', error);
|
||||
});
|
||||
|
||||
console.log('ae_promises.load__person_obj_li:', ae_promises.load__person_obj_li);
|
||||
return ae_promises.load__person_obj_li;
|
||||
}
|
||||
|
||||
// Updated 2025-06-10
|
||||
export async function create_ae_obj__person({
|
||||
api_cfg,
|
||||
user_id,
|
||||
data_kv,
|
||||
params = {},
|
||||
try_cache = true,
|
||||
log_lvl = 0
|
||||
}: {
|
||||
api_cfg: any;
|
||||
user_id?: string;
|
||||
data_kv: key_val;
|
||||
params?: key_val;
|
||||
try_cache?: boolean;
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
if (log_lvl) {
|
||||
console.log(`*** create_ae_obj__person() *** user_id=${user_id}`);
|
||||
}
|
||||
|
||||
ae_promises.create__person = await api
|
||||
.create_ae_obj_crud({
|
||||
api_cfg: api_cfg,
|
||||
obj_type: 'person',
|
||||
fields: {
|
||||
user_id_random: user_id,
|
||||
...data_kv
|
||||
},
|
||||
key: api_cfg.api_crud_super_key,
|
||||
params: params,
|
||||
return_obj: true,
|
||||
log_lvl: log_lvl
|
||||
})
|
||||
.then(async function (person_obj_create_result) {
|
||||
if (person_obj_create_result) {
|
||||
if (try_cache) {
|
||||
// Process the results first
|
||||
const processed_obj_li = await process_ae_obj__person_props({
|
||||
obj_li: [person_obj_create_result],
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
if (log_lvl) {
|
||||
console.log('Processed object list:', processed_obj_li);
|
||||
}
|
||||
// Save the updated results list to the database
|
||||
if (log_lvl) {
|
||||
console.log('Saving to DB...');
|
||||
}
|
||||
await db_save_ae_obj_li__ae_obj({
|
||||
db_instance: db_core,
|
||||
table_name: 'person',
|
||||
obj_li: processed_obj_li,
|
||||
properties_to_save: properties_to_save,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
if (log_lvl) {
|
||||
console.log('DB save completed.');
|
||||
}
|
||||
|
||||
// db_save_ae_obj_li__person(
|
||||
// {
|
||||
// obj_type: 'person',
|
||||
// obj_li: [person_obj_create_result],
|
||||
// log_lvl: log_lvl
|
||||
// });
|
||||
}
|
||||
return person_obj_create_result;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.catch(function (error: any) {
|
||||
console.log('No results returned or failed.', error);
|
||||
})
|
||||
.finally(function () {});
|
||||
|
||||
if (log_lvl) {
|
||||
console.log('ae_promises.create__person:', ae_promises.create__person);
|
||||
}
|
||||
return ae_promises.create__person;
|
||||
}
|
||||
|
||||
// Updated 2025-05-10
|
||||
export async function delete_ae_obj_id__person({
|
||||
api_cfg,
|
||||
person_id,
|
||||
method = 'delete', // 'delete', 'disable', 'hide'
|
||||
params = {},
|
||||
try_cache = true,
|
||||
log_lvl = 0
|
||||
}: {
|
||||
api_cfg: any;
|
||||
person_id: string;
|
||||
method?: string;
|
||||
params?: key_val;
|
||||
try_cache?: boolean;
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
if (log_lvl) {
|
||||
console.log(`*** delete_ae_obj_id__person() *** person_id=${person_id}`);
|
||||
}
|
||||
|
||||
ae_promises.delete__person_obj = await api
|
||||
.delete_ae_obj_id_crud({
|
||||
api_cfg: api_cfg,
|
||||
obj_type: 'person',
|
||||
obj_id: person_id,
|
||||
key: api_cfg.api_crud_super_key,
|
||||
params: params,
|
||||
method: method,
|
||||
log_lvl: log_lvl
|
||||
})
|
||||
.catch(function (error: any) {
|
||||
console.log('No results returned or failed.', error);
|
||||
})
|
||||
.finally(async function () {
|
||||
if (try_cache) {
|
||||
if (log_lvl) {
|
||||
console.log(`Attempting to remove IDB entry for person_id=${person_id}`);
|
||||
}
|
||||
await db_core.person.delete(person_id);
|
||||
}
|
||||
});
|
||||
|
||||
if (log_lvl) {
|
||||
console.log('ae_promises.delete__person_obj:', ae_promises.delete__person_obj);
|
||||
}
|
||||
|
||||
return ae_promises.delete__person_obj;
|
||||
}
|
||||
|
||||
// Updated 2025-06-10
|
||||
export async function update_ae_obj__person({
|
||||
api_cfg,
|
||||
person_id,
|
||||
data_kv,
|
||||
params = {},
|
||||
try_cache = true,
|
||||
log_lvl = 0
|
||||
}: {
|
||||
api_cfg: any;
|
||||
person_id: string;
|
||||
data_kv: key_val;
|
||||
params?: key_val;
|
||||
try_cache?: boolean;
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
if (log_lvl) {
|
||||
console.log(`*** update_ae_obj__person() *** person_id=${person_id}`, data_kv);
|
||||
}
|
||||
|
||||
// log_lvl = 1;
|
||||
|
||||
// Perform the API update
|
||||
const result = await api.update_ae_obj_id_crud({
|
||||
api_cfg: api_cfg,
|
||||
obj_type: 'person',
|
||||
obj_id: person_id,
|
||||
fields: data_kv,
|
||||
key: api_cfg.api_crud_super_key,
|
||||
params: params,
|
||||
return_obj: true,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
|
||||
// Handle the result
|
||||
if (result) {
|
||||
if (try_cache) {
|
||||
// Process the results first
|
||||
const processed_obj_li = await process_ae_obj__person_props({
|
||||
obj_li: [result],
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
if (log_lvl) {
|
||||
console.log('Processed object list:', processed_obj_li);
|
||||
}
|
||||
// Save the updated results list to the database
|
||||
if (log_lvl) {
|
||||
console.log('Saving to DB...');
|
||||
}
|
||||
await db_save_ae_obj_li__ae_obj({
|
||||
db_instance: db_core,
|
||||
table_name: 'person',
|
||||
obj_li: processed_obj_li,
|
||||
properties_to_save: properties_to_save,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
if (log_lvl) {
|
||||
console.log('DB save completed.');
|
||||
}
|
||||
|
||||
// await db_save_ae_obj_li__person({
|
||||
// obj_type: 'person',
|
||||
// obj_li: [result],
|
||||
// log_lvl: log_lvl,
|
||||
// });
|
||||
}
|
||||
return result;
|
||||
} else {
|
||||
console.error('Failed to update person.');
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Updated 2024-06-10
|
||||
export function db_save_ae_obj_li__person({
|
||||
obj_type,
|
||||
obj_li,
|
||||
log_lvl = 0
|
||||
}: {
|
||||
obj_type: string;
|
||||
obj_li: any;
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
if (log_lvl) {
|
||||
console.log(`*** db_save_ae_obj_li__person() ***`);
|
||||
}
|
||||
|
||||
if (obj_li && obj_li.length) {
|
||||
obj_li.forEach(async function (obj: any) {
|
||||
if (log_lvl) {
|
||||
console.log(`ae_obj ${obj_type}:`, obj);
|
||||
}
|
||||
|
||||
const obj_record = {
|
||||
id: obj.person_id_random,
|
||||
// id_random: obj.person_id_random,
|
||||
person_id: obj.person_id_random,
|
||||
person_id_random: obj.person_id_random,
|
||||
|
||||
external_id: obj.external_id,
|
||||
external_sys_id: obj.external_sys_id,
|
||||
code: obj.code,
|
||||
|
||||
account_id: obj.account_id_random,
|
||||
account_id_random: obj.account_id_random,
|
||||
|
||||
person_profile_id: obj.person_profile_id_random,
|
||||
person_profile_id_random: obj.person_profile_id_random, // The new table person_profile will be used soon...
|
||||
|
||||
user_id: obj.user_id_random,
|
||||
user_id_random: obj.user_id_random,
|
||||
|
||||
pronouns: obj.pronouns,
|
||||
informal_name: obj.informal_name,
|
||||
title_names: obj.title_names,
|
||||
given_name: obj.given_name,
|
||||
middle_name: obj.middle_name,
|
||||
family_name: obj.family_name,
|
||||
designations: obj.designations,
|
||||
|
||||
professional_title: obj.professional_title,
|
||||
|
||||
full_name: obj.full_name,
|
||||
full_name_override: obj.full_name_override, // was display_name and display_name_override
|
||||
|
||||
affiliations: obj.affiliations,
|
||||
|
||||
primary_email: obj.primary_email,
|
||||
|
||||
biography: obj.biography,
|
||||
|
||||
agree: obj.agree,
|
||||
comments: obj.comments,
|
||||
|
||||
allow_auth_key: obj.allow_auth_key, // For sign in without password
|
||||
// auth_key: obj.auth_key,
|
||||
passcode: obj.passcode,
|
||||
|
||||
data_json: obj.data_json,
|
||||
|
||||
enable: obj.enable,
|
||||
hide: obj.hide,
|
||||
priority: obj.priority,
|
||||
sort: obj.sort,
|
||||
group: obj.group,
|
||||
notes: obj.notes,
|
||||
created_on: obj.created_on,
|
||||
updated_on: obj.updated_on,
|
||||
|
||||
// From SQL view
|
||||
username: obj.username,
|
||||
user_name: obj.user_name,
|
||||
user_email: obj.user_email,
|
||||
user_allow_auth_key: obj.user_allow_auth_key, // For sign in without password
|
||||
user_super: obj.user_super,
|
||||
user_manager: obj.user_manager,
|
||||
user_administrator: obj.user_administrator,
|
||||
user_public: obj.user_public
|
||||
};
|
||||
|
||||
let id_random = null;
|
||||
|
||||
try {
|
||||
id_random = await db_core.person.update(obj_record.id, obj_record);
|
||||
} catch (error) {
|
||||
console.log(`Error: Failed to update ${obj_record.id}: ${error}`);
|
||||
}
|
||||
if (!id_random) {
|
||||
if (log_lvl) {
|
||||
console.log(`Failed to update record with ID: ${obj_record.id}. Trying put...`);
|
||||
}
|
||||
try {
|
||||
id_random = await db_core.person.put(obj_record);
|
||||
} catch (error) {
|
||||
console.log(`Error: Failed to put ${obj.person_id_random}: ${error}`);
|
||||
}
|
||||
} else {
|
||||
if (log_lvl) {
|
||||
console.log(`Updated record with ID: ${obj_record.id}`);
|
||||
}
|
||||
}
|
||||
if (!id_random) {
|
||||
console.log(`Failed to save record with ID: ${obj_record.id}`);
|
||||
} else {
|
||||
if (log_lvl) {
|
||||
console.log(`Saved record with ID: ${obj_record.id}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Updated 2025-06-10
|
||||
const properties_to_save = [
|
||||
'id',
|
||||
'person_id',
|
||||
// 'person_id_random',
|
||||
|
||||
'external_id',
|
||||
'external_sys_id',
|
||||
'code',
|
||||
|
||||
'account_id',
|
||||
// 'account_id_random',
|
||||
|
||||
'person_profile_id',
|
||||
// 'person_profile_id_random', // The new table person_profile will be used soon...
|
||||
|
||||
'user_id',
|
||||
// 'user_id_random',
|
||||
|
||||
'pronouns',
|
||||
'informal_name',
|
||||
'title_names',
|
||||
'given_name',
|
||||
'middle_name',
|
||||
'family_name',
|
||||
'designations',
|
||||
|
||||
'professional_title',
|
||||
|
||||
'full_name',
|
||||
'full_name_override', // was display_name and display_name_override
|
||||
|
||||
'affiliations',
|
||||
'primary_email',
|
||||
'biography',
|
||||
'agree',
|
||||
'comments',
|
||||
|
||||
'allow_auth_key', // For sign in without password
|
||||
// 'auth_key', // Should this be saved locally?
|
||||
'passcode',
|
||||
|
||||
// 'passcode_timeout',
|
||||
// 'passcode_read', // For LLM (AI) generated summary...???
|
||||
// 'passcode_read_expire',
|
||||
// 'passcode_write',
|
||||
// 'passcode_write_expire',
|
||||
// 'private_passcode',
|
||||
|
||||
// 'alert',
|
||||
// 'alert_msg',
|
||||
|
||||
'data_json',
|
||||
|
||||
'enable',
|
||||
'hide',
|
||||
'priority',
|
||||
'sort',
|
||||
'group',
|
||||
'notes',
|
||||
'created_on',
|
||||
'updated_on',
|
||||
|
||||
// Generated fields for sorting locally only
|
||||
'tmp_sort_1',
|
||||
'tmp_sort_2',
|
||||
'tmp_sort_3',
|
||||
|
||||
// From SQL view
|
||||
'username',
|
||||
// 'user_username', // Same as username
|
||||
'user_name',
|
||||
'user_email',
|
||||
'user_allow_auth_key', // For sign in without password
|
||||
'user_super',
|
||||
'user_manager',
|
||||
'user_administrator',
|
||||
'user_public',
|
||||
|
||||
'organization_id',
|
||||
// 'organization_id_random',
|
||||
'organization_name',
|
||||
|
||||
'contact_id',
|
||||
// 'contact_id_random',
|
||||
'contact_name',
|
||||
'contact_email',
|
||||
'contact_cc_email',
|
||||
'contact_phone_mobile',
|
||||
'contact_phone_home',
|
||||
'contact_phone_office',
|
||||
'contact_phone_land',
|
||||
'contact_phone_fax',
|
||||
'contact_phone_other',
|
||||
|
||||
'address_id',
|
||||
// 'address_id_random',
|
||||
'address_city',
|
||||
'address_country_alpha_2_code' // contact_address_country_alpha_2_code
|
||||
];
|
||||
|
||||
/**
|
||||
* NON-EXPORTED LOCAL HELPER
|
||||
* Processes a list of Aether objects by applying common and specific transformations.
|
||||
*/
|
||||
async function _process_generic_props<T extends Record<string, any>>({
|
||||
obj_li,
|
||||
obj_type,
|
||||
log_lvl = 0,
|
||||
specific_processor
|
||||
}: {
|
||||
obj_li: T[];
|
||||
obj_type: string;
|
||||
log_lvl?: number;
|
||||
specific_processor?: (obj: T) => Promise<T> | T;
|
||||
}): Promise<T[]> {
|
||||
if (log_lvl > 0) {
|
||||
console.log(
|
||||
`*** _process_generic_props: Processing ${obj_li.length} objects of type "${obj_type}" ***`
|
||||
);
|
||||
}
|
||||
|
||||
if (!obj_li || obj_li.length === 0) {
|
||||
if (log_lvl > 0) console.log('No objects to process.');
|
||||
return [];
|
||||
}
|
||||
|
||||
const processed_obj_li: T[] = [];
|
||||
|
||||
for (const original_obj of obj_li) {
|
||||
let processed_obj = { ...original_obj };
|
||||
|
||||
// --- Common Transformations ---
|
||||
|
||||
// 1. Standardize ID and other '_random' fields
|
||||
// The API often returns fields like 'person_id_random', which need to be aliased to 'person_id'.
|
||||
for (const key in processed_obj) {
|
||||
if (key.endsWith('_random')) {
|
||||
const new_key = key.slice(0, -7); // Remove '_random' suffix
|
||||
(processed_obj as any)[new_key] = processed_obj[key];
|
||||
}
|
||||
}
|
||||
// Ensure 'id' is set from '[obj_type]_id_random'
|
||||
const random_id_key = `${obj_type}_id_random`;
|
||||
if (processed_obj[random_id_key]) {
|
||||
(processed_obj as any).id = processed_obj[random_id_key];
|
||||
}
|
||||
|
||||
// 2. Create common computed properties for client-side sorting.
|
||||
const group = processed_obj.group ?? '0';
|
||||
const priority = processed_obj.priority ? 1 : 0;
|
||||
const sort = processed_obj.sort ?? '0';
|
||||
const updated = processed_obj.updated_on ?? processed_obj.created_on;
|
||||
const name = processed_obj.name ?? '';
|
||||
|
||||
(processed_obj as any).tmp_sort_1 = `${group}_${priority}_${sort}_${updated}`;
|
||||
(processed_obj as any).tmp_sort_2 = `${group}_${priority}_${sort}_${name}_${updated}`;
|
||||
|
||||
// --- Specific Transformations ---
|
||||
if (specific_processor) {
|
||||
processed_obj = await Promise.resolve(specific_processor(processed_obj));
|
||||
}
|
||||
|
||||
processed_obj_li.push(processed_obj as T);
|
||||
}
|
||||
|
||||
return processed_obj_li;
|
||||
}
|
||||
|
||||
// Updated 2025-06-10
|
||||
export async function process_ae_obj__person_props({
|
||||
obj_li,
|
||||
log_lvl = 0
|
||||
}: {
|
||||
obj_li: any[];
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
return _process_generic_props({
|
||||
obj_li,
|
||||
obj_type: 'person',
|
||||
log_lvl,
|
||||
specific_processor: (obj) => {
|
||||
// Person-specific computed sort fields, overriding generic ones if needed
|
||||
obj.tmp_sort_1 = `${obj.group ?? '0'}_${obj.priority ? 1 : 0}_${
|
||||
obj.sort ?? '0'
|
||||
}_${obj.updated_on}_${obj.created_on}`;
|
||||
obj.tmp_sort_2 = `${obj.group ?? '0'}_${obj.priority ? 1 : 0}_${
|
||||
obj.sort ?? '0'
|
||||
}_${obj.updated_on ?? obj.created_on}`;
|
||||
obj.tmp_sort_3 = `${obj.group ?? '0'}_${obj.priority ? 1 : 0}_${
|
||||
obj.sort ?? '0'
|
||||
}_${obj.name ?? ''}_${obj.updated_on ?? obj.created_on}`;
|
||||
|
||||
return obj;
|
||||
}
|
||||
});
|
||||
}
|
||||
263
src/lib/ae_core/core__qr_code.ts
Normal file
263
src/lib/ae_core/core__qr_code.ts
Normal file
@@ -0,0 +1,263 @@
|
||||
import QRCode from 'qrcode';
|
||||
|
||||
import type { key_val } from '$lib/stores/ae_stores';
|
||||
import { api } from '$lib/api/api';
|
||||
|
||||
import { db_core } from '$lib/ae_core/db_core';
|
||||
|
||||
const ae_promises: key_val = {};
|
||||
|
||||
// I recently made significant updates to this with the help of Copilot. I think it is correct.
|
||||
// Updated 2025-10-03
|
||||
export async function generate_qr_code({
|
||||
api_cfg,
|
||||
account_id,
|
||||
qr_type, // mecard, obj, str, vcard
|
||||
qr_id, // This is essentially the filename it can be found at /qr/{account_id}/{qr_id}
|
||||
qr_data, // vcard fields:
|
||||
obj_type,
|
||||
obj_id,
|
||||
str, // For encoding a string (like a URL) into a QR code.
|
||||
return_blob = true, // blob or url?
|
||||
try_cache = false,
|
||||
log_lvl = 0
|
||||
}: {
|
||||
api_cfg: any;
|
||||
account_id: string;
|
||||
qr_type: string;
|
||||
qr_id: string;
|
||||
qr_data?: any;
|
||||
obj_type?: string;
|
||||
obj_id?: string;
|
||||
str?: string;
|
||||
return_blob?: boolean;
|
||||
try_cache?: boolean;
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
if (log_lvl) {
|
||||
console.log(`*** generate_qr_code() *** qr_id=${qr_id}`);
|
||||
}
|
||||
|
||||
const endpoint = `/qr/${account_id}/${qr_id}`;
|
||||
if (log_lvl) {
|
||||
console.log('Endpoint', endpoint);
|
||||
}
|
||||
const params: key_val = {
|
||||
regen: true, // Regenerate the file even if nothing has changed.
|
||||
return_file: return_blob,
|
||||
qr_type: qr_type, // mecard, obj, vcard
|
||||
qr_send: return_blob
|
||||
};
|
||||
|
||||
if (qr_type == 'vcard') {
|
||||
if (qr_data.informal_name) {
|
||||
params['n'] = `${qr_data.family_name};${qr_data.given_name};${qr_data.informal_name}`;
|
||||
} else {
|
||||
params['n'] = `${qr_data.family_name};${qr_data.given_name}`;
|
||||
}
|
||||
params['fn'] = qr_data.full_name_override;
|
||||
if (qr_data.affiliations) {
|
||||
params['org'] = qr_data.affiliations;
|
||||
}
|
||||
params['email'] = qr_data.email;
|
||||
if (qr_data.phone) {
|
||||
params['tel'] = qr_data.phone;
|
||||
}
|
||||
params['adr'] = qr_data.location_override;
|
||||
if (qr_data.address_line_1) {
|
||||
params['adr_str'] = qr_data.address_line_1;
|
||||
}
|
||||
params['adr_loc'] = qr_data.city;
|
||||
params['adr_reg'] = qr_data.state_province;
|
||||
params['adr_postal'] = qr_data.postal_code;
|
||||
params['adr_country'] = qr_data.country;
|
||||
} else if (qr_type == 'obj') {
|
||||
params['obj_type'] = obj_type;
|
||||
params['obj_id'] = obj_id;
|
||||
} else if (qr_type == 'str') {
|
||||
params['str'] = str;
|
||||
}
|
||||
|
||||
if (log_lvl) {
|
||||
console.log('Params', params);
|
||||
}
|
||||
|
||||
const filename = null;
|
||||
|
||||
// Await the API call
|
||||
ae_promises.generate_qr_code = await api.get_object({
|
||||
api_cfg: api_cfg,
|
||||
endpoint: endpoint,
|
||||
params: params,
|
||||
return_blob: return_blob,
|
||||
filename: filename,
|
||||
auto_download: false,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
|
||||
if (log_lvl) {
|
||||
console.log('QR code API response:', ae_promises.generate_qr_code);
|
||||
}
|
||||
|
||||
// If return_blob is true, ensure we return an object URL for use in <img src=...>
|
||||
if (return_blob) {
|
||||
const data = ae_promises.generate_qr_code.data ?? ae_promises.generate_qr_code;
|
||||
|
||||
// If already a Blob, use it directly
|
||||
if (data instanceof Blob) {
|
||||
return URL.createObjectURL(data);
|
||||
}
|
||||
|
||||
// If it's a Response (from fetch), convert to Blob
|
||||
if (data instanceof Response) {
|
||||
const blob = await data.blob();
|
||||
return URL.createObjectURL(blob);
|
||||
}
|
||||
|
||||
// If it's an ArrayBuffer or Uint8Array, convert to Blob
|
||||
if (data instanceof ArrayBuffer || data instanceof Uint8Array) {
|
||||
const blob = new Blob([data], { type: 'image/png' });
|
||||
return URL.createObjectURL(blob);
|
||||
}
|
||||
|
||||
// If it's a base64 string, return as data URL
|
||||
if (typeof data === 'string' && data.startsWith('data:image')) {
|
||||
return data;
|
||||
}
|
||||
|
||||
// If it's a raw string (base64), convert to data URL
|
||||
if (typeof data === 'string') {
|
||||
return `data:image/png;base64,${data}`;
|
||||
}
|
||||
|
||||
// Fallback: try to create a Blob from whatever is left
|
||||
try {
|
||||
const blob = new Blob([data], { type: 'image/png' });
|
||||
return URL.createObjectURL(blob);
|
||||
} catch (e) {
|
||||
if (log_lvl) console.error('Could not create QR code image blob:', e, data);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// If not returning a blob, return the raw API response
|
||||
return ae_promises.generate_qr_code;
|
||||
}
|
||||
|
||||
// Updated 2025-10-09
|
||||
/**
|
||||
* Generates a QR code image as a Base64 data URL based on provided parameters.
|
||||
*
|
||||
* NOTE: This function handles the data formatting and QR generation,
|
||||
* but does NOT handle server-side logic like file saving, disk path checks,
|
||||
* or database lookups (like redis_lookup_id_random).
|
||||
*
|
||||
* @param {string} qr_type - The type of data format ('mecard', 'vcard', 'obj', 'kv', 'js', 'str').
|
||||
* @param {Object} params - An object containing all necessary query parameters (n, fn, url, email, etc.).
|
||||
* @param {string} qr_id - A unique ID (unused in pure client-side generation, but kept for context).
|
||||
* @returns {Promise<string>} A promise that resolves to a Base64 data URL of the QR code image.
|
||||
* @throws {Error} If the qr_type is unknown or data is missing.
|
||||
*/
|
||||
export async function js_generate_qr_code(qr_type, params = {}) {
|
||||
const {
|
||||
n = '',
|
||||
fn = '',
|
||||
org = '',
|
||||
url = '',
|
||||
email = '',
|
||||
tel = '',
|
||||
adr_poa = '',
|
||||
adr_ext = '',
|
||||
adr_str = '',
|
||||
adr_loc = '',
|
||||
adr_reg = '',
|
||||
adr_postal = '',
|
||||
adr_country = '',
|
||||
obj_type,
|
||||
obj_id,
|
||||
key,
|
||||
val,
|
||||
js,
|
||||
str
|
||||
} = params;
|
||||
|
||||
console.log(`*** js_generate_qr_code() *** qr_type=${qr_type}`, params);
|
||||
|
||||
let qr_data = null;
|
||||
|
||||
// --- 1. Replicate Data Formatting Logic ---
|
||||
switch (qr_type) {
|
||||
case 'mecard':
|
||||
// Format: MECARD:N:name;EMAIL:email;ADR:address;;
|
||||
// Note: The original Python code had adr, but we'll use n and email as a minimum.
|
||||
qr_data = `MECARD:N:${n};EMAIL:${email};;`;
|
||||
// You can enhance this with other MeCard fields if needed.
|
||||
break;
|
||||
|
||||
case 'vcard':
|
||||
// Format: BEGIN:VCARD...END:VCARD
|
||||
qr_data = `BEGIN:VCARD\nVERSION:3.0\nN:${n}\nFN:${fn}\nORG:${org}\nEMAIL:${email}\n`;
|
||||
|
||||
if (url) {
|
||||
qr_data += `URL:${url}\n`;
|
||||
}
|
||||
if (tel) {
|
||||
qr_data += `TEL:${tel}\n`;
|
||||
}
|
||||
if (adr_loc) {
|
||||
// ADR format: TYPE=postal:Po box;Ext;Street;Locality;Region;Postal code;Country
|
||||
qr_data += `ADR:${adr_poa};${adr_ext};${adr_str};${adr_loc};${adr_reg};${adr_postal};${adr_country}\n`;
|
||||
}
|
||||
qrData += 'END:VCARD';
|
||||
break;
|
||||
|
||||
case 'obj':
|
||||
// Custom format: OBJ:ot:obj_type,oi:obj_id
|
||||
if (!obj_type || !obj_id) throw new Error('Missing obj_type or obj_id for type "obj".');
|
||||
qr_data = `OBJ:ot:${obj_type},oi:${obj_id}`;
|
||||
break;
|
||||
|
||||
case 'kv':
|
||||
// Custom format: KV:k:"key",v:"val"
|
||||
if (!key || !val) throw new Error('Missing key or val for type "kv".');
|
||||
qr_data = `KV:k:"${key}",v:"${val}"`;
|
||||
break;
|
||||
|
||||
case 'js':
|
||||
// Assumes 'js' is a stringified JSON object
|
||||
if (!js) throw new Error('Missing js string for type "js".');
|
||||
qr_data = `JS:${js}`;
|
||||
break;
|
||||
|
||||
case 'str':
|
||||
// Raw string data
|
||||
if (!str) throw new Error('Missing raw string data for type "str".');
|
||||
qr_data = str;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Error(`Unknown QR type: ${qr_type}`);
|
||||
}
|
||||
|
||||
if (!qr_data) {
|
||||
throw new Error('Failed to create QR code data string.');
|
||||
}
|
||||
|
||||
// --- 2. Generate QR Code Image ---
|
||||
try {
|
||||
// Options match the Python 'qrcode' library defaults closely:
|
||||
// error_correction = qrcode.constants.ERROR_CORRECT_M
|
||||
// box_size = 10, border = 1
|
||||
const data_url = await QRCode.toDataURL(qr_data, {
|
||||
errorCorrectionLevel: 'M',
|
||||
margin: 1, // Corresponds to border
|
||||
scale: 10, // Corresponds to box_size
|
||||
type: 'image/png'
|
||||
});
|
||||
console.log('Generated QR code data URL:', data_url);
|
||||
return data_url;
|
||||
} catch (error) {
|
||||
console.error('Error generating QR code:', error);
|
||||
throw new Error('Could not generate QR code image.');
|
||||
}
|
||||
}
|
||||
50
src/lib/ae_core/core__site.ts
Normal file
50
src/lib/ae_core/core__site.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
export interface Site {
|
||||
id: string;
|
||||
// id_random: string;
|
||||
site_id: string;
|
||||
site_id_random?: string;
|
||||
|
||||
code?: string;
|
||||
|
||||
account_id: string;
|
||||
account_id_random?: string;
|
||||
|
||||
name: string;
|
||||
description?: null | string;
|
||||
|
||||
restrict_access?: null | boolean;
|
||||
access_key?: null | string;
|
||||
access_code_kv_json?: null | string;
|
||||
|
||||
logo_path?: null | string;
|
||||
logo_bg_color?: null | string; // Not really used currently.
|
||||
// background_image_path?: null|string; // Legacy field
|
||||
// background_bg_color?: null|string; // Legacy field
|
||||
title?: null | string;
|
||||
|
||||
// header_html?: null|string; // Legacy field
|
||||
// header_css?: null|string; // Legacy field
|
||||
// header_image_path?: null|string; // Legacy field
|
||||
// header_image_bg_color?: null|string; // Legacy field
|
||||
// body_html?: null|string; // Legacy field
|
||||
tagline?: null | string;
|
||||
// site_header_h1?: null|string; // Legacy field
|
||||
// site_header_h2?: null|string; // Legacy field
|
||||
style_href?: null | string; // Legacy field
|
||||
// script_src?: null|string; // Legacy field
|
||||
google_tracking_id?: null | string;
|
||||
|
||||
cfg_json?: null | string; // key value config json
|
||||
|
||||
enable: null | boolean;
|
||||
enable_from?: null | Date;
|
||||
enable_to?: null | Date;
|
||||
|
||||
hide?: null | boolean;
|
||||
priority?: null | boolean;
|
||||
sort?: null | number;
|
||||
group?: null | string;
|
||||
notes?: null | string;
|
||||
created_on: Date;
|
||||
updated_on?: null | Date;
|
||||
}
|
||||
75
src/lib/ae_core/core__site_domain.ts
Normal file
75
src/lib/ae_core/core__site_domain.ts
Normal file
@@ -0,0 +1,75 @@
|
||||
export interface Site_Domain {
|
||||
id: string;
|
||||
// id_random: string;
|
||||
site_id: string;
|
||||
site_id_random?: string;
|
||||
|
||||
fqdn: string;
|
||||
access_key?: null | string;
|
||||
required_referrer?: null | string;
|
||||
valid_for?: null | number; // In hours
|
||||
|
||||
enable: null | boolean;
|
||||
hide?: null | boolean;
|
||||
priority?: null | boolean;
|
||||
sort?: null | number;
|
||||
group?: null | string;
|
||||
notes?: null | string;
|
||||
created_on: Date;
|
||||
updated_on?: null | Date;
|
||||
}
|
||||
|
||||
import { api } from '$lib/api/api';
|
||||
|
||||
/**
|
||||
* Fetches a site_domain object by its Fully Qualified Domain Name (FQDN).
|
||||
*
|
||||
* @param api_cfg - The API configuration object.
|
||||
* @param fqdn - The FQDN of the site domain to fetch.
|
||||
* @param timeout - The request timeout in milliseconds.
|
||||
* @param log_lvl - The logging level.
|
||||
* @returns The site domain object or null if not found.
|
||||
*/
|
||||
export async function load_ae_obj_by_fqdn__site_domain({
|
||||
api_cfg,
|
||||
fqdn,
|
||||
timeout = 7000,
|
||||
log_lvl = 0
|
||||
}: {
|
||||
api_cfg: any;
|
||||
fqdn: string;
|
||||
timeout?: number;
|
||||
log_lvl?: number;
|
||||
}): Promise<any> {
|
||||
if (log_lvl) {
|
||||
console.log(
|
||||
`*** load_ae_obj_by_fqdn__site_domain() *** api.base_url=${api_cfg.base_url}, fqdn=${fqdn}, timeout=${timeout}`
|
||||
);
|
||||
}
|
||||
|
||||
const params = {};
|
||||
|
||||
try {
|
||||
const site_domain_obj = await api.get_ae_obj_id_crud({
|
||||
api_cfg: api_cfg,
|
||||
no_account_id: true, // This seems to be a special case for this endpoint
|
||||
obj_type: 'site_domain',
|
||||
obj_id: fqdn, // NOTE: This is the FQDN, not the ID.
|
||||
use_alt_table: true,
|
||||
use_alt_base: true,
|
||||
params: params,
|
||||
timeout: timeout,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
|
||||
if (site_domain_obj) {
|
||||
return site_domain_obj;
|
||||
} else {
|
||||
console.log('No results returned.');
|
||||
return null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('No results returned or failed.', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
72
src/lib/ae_core/core__time_zones.ts
Normal file
72
src/lib/ae_core/core__time_zones.ts
Normal file
@@ -0,0 +1,72 @@
|
||||
import type { key_val } from '$lib/stores/ae_stores';
|
||||
import { api } from '$lib/api/api';
|
||||
|
||||
import { db_core } from '$lib/ae_core/db_core';
|
||||
|
||||
const ae_promises: key_val = {};
|
||||
|
||||
// Updated 2024-10-14
|
||||
export async function load_ae_obj_li__time_zone({
|
||||
api_cfg,
|
||||
// account_id,
|
||||
enabled = 'enabled',
|
||||
hidden = 'not_hidden',
|
||||
limit = 99,
|
||||
offset = 0,
|
||||
// order_by_li = {'priority': 'DESC', 'group': 'ASC', 'sort': 'DESC', 'name': 'ASC'},
|
||||
order_by_li = { priority: 'DESC', sort: 'DESC', name: 'ASC' },
|
||||
params = {},
|
||||
try_cache = true,
|
||||
log_lvl = 0
|
||||
}: {
|
||||
api_cfg: any;
|
||||
// account_id: string,
|
||||
enabled?: 'enabled' | 'all' | 'not_enabled' | undefined;
|
||||
hidden?: 'hidden' | 'all' | 'not_hidden' | undefined;
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
order_by_li?: key_val;
|
||||
params?: key_val;
|
||||
try_cache?: boolean;
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
if (log_lvl) {
|
||||
console.log(`*** load_ae_obj_li__time_zone() ***`);
|
||||
}
|
||||
|
||||
const params_json: key_val = {};
|
||||
|
||||
// console.log('params_json:', params_json);
|
||||
|
||||
ae_promises.load__time_zone_li = await api
|
||||
.get_ae_obj_li_for_obj_id_crud_v2({
|
||||
api_cfg: api_cfg,
|
||||
obj_type: 'lu',
|
||||
for_obj_type: 'time_zone',
|
||||
// for_obj_id: account_id,
|
||||
use_alt_tbl: true, // NOTE: Using this with the time zones to use the view named "v_lu_time_zone_cust"
|
||||
use_alt_mdl: false,
|
||||
enabled: enabled,
|
||||
hidden: hidden,
|
||||
order_by_li: order_by_li,
|
||||
limit: limit,
|
||||
offset: offset,
|
||||
params_json: params_json,
|
||||
params: params,
|
||||
log_lvl: log_lvl
|
||||
})
|
||||
.then(function (time_zone_li_get_result) {
|
||||
if (time_zone_li_get_result) {
|
||||
// handle_db_save_ae_obj_li__time_zone({obj_type: 'time_zone', obj_li: time_zone_li_get_result});
|
||||
return time_zone_li_get_result;
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
})
|
||||
.catch(function (error: any) {
|
||||
console.log('No results returned or failed.', error);
|
||||
});
|
||||
|
||||
console.log('ae_promises.load__time_zone_li:', ae_promises.load__time_zone_li);
|
||||
return ae_promises.load__time_zone_li;
|
||||
}
|
||||
335
src/lib/ae_core/core__user.ts
Normal file
335
src/lib/ae_core/core__user.ts
Normal file
@@ -0,0 +1,335 @@
|
||||
import type { key_val } from '$lib/stores/ae_stores';
|
||||
import { api } from '$lib/api/api';
|
||||
|
||||
import { db_core } from '$lib/ae_core/db_core';
|
||||
|
||||
const ae_promises: key_val = {};
|
||||
|
||||
// Updated 2025-04-04
|
||||
export async function auth_ae_obj__username_password({
|
||||
api_cfg,
|
||||
account_id,
|
||||
null_account_id = false,
|
||||
username,
|
||||
password,
|
||||
params = {},
|
||||
try_cache = true,
|
||||
log_lvl = 0
|
||||
}: {
|
||||
api_cfg: any;
|
||||
account_id: string;
|
||||
null_account_id?: boolean;
|
||||
username: string;
|
||||
password: string;
|
||||
params?: key_val;
|
||||
try_cache?: boolean;
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
if (log_lvl) {
|
||||
console.log(
|
||||
`*** auth_ae_obj__username_password() *** account_id=${account_id} username=${username} password=${password}`
|
||||
);
|
||||
}
|
||||
|
||||
const endpoint = '/user/authenticate';
|
||||
|
||||
if (null_account_id) {
|
||||
params['null_account_id'] = true;
|
||||
}
|
||||
params['username'] = username; // Required
|
||||
params['password'] = password; // Required
|
||||
if (log_lvl > 1) {
|
||||
console.log(`auth_ae_obj__username_password() - params:`, params);
|
||||
}
|
||||
|
||||
ae_promises.auth__username_password = await api
|
||||
.get_object({
|
||||
api_cfg: api_cfg,
|
||||
endpoint: endpoint,
|
||||
params: params,
|
||||
// data: {},
|
||||
log_lvl: log_lvl
|
||||
})
|
||||
.then(async function (user_obj_get_result) {
|
||||
if (user_obj_get_result) {
|
||||
// if (try_cache) {
|
||||
// // This is expecting a list
|
||||
// db_save_ae_obj_li__user({
|
||||
// obj_type: 'user',
|
||||
// obj_li: [user_obj_get_result],
|
||||
// log_lvl: log_lvl
|
||||
// });
|
||||
// }
|
||||
return user_obj_get_result;
|
||||
} else {
|
||||
console.log('No results returned.');
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.catch(function (error: any) {
|
||||
console.log('No results returned or failed.', error);
|
||||
});
|
||||
|
||||
if (log_lvl) {
|
||||
console.log('ae_promises.auth__username_password:', ae_promises.auth__username_password);
|
||||
}
|
||||
return ae_promises.auth__username_password;
|
||||
}
|
||||
|
||||
// Updated 2025-04-04
|
||||
export async function auth_ae_obj__user_id_user_auth_key({
|
||||
api_cfg,
|
||||
account_id,
|
||||
user_id,
|
||||
user_auth_key,
|
||||
params = {},
|
||||
try_cache = true,
|
||||
log_lvl = 0
|
||||
}: {
|
||||
api_cfg: any;
|
||||
account_id: string;
|
||||
user_id: string;
|
||||
user_auth_key: string;
|
||||
params?: key_val;
|
||||
try_cache?: boolean;
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
if (log_lvl) {
|
||||
console.log(
|
||||
`*** auth_ae_obj__user_id_user_auth_key() *** account_id=${account_id} user_id=${user_id}`
|
||||
);
|
||||
}
|
||||
|
||||
const endpoint = '/user/authenticate';
|
||||
|
||||
params['user_id'] = user_id; // Required
|
||||
params['auth_key'] = user_auth_key; // Required
|
||||
if (log_lvl > 1) {
|
||||
console.log(`auth_ae_obj__user_id_user_auth_key() - params:`, params);
|
||||
}
|
||||
|
||||
ae_promises.auth__user_id_user_key = await api
|
||||
.get_object({
|
||||
api_cfg: api_cfg,
|
||||
endpoint: endpoint,
|
||||
params: params,
|
||||
log_lvl: log_lvl
|
||||
})
|
||||
.then(async function (user_obj_get_result) {
|
||||
if (user_obj_get_result) {
|
||||
return user_obj_get_result;
|
||||
} else {
|
||||
console.log('No results returned.');
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.catch(function (error: any) {
|
||||
console.log('No results returned or failed.', error);
|
||||
});
|
||||
|
||||
if (log_lvl) {
|
||||
console.log('ae_promises.auth__user_id_user_key:', ae_promises.auth__user_id_user_key);
|
||||
}
|
||||
return ae_promises.auth__user_id_user_key;
|
||||
}
|
||||
|
||||
// Send an email to the user with a new one time use authentication key. The new key must be generated and returned first.
|
||||
// Updated 2025-04-08
|
||||
export async function send_email_auth_ae_obj__user_id({
|
||||
api_cfg,
|
||||
account_id,
|
||||
user_id,
|
||||
base_url,
|
||||
key_param_name = 'user_key', // API defaults to 'auth_key'
|
||||
params = {},
|
||||
// try_cache = true,
|
||||
log_lvl = 0
|
||||
}: {
|
||||
api_cfg: any;
|
||||
account_id: string;
|
||||
user_id: string;
|
||||
base_url?: string;
|
||||
key_param_name?: string;
|
||||
params?: key_val;
|
||||
// try_cache?: boolean,
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
if (log_lvl) {
|
||||
console.log(
|
||||
`*** send_email_auth_ae_obj__user_id() *** account_id=${account_id} user_id=${user_id}`
|
||||
);
|
||||
}
|
||||
if (log_lvl > 1) {
|
||||
console.log(api_cfg);
|
||||
}
|
||||
|
||||
const email_auth_key_endpoint = `user/${user_id}/email_auth_key_url`;
|
||||
params = {
|
||||
root_url: base_url,
|
||||
key_param_name: key_param_name
|
||||
};
|
||||
ae_promises.auth_key__send_email = await api.get_object({
|
||||
api_cfg: api_cfg,
|
||||
endpoint: email_auth_key_endpoint,
|
||||
params: params,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
|
||||
return ae_promises.auth_key__send_email;
|
||||
|
||||
// let endpoint = `/user/${user_id}/new_auth_key`;
|
||||
|
||||
// // params['user_id'] = user_id; // Required
|
||||
// if (log_lvl > 1) {
|
||||
// console.log(`send_email_auth_ae_obj__user_id() - params:`, params);
|
||||
// }
|
||||
|
||||
// ae_promises.auth_key__gen_auth_key = await api.get_object({
|
||||
// api_cfg: api_cfg,
|
||||
// endpoint: endpoint,
|
||||
// params: params,
|
||||
// log_lvl: log_lvl
|
||||
// })
|
||||
// .then(async function (email_send_result) {
|
||||
// if (email_send_result) {
|
||||
// let email_auth_key_endpoint = `user/${user_id}/email_auth_key_url`;
|
||||
// params = {
|
||||
// 'root_url': 'https://test.oneskyit.com'
|
||||
// }
|
||||
// ae_promises.auth_key__send_email = await api.get_object({
|
||||
// api_cfg: api_cfg,
|
||||
// endpoint: email_auth_key_endpoint,
|
||||
// params: params,
|
||||
// log_lvl: log_lvl
|
||||
// })
|
||||
|
||||
// return email_send_result;
|
||||
// } else {
|
||||
// console.log('No results returned.');
|
||||
// return null;
|
||||
// }
|
||||
// })
|
||||
// .catch(function (error: any) {
|
||||
// console.log('No results returned or failed.', error);
|
||||
// });
|
||||
|
||||
// if (log_lvl) {
|
||||
// console.log('ae_promises.send_email_auth__user_id:', ae_promises.send_email_auth__user_id);
|
||||
// }
|
||||
// return ae_promises.send_email_auth__user_id;
|
||||
}
|
||||
|
||||
// Look up user based on email address provided
|
||||
// Updated 2025-04-08
|
||||
export async function qry_ae_obj_li__user_email({
|
||||
api_cfg,
|
||||
account_id,
|
||||
null_account_id = false,
|
||||
email,
|
||||
params = {},
|
||||
try_cache = true,
|
||||
log_lvl = 0
|
||||
}: {
|
||||
api_cfg: any;
|
||||
account_id: string;
|
||||
null_account_id?: boolean;
|
||||
email: string;
|
||||
params?: key_val;
|
||||
try_cache?: boolean;
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
if (log_lvl) {
|
||||
console.log(`*** qry_ae_obj_li__user_email() *** account_id=${account_id} email=${email}`);
|
||||
}
|
||||
|
||||
const endpoint = '/user/lookup_email';
|
||||
|
||||
params['email'] = email; // Required
|
||||
params['null_account_id'] = null_account_id || false;
|
||||
if (log_lvl > 1) {
|
||||
console.log(`qry_ae_obj_li__user_email() - params:`, params);
|
||||
}
|
||||
|
||||
ae_promises.qry__user_email = await api
|
||||
.get_object({
|
||||
api_cfg: api_cfg,
|
||||
endpoint: endpoint,
|
||||
params: params,
|
||||
log_lvl: log_lvl
|
||||
})
|
||||
.then(async function (user_obj_get_result) {
|
||||
if (user_obj_get_result) {
|
||||
return user_obj_get_result;
|
||||
} else {
|
||||
console.log('No results returned.');
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.catch(function (error: any) {
|
||||
console.log('No results returned or failed.', error);
|
||||
});
|
||||
|
||||
if (log_lvl) {
|
||||
console.log('ae_promises.qry__user_email:', ae_promises.qry__user_email);
|
||||
}
|
||||
return ae_promises.qry__user_email;
|
||||
}
|
||||
|
||||
// Change user password
|
||||
// endpoint: PATCH /user/{user_id}/change_password
|
||||
// params:
|
||||
// data_kv: password (the new password)
|
||||
// Updated 2025-04-11
|
||||
export async function auth_ae_obj__user_id_change_password({
|
||||
api_cfg,
|
||||
account_id,
|
||||
user_id,
|
||||
password,
|
||||
params = {},
|
||||
log_lvl = 0
|
||||
}: {
|
||||
api_cfg: any;
|
||||
account_id: string;
|
||||
user_id: string;
|
||||
password: string;
|
||||
params?: key_val;
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
if (log_lvl) {
|
||||
console.log(
|
||||
`*** auth_ae_obj__user_id_change_password() *** account_id=${account_id} user_id=${user_id}`
|
||||
);
|
||||
}
|
||||
|
||||
const endpoint = `/user/${user_id}/change_password`;
|
||||
|
||||
params['user_id'] = user_id; // Required
|
||||
if (log_lvl > 1) {
|
||||
console.log(`auth_ae_obj__user_id_change_password() - params:`, params);
|
||||
}
|
||||
|
||||
ae_promises.change_password__user_id = await api
|
||||
.patch_object({
|
||||
api_cfg: api_cfg,
|
||||
endpoint: endpoint,
|
||||
params: params,
|
||||
data: { password: password },
|
||||
log_lvl: log_lvl
|
||||
})
|
||||
.then(async function (change_password_result) {
|
||||
if (change_password_result) {
|
||||
return change_password_result;
|
||||
} else {
|
||||
console.log('No results returned.');
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.catch(function (error: any) {
|
||||
console.log('No results returned or failed.', error);
|
||||
});
|
||||
|
||||
if (log_lvl) {
|
||||
console.log('ae_promises.change_password__user_id:', ae_promises.change_password__user_id);
|
||||
}
|
||||
return ae_promises.change_password__user_id;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user