mirror of
https://github.com/Part-DB/Part-DB-server.git
synced 2026-02-21 01:02:53 +01:00
Compare commits
736 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
39009a71d5 | ||
|
|
0430178fe2 | ||
|
|
cf9df883c9 | ||
|
|
198befe2bc | ||
|
|
7195bd6cd6 | ||
|
|
a5fa2da80c | ||
|
|
593d37f37c | ||
|
|
2ddd6753ca | ||
|
|
9537c4f210 | ||
|
|
e0ce6ba165 | ||
|
|
ee50ce26f8 | ||
|
|
94a6de4a90 | ||
|
|
d5902314c3 | ||
|
|
60125534ec | ||
|
|
48385cadc9 | ||
|
|
ba6abe6ca7 | ||
|
|
79ad243bf4 | ||
|
|
5ab21e019d | ||
|
|
d8469efba2 | ||
|
|
316b09ddf3 | ||
|
|
866ef73774 | ||
|
|
138d5c6e0f | ||
|
|
4bed50d894 | ||
|
|
55943f5d8f | ||
|
|
133652c296 | ||
|
|
b9331ac1ef | ||
|
|
08f7b2cc87 | ||
|
|
1a2bdaf8e5 | ||
|
|
d81dec78ae | ||
|
|
f78bd03521 | ||
|
|
6aa16272d8 | ||
|
|
e80f7c08ab | ||
|
|
675f05f0fb | ||
|
|
b1f23e1684 | ||
|
|
d612164885 | ||
|
|
b257e1d5f7 | ||
|
|
f26776ecd5 | ||
|
|
bf4a23652c | ||
|
|
e7681aedb1 | ||
|
|
098fcb29fb | ||
|
|
eb46ea19e3 | ||
|
|
99ee05a90f | ||
|
|
fd31f983af | ||
|
|
80bae4167f | ||
|
|
eaee4af715 | ||
|
|
7d4723c3e4 | ||
|
|
33a0981981 | ||
|
|
b62dc1241d | ||
|
|
e2270aec38 | ||
|
|
73346fcdaf | ||
|
|
7b112512a9 | ||
|
|
0e5613b57b | ||
|
|
e66ff40733 | ||
|
|
73d61f7440 | ||
|
|
dedb3071d6 | ||
|
|
a43ee52086 | ||
|
|
97ccb0cb21 | ||
|
|
1fb334b0ca | ||
|
|
fa4af99525 | ||
|
|
b3153dac68 | ||
|
|
c981476706 | ||
|
|
1a3e5ec705 | ||
|
|
aaff0835a3 | ||
|
|
9bf814d4cd | ||
|
|
b5c0f37f88 | ||
|
|
05d73d2f68 | ||
|
|
ff284d056c | ||
|
|
2393c759f3 | ||
|
|
0a983513ea | ||
|
|
c737348cea | ||
|
|
e8e2258357 | ||
|
|
d847b74522 | ||
|
|
5750e7dbdf | ||
|
|
ffe76f9d2e | ||
|
|
5b1ad541a8 | ||
|
|
4824a82c3f | ||
|
|
f7cea1100c | ||
|
|
827dd01e28 | ||
|
|
d969f49ecc | ||
|
|
0f336b6f89 | ||
|
|
43cc37d10f | ||
|
|
6a00b8e168 | ||
|
|
1b3fc2c23c | ||
|
|
8e96971b9c | ||
|
|
8e39e330fe | ||
|
|
15ba6572df | ||
|
|
1c222ff293 | ||
|
|
2fb1ec7f8a | ||
|
|
70f1db9619 | ||
|
|
11be65678e | ||
|
|
80ed064cd6 | ||
|
|
62b1e33616 | ||
|
|
52f2ef6d30 | ||
|
|
8ace78a873 | ||
|
|
5c30210534 | ||
|
|
1d03b6c38d | ||
|
|
d3ead8742e | ||
|
|
ed6b0057b7 | ||
|
|
90fbcb88d8 | ||
|
|
be2ed52d93 | ||
|
|
f1af19a52a | ||
|
|
4c4501073c | ||
|
|
b8b9a416ac | ||
|
|
fc7e436ca9 | ||
|
|
1de1eebc59 | ||
|
|
a4d411656b | ||
|
|
1ec4266f96 | ||
|
|
61f02d693f | ||
|
|
cd80552ce7 | ||
|
|
d59b8817c3 | ||
|
|
8ce5f4a796 | ||
|
|
2e8cb35acc | ||
|
|
c0f626e9bd | ||
|
|
2ddfe48aba | ||
|
|
2c6de84c9a | ||
|
|
87cf4c2d08 | ||
|
|
3a8c835880 | ||
|
|
e2dbd3d873 | ||
|
|
55aabddd41 | ||
|
|
eb07820523 | ||
|
|
8116217019 | ||
|
|
6fb1845ff7 | ||
|
|
75325f0ed8 | ||
|
|
0577f9e166 | ||
|
|
52c6884e28 | ||
|
|
2be76a488f | ||
|
|
686535fe42 | ||
|
|
5c17aee1e4 | ||
|
|
9b35ac3a99 | ||
|
|
59b78e850f | ||
|
|
3a8c5a788f | ||
|
|
afcbbe0f43 | ||
|
|
d10d29e590 | ||
|
|
7b61cb3163 | ||
|
|
4c1c6701b3 | ||
|
|
f423fdf7f8 | ||
|
|
a5995a2ce8 | ||
|
|
c810b6772c | ||
|
|
b74ab18a6d | ||
|
|
edc54aaf91 | ||
|
|
b3b205cd6e | ||
|
|
2fe4def775 | ||
|
|
7bbf612394 | ||
|
|
97ab1f0492 | ||
|
|
81bfcdd158 | ||
|
|
6862d318f0 | ||
|
|
412fa3f0bf | ||
|
|
01d9109c45 | ||
|
|
dd914d1d64 | ||
|
|
5cf3624a3a | ||
|
|
c7ff8c2dd1 | ||
|
|
83c202d675 | ||
|
|
f7648e3311 | ||
|
|
c203de082e | ||
|
|
a95ba1acc4 | ||
|
|
db325525e4 | ||
|
|
db97114fb4 | ||
|
|
b18a300f10 | ||
|
|
61ffb857ee | ||
|
|
701212239d | ||
|
|
422fa01c6f | ||
|
|
62820b4dd9 | ||
|
|
8ea92ef330 | ||
|
|
de82249d8d | ||
|
|
94a26ae75a | ||
|
|
f9fdae9de9 | ||
|
|
0cb46039dd | ||
|
|
c4439cc9db | ||
|
|
6cd9640b30 | ||
|
|
f9bce3dfdb | ||
|
|
8eb0c997ed | ||
|
|
a8f96e06bd | ||
|
|
9a2945927f | ||
|
|
89f9249ec6 | ||
|
|
24f572253f | ||
|
|
4fc9c19893 | ||
|
|
f6fcd730a8 | ||
|
|
716a56979d | ||
|
|
538476be99 | ||
|
|
93a170a893 | ||
|
|
e0301f096f | ||
|
|
9e3cb4d694 | ||
|
|
49b76c3e43 | ||
|
|
9962784991 | ||
|
|
6336b38cfc | ||
|
|
2362835275 | ||
|
|
8a4ede9d43 | ||
|
|
cc1595e048 | ||
|
|
ca16763423 | ||
|
|
b6dd5bb881 | ||
|
|
f8e299ec56 | ||
|
|
91e9c6e048 | ||
|
|
b941b97eee | ||
|
|
d38ac652fc | ||
|
|
bdcf3b71ce | ||
|
|
ddbf8b7725 | ||
|
|
a6fd4547a7 | ||
|
|
d20153c569 | ||
|
|
15e072a2ff | ||
|
|
f98e20aa84 | ||
|
|
e7a1b33ae6 | ||
|
|
2d5f23271f | ||
|
|
059110ae7a | ||
|
|
ac84c175af | ||
|
|
3b6014c229 | ||
|
|
9cb265c6f5 | ||
|
|
a47f0ccc12 | ||
|
|
e032f6b33d | ||
|
|
98e179ba06 | ||
|
|
2ebb4fef4c | ||
|
|
e72b120c12 | ||
|
|
7b87b00b44 | ||
|
|
2b793bf242 | ||
|
|
49ae906029 | ||
|
|
4f82a0f026 | ||
|
|
ae8edffdc8 | ||
|
|
2b67c1c631 | ||
|
|
d395cf66a0 | ||
|
|
956ed9e8ae | ||
|
|
63726b09d6 | ||
|
|
f78d42cc30 | ||
|
|
5d1c807a86 | ||
|
|
fad077aad9 | ||
|
|
24f47bee73 | ||
|
|
d93b7b2cb2 | ||
|
|
ab03111a84 | ||
|
|
1ba03b69f6 | ||
|
|
9957f64628 | ||
|
|
6505af2a8b | ||
|
|
54c74bac6e | ||
|
|
5cf4c879dd | ||
|
|
aa00db48ce | ||
|
|
4a158db632 | ||
|
|
f57a0ecba2 | ||
|
|
3614c82632 | ||
|
|
9207d41f17 | ||
|
|
c5abd0ff3f | ||
|
|
2c2bde1e05 | ||
|
|
dcff8c0d9a | ||
|
|
44555e5289 | ||
|
|
9c4eff68a3 | ||
|
|
8f9122c706 | ||
|
|
3eb1b476dd | ||
|
|
0de9f48be4 | ||
|
|
162b482a8b | ||
|
|
2a46358ccf | ||
|
|
8146d6c293 | ||
|
|
5ab067cf86 | ||
|
|
720859197c | ||
|
|
ce064a0b37 | ||
|
|
bfd82fb415 | ||
|
|
655f656781 | ||
|
|
3f32841f49 | ||
|
|
4d7c021925 | ||
|
|
ac923fe669 | ||
|
|
d35b62995e | ||
|
|
ae7d2745db | ||
|
|
5ff47e63bc | ||
|
|
389341f613 | ||
|
|
00b51ad40d | ||
|
|
34c39597f5 | ||
|
|
4516e75b6f | ||
|
|
040518cca8 | ||
|
|
5d336e5fb9 | ||
|
|
e7d0103869 | ||
|
|
55cb10910f | ||
|
|
ecded8af93 | ||
|
|
20826daa18 | ||
|
|
742f1f4622 | ||
|
|
49cf20545f | ||
|
|
289e6f3d1c | ||
|
|
b246d17a33 | ||
|
|
c6b6616ee3 | ||
|
|
d6500c45aa | ||
|
|
6fd79688b0 | ||
|
|
c6478857bc | ||
|
|
8a711ffecb | ||
|
|
139ea879df | ||
|
|
6a0968cc02 | ||
|
|
5a1fa409d8 | ||
|
|
225da163bb | ||
|
|
801ed0fbaf | ||
|
|
ea44fe0f16 | ||
|
|
6081fe3295 | ||
|
|
6df65a0b9d | ||
|
|
0aec9419ec | ||
|
|
bb510a9240 | ||
|
|
cce3e1cfb8 | ||
|
|
4977f6c270 | ||
|
|
fe1715259a | ||
|
|
f4c0d84380 | ||
|
|
8a20584e27 | ||
|
|
218b0adb8f | ||
|
|
7d99607919 | ||
|
|
9adfcc7aec | ||
|
|
2da7463edf | ||
|
|
4a644d8712 | ||
|
|
afa17ca429 | ||
|
|
50708c6942 | ||
|
|
cbdf0a9392 | ||
|
|
b7c8ca2a48 | ||
|
|
3817ba774d | ||
|
|
e8771ea118 | ||
|
|
2f46fbfc7a | ||
|
|
78b0e1bf7e | ||
|
|
19530a9102 | ||
|
|
74051c5649 | ||
|
|
f3f391ab43 | ||
|
|
fc75621f1a | ||
|
|
fc3290271c | ||
|
|
71cd4057a7 | ||
|
|
485b35fbd4 | ||
|
|
172884ace8 | ||
|
|
b788c3745c | ||
|
|
7658cfcdbd | ||
|
|
52c8ea13af | ||
|
|
8f424f3273 | ||
|
|
3d7cf8f7f3 | ||
|
|
930adaf439 | ||
|
|
e5a14557a2 | ||
|
|
6a2ff9d153 | ||
|
|
bea90a7d94 | ||
|
|
e57d6e508a | ||
|
|
219b57a362 | ||
|
|
df8f54f5a4 | ||
|
|
fcbb1849ec | ||
|
|
684334ba22 | ||
|
|
5629215ce4 | ||
|
|
f63b6d7207 | ||
|
|
98dc553938 | ||
|
|
7ee01d9a05 | ||
|
|
dc6a67c2f0 | ||
|
|
affed459df | ||
|
|
8d4b8b02b8 | ||
|
|
8c430a3af0 | ||
|
|
b7573a40d7 | ||
|
|
624696711d | ||
|
|
56828e9e00 | ||
|
|
d2358c9550 | ||
|
|
ab11747fab | ||
|
|
44cb0fa434 | ||
|
|
13814695ac | ||
|
|
377e2eb613 | ||
|
|
bf4725a768 | ||
|
|
ed65abf786 | ||
|
|
8d29fe8679 | ||
|
|
f4f77c62c8 | ||
|
|
2cc08cdea1 | ||
|
|
03dc6d63ed | ||
|
|
bcb3ccec9a | ||
|
|
4bec8efea1 | ||
|
|
58b2c2bd69 | ||
|
|
636776c531 | ||
|
|
ca4a33d408 | ||
|
|
9db158f4d4 | ||
|
|
ea8b179df1 | ||
|
|
efc152e3c8 | ||
|
|
e68827bf3b | ||
|
|
58bf69882f | ||
|
|
915f313efd | ||
|
|
52d29099a2 | ||
|
|
c06fc926a1 | ||
|
|
79ab1a2277 | ||
|
|
7c03630e24 | ||
|
|
34a65419c7 | ||
|
|
7191ece7a5 | ||
|
|
0837f84a43 | ||
|
|
0bc4699cdc | ||
|
|
bb1285c35c | ||
|
|
21fc554589 | ||
|
|
a43af180a7 | ||
|
|
88ea920dfb | ||
|
|
132aac3951 | ||
|
|
7640ed08bc | ||
|
|
1dbf36b86b | ||
|
|
508de10191 | ||
|
|
ccfe259c69 | ||
|
|
0573f80525 | ||
|
|
8fb4e6c4ee | ||
|
|
05b2515b3b | ||
|
|
0ecb339fdf | ||
|
|
92ddebc289 | ||
|
|
1a3f0675bf | ||
|
|
c24019fd57 | ||
|
|
55641a234c | ||
|
|
9f52d364c9 | ||
|
|
edce70bc12 | ||
|
|
b8a7f81f55 | ||
|
|
ef9b2aefe5 | ||
|
|
cd1413a74e | ||
|
|
4e9d93957e | ||
|
|
9c4e9066f9 | ||
|
|
b4d1af2bce | ||
|
|
5ec676c40c | ||
|
|
5096aea5bb | ||
|
|
feedd190dc | ||
|
|
3423fffaca | ||
|
|
1624fd2e28 | ||
|
|
10b3094d5e | ||
|
|
580e638f67 | ||
|
|
e44428f87c | ||
|
|
379f7ef865 | ||
|
|
427f6e4d55 | ||
|
|
07a1e9fc3c | ||
|
|
78d64e8f1b | ||
|
|
559a9a9f3e | ||
|
|
ac6dd23fd6 | ||
|
|
1e515df0b5 | ||
|
|
35490762a6 | ||
|
|
c25e23d3d9 | ||
|
|
8bb8257e62 | ||
|
|
5f096927bd | ||
|
|
434826c125 | ||
|
|
89595cd5dc | ||
|
|
d991e15a94 | ||
|
|
6a1aefa5a5 | ||
|
|
272684e7eb | ||
|
|
9be3eba694 | ||
|
|
5a3fc0fb43 | ||
|
|
47ef8e9568 | ||
|
|
e4285bbc78 | ||
|
|
49b6a42791 | ||
|
|
b62fd602f2 | ||
|
|
923e40ed8f | ||
|
|
3c724a227a | ||
|
|
90d26eb16a | ||
|
|
b629744e1a | ||
|
|
b0ab43c39a | ||
|
|
2c33b381c1 | ||
|
|
c50a80e8df | ||
|
|
bafbd63610 | ||
|
|
557347d42d | ||
|
|
c828aa3bc0 | ||
|
|
376d29e829 | ||
|
|
97ee4f36e3 | ||
|
|
d766f255ef | ||
|
|
19ae9e7456 | ||
|
|
61ea312403 | ||
|
|
13193c9368 | ||
|
|
31e0ce4c64 | ||
|
|
43238aff0a | ||
|
|
d598bfc35b | ||
|
|
1c836918ca | ||
|
|
4a6a3b9269 | ||
|
|
1534f780aa | ||
|
|
4c6ceab8e8 | ||
|
|
021e28aca8 | ||
|
|
334d81db08 | ||
|
|
6ffd45a82a | ||
|
|
2fe3902d8d | ||
|
|
4dceda8251 | ||
|
|
09cf33f530 | ||
|
|
3e851a65e9 | ||
|
|
e8ec536a5a | ||
|
|
967be4451a | ||
|
|
bc65a18f3c | ||
|
|
1eb9c38aee | ||
|
|
ccaad1c305 | ||
|
|
963a22783f | ||
|
|
303a3690e8 | ||
|
|
29fa0818f6 | ||
|
|
1a21a3ed42 | ||
|
|
7baad04e39 | ||
|
|
273293479d | ||
|
|
37fb895d67 | ||
|
|
0dcdd252f5 | ||
|
|
d04d743520 | ||
|
|
63df16a369 | ||
|
|
13209c3236 | ||
|
|
29d1d49aca | ||
|
|
de96aae9a5 | ||
|
|
5f29ee9052 | ||
|
|
b3ecee749e | ||
|
|
1cee1abe00 | ||
|
|
558440168d | ||
|
|
d0cb7ab486 | ||
|
|
c317bc020a | ||
|
|
4065fb77da | ||
|
|
8351f38ee7 | ||
|
|
f3fc01b740 | ||
|
|
a201be5a01 | ||
|
|
ebf2035351 | ||
|
|
6e6e203f8a | ||
|
|
2192149b5a | ||
|
|
a4e19196a7 | ||
|
|
0c744c5444 | ||
|
|
69fc28d5d6 | ||
|
|
4107535b19 | ||
|
|
e0e5fb3d5a | ||
|
|
1125096e5a | ||
|
|
fc1d2269d0 | ||
|
|
cc033d5be7 | ||
|
|
7eee3de965 | ||
|
|
0c6245fe8e | ||
|
|
342ed382e3 | ||
|
|
aaf6c37871 | ||
|
|
65e1346a11 | ||
|
|
7f9307feec | ||
|
|
036eaf3bae | ||
|
|
2717d7d311 | ||
|
|
577b841ee0 | ||
|
|
857eb0517c | ||
|
|
ec50197b40 | ||
|
|
4ace7dd370 | ||
|
|
0eea7f8d4d | ||
|
|
80c7680d17 | ||
|
|
3edc0a7f53 | ||
|
|
29af14f588 | ||
|
|
5f2408b791 | ||
|
|
5b5e8a4fd5 | ||
|
|
71b0c2d83e | ||
|
|
363b7bc314 | ||
|
|
448032c5b7 | ||
|
|
2af1234cfd | ||
|
|
d258235430 | ||
|
|
c060d6ebb1 | ||
|
|
72dab2bc4e | ||
|
|
b0d2a22f62 | ||
|
|
bcda71cb25 | ||
|
|
d32e902d17 | ||
|
|
f91b719542 | ||
|
|
8bccab258a | ||
|
|
6443d8e2bf | ||
|
|
286759f232 | ||
|
|
0dba32fdf2 | ||
|
|
54c6757bc7 | ||
|
|
c91a6640ff | ||
|
|
80ef617949 | ||
|
|
72dd3f92f9 | ||
|
|
5330476dbe | ||
|
|
69fdc85c99 | ||
|
|
f7293508ff | ||
|
|
4aedce9668 | ||
|
|
9244fe5944 | ||
|
|
35710b17d1 | ||
|
|
fb78ce5679 | ||
|
|
749e7dbdf9 | ||
|
|
ccae58cb2f | ||
|
|
64199b91d5 | ||
|
|
c8218f6891 | ||
|
|
8e2f297839 | ||
|
|
0feb9661df | ||
|
|
1acceae81e | ||
|
|
a7ff690891 | ||
|
|
447b54fa4b | ||
|
|
5f5541ca12 | ||
|
|
f101e1b184 | ||
|
|
065417038c | ||
|
|
047c82791b | ||
|
|
f1672c7076 | ||
|
|
e7e57fa412 | ||
|
|
5536fcce00 | ||
|
|
8a3ce36c65 | ||
|
|
325812fe95 | ||
|
|
421a5d27dd | ||
|
|
27b43041f9 | ||
|
|
a7ea12d07d | ||
|
|
927f570283 | ||
|
|
66c1eff79f | ||
|
|
4cb1313a77 | ||
|
|
52bdde40a1 | ||
|
|
8295ed716b | ||
|
|
d84ee57354 | ||
|
|
0ae57b8b7b | ||
|
|
a4e68ea2d6 | ||
|
|
a48b4ccaa8 | ||
|
|
bcaf8e9912 | ||
|
|
ae438f1650 | ||
|
|
563d6bccd3 | ||
|
|
7220d752ac | ||
|
|
46beb21ba7 | ||
|
|
c972f0ac59 | ||
|
|
21c74fbcc8 | ||
|
|
1ca839ab26 | ||
|
|
34aefd32e8 | ||
|
|
fce32e70b9 | ||
|
|
0550c045c7 | ||
|
|
69b1c062f5 | ||
|
|
4713b2f079 | ||
|
|
6fe907a13d | ||
|
|
45ce4ac1ba | ||
|
|
9313f870bc | ||
|
|
9e72e88930 | ||
|
|
dcb64bf0a6 | ||
|
|
5d07070558 | ||
|
|
8c6ba9175b | ||
|
|
ccaa2c48e2 | ||
|
|
5d38bf2e66 | ||
|
|
15331da389 | ||
|
|
477171abac | ||
|
|
dc85e4f4a4 | ||
|
|
ac402a6697 | ||
|
|
f86d35f8d1 | ||
|
|
7d6c04e3cf | ||
|
|
5c059ce9fe | ||
|
|
575bffe0bf | ||
|
|
d0b70253fa | ||
|
|
5f04b2649f | ||
|
|
f0099859bb | ||
|
|
906b654afa | ||
|
|
14740fad58 | ||
|
|
e97a149474 | ||
|
|
c1d1270d59 | ||
|
|
e550918d7c | ||
|
|
f3449babc1 | ||
|
|
e444388517 | ||
|
|
bd2559c37b | ||
|
|
7abf44e893 | ||
|
|
0b94a31d15 | ||
|
|
989e09b610 | ||
|
|
7e69e80290 | ||
|
|
a3177dcfaf | ||
|
|
10e54d7a2d | ||
|
|
ed514a01bb | ||
|
|
47fce4e914 | ||
|
|
54276e19e9 | ||
|
|
193650efd4 | ||
|
|
b7aae7d87b | ||
|
|
2c799d894b | ||
|
|
5745fc1046 | ||
|
|
80085abe16 | ||
|
|
fe5dd065ed | ||
|
|
945fd988b3 | ||
|
|
3bbff0aecf | ||
|
|
9188331c1e | ||
|
|
be5663c468 | ||
|
|
9ac8098f15 | ||
|
|
bd5ee837f4 | ||
|
|
4be6cb2459 | ||
|
|
c466cb68b9 | ||
|
|
820be46ed3 | ||
|
|
4437f206af | ||
|
|
a1f4b35749 | ||
|
|
b38f49a90e | ||
|
|
5d318b2693 | ||
|
|
c7b9f9e50a | ||
|
|
256d628543 | ||
|
|
508641d1e8 | ||
|
|
61e2dde400 | ||
|
|
85ae862381 | ||
|
|
7a9b7c87a4 | ||
|
|
8f033910ce | ||
|
|
38b5e95842 | ||
|
|
2c67586873 | ||
|
|
b99e6c9a21 | ||
|
|
49944cda87 | ||
|
|
3b36b2a4dc | ||
|
|
1dfcffe70d | ||
|
|
a9b3dcd2c2 | ||
|
|
31f9145d3f | ||
|
|
ba04b94964 | ||
|
|
4ecf99c17e | ||
|
|
80389ff236 | ||
|
|
9e80b23726 | ||
|
|
494a1c49f9 | ||
|
|
4a77064826 | ||
|
|
ce90f10243 | ||
|
|
426aa4e41d | ||
|
|
bdc953cab0 | ||
|
|
15725a9f38 | ||
|
|
cc7d290feb | ||
|
|
40a2a46a5e | ||
|
|
2e160b0b0b | ||
|
|
5aaba102a7 | ||
|
|
52e459ec60 | ||
|
|
4a30819ea5 | ||
|
|
27969a1f65 | ||
|
|
c68b13b075 | ||
|
|
1446aab451 | ||
|
|
86f77fde1a | ||
|
|
02134dc959 | ||
|
|
c27b02512f | ||
|
|
222e76ce47 | ||
|
|
0efb32c891 | ||
|
|
e808964913 | ||
|
|
9ed1e896cb | ||
|
|
49e521404a | ||
|
|
2ae34b856a | ||
|
|
6230ad971b | ||
|
|
20caad24ed | ||
|
|
eabdd3b11f | ||
|
|
8fad743e85 | ||
|
|
f9fd015ecb | ||
|
|
27de5ae387 | ||
|
|
4f43f10672 | ||
|
|
fb45ef432e | ||
|
|
d0a8e33bf2 | ||
|
|
5a19024bec | ||
|
|
e0635f7ead | ||
|
|
6fa5efc4ca | ||
|
|
7394a23a83 | ||
|
|
bbe4de996a | ||
|
|
7030e752fc | ||
|
|
d845f8b7e3 | ||
|
|
8a18951562 | ||
|
|
cb9433902c | ||
|
|
472e1ce0a3 | ||
|
|
5e85c52a57 | ||
|
|
6a06a24296 | ||
|
|
99f04d71af | ||
|
|
d1b8a36b93 | ||
|
|
f20da0f049 | ||
|
|
5d3ab01176 | ||
|
|
83cd91f1d1 | ||
|
|
5f39d8e594 | ||
|
|
6ff60e556e | ||
|
|
5b7f44f4ea | ||
|
|
dc906bfb0f | ||
|
|
b70c9d4f00 | ||
|
|
03e0584279 | ||
|
|
960ee342e4 | ||
|
|
f5a5114999 | ||
|
|
e6d9237bda | ||
|
|
c831d57614 | ||
|
|
c5904303e3 | ||
|
|
586a57c2c9 | ||
|
|
91fb861fd3 | ||
|
|
b13655e951 | ||
|
|
e064ee4263 | ||
|
|
60f926924b | ||
|
|
97c3b9002a | ||
|
|
78ec0f1ea3 | ||
|
|
c0b74d83a5 | ||
|
|
9dd172df98 | ||
|
|
d3659858eb | ||
|
|
b637f5c3dd | ||
|
|
05ab3c3b7b | ||
|
|
f9d5a9a3b5 | ||
|
|
82aec6f1ee | ||
|
|
c39a9a4da7 | ||
|
|
9d1cd0477a | ||
|
|
1e998fccbb | ||
|
|
2fcd48d4f2 | ||
|
|
4e79bb120a | ||
|
|
2d85734703 | ||
|
|
ccb0ac63e1 |
@@ -39,6 +39,9 @@ if [ -d /var/www/html/var/db ]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
# Start PHP-FPM
|
||||
service php8.1-fpm start
|
||||
|
||||
# first arg is `-f` or `--some-option` (taken from https://github.com/docker-library/php/blob/master/8.2/bullseye/apache/docker-php-entrypoint)
|
||||
if [ "${1#-}" != "$1" ]; then
|
||||
set -- apache2-foreground "$@"
|
||||
|
||||
@@ -26,13 +26,21 @@
|
||||
|
||||
# Pass the configuration from the docker env to the PHP environment (here you should list all .env options)
|
||||
PassEnv APP_ENV APP_DEBUG APP_SECRET
|
||||
PassEnv DATABASE_URL
|
||||
PassEnv DEFAULT_LANG DEFAULT_TIMEZONE BASE_CURRENCY INSTANCE_NAME ALLOW_ATTACHMENT_DOWNLOADS USE_GRAVATAR
|
||||
PassEnv TRUSTED_PROXIES TRUSTED_HOSTS LOCK_DSN
|
||||
PassEnv DATABASE_URL ENFORCE_CHANGE_COMMENTS_FOR
|
||||
PassEnv DEFAULT_LANG DEFAULT_TIMEZONE BASE_CURRENCY INSTANCE_NAME ALLOW_ATTACHMENT_DOWNLOADS USE_GRAVATAR MAX_ATTACHMENT_FILE_SIZE DEFAULT_URI CHECK_FOR_UPDATES
|
||||
PassEnv MAILER_DSN ALLOW_EMAIL_PW_RESET EMAIL_SENDER_EMAIL EMAIL_SENDER_NAME
|
||||
PassEnv HISTORY_SAVE_CHANGED_FIELDS HISTORY_SAVE_CHANGED_DATA HISTORY_SAVE_REMOVED_DATA
|
||||
PassEnv HISTORY_SAVE_CHANGED_FIELDS HISTORY_SAVE_CHANGED_DATA HISTORY_SAVE_REMOVED_DATA HISTORY_SAVE_NEW_DATA
|
||||
PassEnv ERROR_PAGE_ADMIN_EMAIL ERROR_PAGE_SHOW_HELP
|
||||
PassEnv DEMO_MODE NO_URL_REWRITE_AVAILABLE FIXER_API_KEY BANNER
|
||||
# In old version the SAML sp private key env, was wrongly named SAMLP_SP_PRIVATE_KEY, keep it for backward compatibility
|
||||
PassEnv SAML_ENABLED SAML_ROLE_MAPPING SAML_UPDATE_GROUP_ON_LOGIN SAML_IDP_ENTITY_ID SAML_IDP_SINGLE_SIGN_ON_SERVICE SAML_IDP_SINGLE_LOGOUT_SERVICE SAML_IDP_X509_CERT SAML_SP_ENTITY_ID SAML_SP_X509_CERT SAML_SP_PRIVATE_KEY SAMLP_SP_PRIVATE_KEY
|
||||
PassEnv TABLE_DEFAULT_PAGE_SIZE
|
||||
|
||||
PassEnv PROVIDER_DIGIKEY_CLIENT_ID PROVIDER_DIGIKEY_SECRET PROVIDER_DIGIKEY_CURRENCY PROVIDER_DIGIKEY_LANGUAGE PROVIDER_DIGIKEY_COUNTRY
|
||||
PassEnv PROVIDER_ELEMENT14_KEY PROVIDER_ELEMENT14_STORE_ID
|
||||
PassEnv PROVIDER_TME_KEY PROVIDER_TME_SECRET PROVIDER_TME_CURRENCY PROVIDER_TME_LANGUAGE PROVIDER_TME_COUNTRY PROVIDER_TME_GET_GROSS_PRICES
|
||||
PassEnv PROVIDER_OCTOPART_CLIENT_ID PROVIDER_OCTOPART_SECRET PROVIDER_OCTOPART_CURRENCY PROVIDER_OCTOPART_COUNTRY PROVIDER_OCTOPART_SEARCH_LIMIT PROVIDER_OCTOPART_ONLY_AUTHORIZED_SELLERS
|
||||
|
||||
# For most configuration files from conf-available/, which are
|
||||
# enabled or disabled at a global level, it is possible to
|
||||
|
||||
109
.env
109
.env
@@ -31,6 +31,21 @@ INSTANCE_NAME="Part-DB"
|
||||
ALLOW_ATTACHMENT_DOWNLOADS=0
|
||||
# Use gravatars for user avatars, when user has no own avatar defined
|
||||
USE_GRAVATAR=0
|
||||
# The maximum allowed size for attachment files in bytes (you can use M for megabytes and G for gigabytes)
|
||||
# Please note that the php.ini setting upload_max_filesize also limits the maximum size of uploaded files
|
||||
MAX_ATTACHMENT_FILE_SIZE="100M"
|
||||
|
||||
# The public reachable URL of this Part-DB installation. This is used for generating links to the website in emails and so on
|
||||
# This must end with a slash!
|
||||
DEFAULT_URI="https://partdb.changeme.invalid/"
|
||||
|
||||
# With this option you can configure, where users are enforced to give a change reason, which will be logged
|
||||
# This is a comma separated list of values, see documentation for available values
|
||||
# Leave this empty, to make all change reasons optional
|
||||
ENFORCE_CHANGE_COMMENTS_FOR=""
|
||||
|
||||
# Disable that if you do not want that Part-DB connects to GitHub to check for available updates, or if your server can not connect to the internet
|
||||
CHECK_FOR_UPDATES=1
|
||||
|
||||
###################################################################################
|
||||
# Email settings
|
||||
@@ -59,6 +74,9 @@ HISTORY_SAVE_CHANGED_FIELDS=1
|
||||
HISTORY_SAVE_CHANGED_DATA=1
|
||||
# Save the data of an element that gets removed into log entry. This allows to undelete an element
|
||||
HISTORY_SAVE_REMOVED_DATA=1
|
||||
# Save the new data of an element that gets changed or added. This allows an easy comparison of the old and new data on the detail page
|
||||
# This option only becomes active when HISTORY_SAVE_CHANGED_DATA is set to 1
|
||||
HISTORY_SAVE_NEW_DATA=1
|
||||
|
||||
###################################################################################
|
||||
# Error pages settings
|
||||
@@ -69,6 +87,97 @@ ERROR_PAGE_ADMIN_EMAIL=''
|
||||
# If this is set to true, solutions to common problems are shown on error pages. Disable this, if you do not want your users to see them...
|
||||
ERROR_PAGE_SHOW_HELP=1
|
||||
|
||||
##################################################################################
|
||||
# Part table settings
|
||||
##################################################################################
|
||||
|
||||
# The default page size for the part table (set to -1 to show all parts on one page)
|
||||
TABLE_DEFAULT_PAGE_SIZE=50
|
||||
|
||||
##################################################################################
|
||||
# Info provider settings
|
||||
##################################################################################
|
||||
|
||||
# Digikey Provider:
|
||||
# You can get your client id and secret from https://developer.digikey.com/
|
||||
PROVIDER_DIGIKEY_CLIENT_ID=
|
||||
PROVIDER_DIGIKEY_SECRET=
|
||||
# The currency to get prices in
|
||||
PROVIDER_DIGIKEY_CURRENCY=EUR
|
||||
# The language to get results in (en, de, fr, it, es, zh, ja, ko)
|
||||
PROVIDER_DIGIKEY_LANGUAGE=en
|
||||
# The country to get results for
|
||||
PROVIDER_DIGIKEY_COUNTRY=DE
|
||||
|
||||
# Farnell Provider:
|
||||
# You can get your API key from https://partner.element14.com/
|
||||
PROVIDER_ELEMENT14_KEY=
|
||||
# Configure the store domain you want to use. This decides the language and currency of results. You can get a list of available stores from https://partner.element14.com/docs/Product_Search_API_REST__Description
|
||||
PROVIDER_ELEMENT14_STORE_ID=de.farnell.com
|
||||
|
||||
# TME Provider:
|
||||
# You can get your API key from https://developers.tme.eu/en/
|
||||
PROVIDER_TME_KEY=
|
||||
PROVIDER_TME_SECRET=
|
||||
# The currency to get prices in
|
||||
PROVIDER_TME_CURRENCY=EUR
|
||||
# The language to get results in (en, de, pl)
|
||||
PROVIDER_TME_LANGUAGE=en
|
||||
# The country to get results for
|
||||
PROVIDER_TME_COUNTRY=DE
|
||||
# Set this to 1 to get gross prices (including VAT) instead of net prices
|
||||
PROVIDER_TME_GET_GROSS_PRICES=1
|
||||
|
||||
# Octopart / Nexar Provider:
|
||||
# You can get your API key from https://nexar.com/api
|
||||
PROVIDER_OCTOPART_CLIENT_ID=
|
||||
PROVIDER_OCTOPART_SECRET=
|
||||
# The currency and country to get prices for (you have to set both to get meaningful results)
|
||||
# 3 letter ISO currency code (e.g. EUR, USD, GBP)
|
||||
PROVIDER_OCTOPART_CURRENCY=EUR
|
||||
# 2 letter ISO country code (e.g. DE, US, GB)
|
||||
PROVIDER_OCTOPART_COUNTRY=DE
|
||||
# The number of results to get from Octopart while searching (please note that this counts towards your API limits)
|
||||
PROVIDER_OCTOPART_SEARCH_LIMIT=10
|
||||
# Set to false to include non authorized offers in the results
|
||||
PROVIDER_OCTOPART_ONLY_AUTHORIZED_SELLERS=1
|
||||
|
||||
|
||||
###################################################################################
|
||||
# SAML Single sign on-settings
|
||||
###################################################################################
|
||||
# Set this to 1 to enable SAML single sign on
|
||||
SAML_ENABLED=0
|
||||
|
||||
# A JSON encoded array of role mappings in the form { "saml_role": PARTDB_GROUP_ID, "*": PARTDB_GROUP_ID }
|
||||
# The first match is used, so the order is important! Put the group mapping with the most privileges first.
|
||||
# Please not to only use single quotes to enclose the JSON string
|
||||
SAML_ROLE_MAPPING='{}'
|
||||
# A mapping could look like the following
|
||||
#SAML_ROLE_MAPPING='{ "*": 2, "admin": 1, "editor": 3}'
|
||||
|
||||
# When this is set to 1, the group of SAML users will be updated everytime they login based on their SAML roles
|
||||
SAML_UPDATE_GROUP_ON_LOGIN=1
|
||||
|
||||
# The entity ID of your SAML IDP (e.g. the realm name of your Keycloak server)
|
||||
SAML_IDP_ENTITY_ID="https://idp.changeme.invalid/realms/master"
|
||||
# The URL of your SAML IDP SingleSignOnService (e.g. the endpoint of your Keycloak server)
|
||||
SAML_IDP_SINGLE_SIGN_ON_SERVICE="https://idp.changeme.invalid/realms/master/protocol/saml"
|
||||
# The URL of your SAML IDP SingleLogoutService (e.g. the endpoint of your Keycloak server)
|
||||
SAML_IDP_SINGLE_LOGOUT_SERVICE="https://idp.changeme.invalid/realms/master/protocol/saml"
|
||||
# The public certificate of the SAML IDP (e.g. the certificate of your Keycloak server)
|
||||
SAML_IDP_X509_CERT="MIIC..."
|
||||
|
||||
# The entity of your SAML SP, must match the SP entityID configured in your SAML IDP (e.g. Keycloak).
|
||||
# This should be a the domain name of your Part-DB installation, followed by "/sp"
|
||||
SAML_SP_ENTITY_ID="https://partdb.changeme.invalid/sp"
|
||||
|
||||
# The public certificate of the SAML SP
|
||||
SAML_SP_X509_CERT="MIIC..."
|
||||
# The private key of the SAML SP
|
||||
SAML_SP_PRIVATE_KEY="MIIE..."
|
||||
|
||||
|
||||
######################################################################################
|
||||
# Other settings
|
||||
######################################################################################
|
||||
|
||||
2
.gitattributes
vendored
Normal file
2
.gitattributes
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
# For sh files, always use LF line endings
|
||||
*.sh text eol=lf
|
||||
752
.github/assets/legacy_import/db_jbtronics.sql
vendored
Normal file
752
.github/assets/legacy_import/db_jbtronics.sql
vendored
Normal file
@@ -0,0 +1,752 @@
|
||||
-- phpMyAdmin SQL Dump
|
||||
-- version 5.1.3
|
||||
-- https://www.phpmyadmin.net/
|
||||
--
|
||||
-- Host: 127.0.0.1
|
||||
-- Erstellungszeit: 07. Mai 2023 um 01:58
|
||||
-- Server-Version: 10.6.5-MariaDB-log
|
||||
-- PHP-Version: 8.1.2
|
||||
|
||||
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
|
||||
START TRANSACTION;
|
||||
SET time_zone = "+00:00";
|
||||
|
||||
|
||||
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
|
||||
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
|
||||
/*!40101 SET NAMES utf8mb4 */;
|
||||
|
||||
--
|
||||
-- Datenbank: `partdb_demo`
|
||||
--
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabellenstruktur für Tabelle `attachements`
|
||||
--
|
||||
|
||||
CREATE TABLE `attachements` (
|
||||
`id` int(11) NOT NULL,
|
||||
`name` tinytext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`class_name` varchar(255) COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`element_id` int(11) NOT NULL,
|
||||
`type_id` int(11) NOT NULL,
|
||||
`filename` mediumtext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`show_in_table` tinyint(1) NOT NULL DEFAULT 0,
|
||||
`last_modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
|
||||
|
||||
--
|
||||
-- Daten für Tabelle `attachements`
|
||||
--
|
||||
|
||||
INSERT INTO `attachements` (`id`, `name`, `class_name`, `element_id`, `type_id`, `filename`, `show_in_table`, `last_modified`) VALUES
|
||||
(1, 'BC547', 'Part', 2, 2, '%BASE%/data/media/bc547.pdf', 1, '0000-00-00 00:00:00');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabellenstruktur für Tabelle `attachement_types`
|
||||
--
|
||||
|
||||
CREATE TABLE `attachement_types` (
|
||||
`id` int(11) NOT NULL,
|
||||
`name` tinytext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`parent_id` int(11) DEFAULT NULL,
|
||||
`comment` text COLLATE utf8mb3_unicode_ci DEFAULT NULL,
|
||||
`datetime_added` timestamp NOT NULL DEFAULT current_timestamp(),
|
||||
`last_modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
|
||||
|
||||
--
|
||||
-- Daten für Tabelle `attachement_types`
|
||||
--
|
||||
|
||||
INSERT INTO `attachement_types` (`id`, `name`, `parent_id`, `comment`, `datetime_added`, `last_modified`) VALUES
|
||||
(1, 'Bilder', NULL, NULL, '2017-10-21 17:58:48', '0000-00-00 00:00:00'),
|
||||
(2, 'Datenblätter', NULL, NULL, '2017-10-21 17:58:48', '0000-00-00 00:00:00');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabellenstruktur für Tabelle `categories`
|
||||
--
|
||||
|
||||
CREATE TABLE `categories` (
|
||||
`id` int(11) NOT NULL,
|
||||
`name` tinytext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`parent_id` int(11) DEFAULT NULL,
|
||||
`disable_footprints` tinyint(1) NOT NULL DEFAULT 0,
|
||||
`disable_manufacturers` tinyint(1) NOT NULL DEFAULT 0,
|
||||
`disable_autodatasheets` tinyint(1) NOT NULL DEFAULT 0,
|
||||
`disable_properties` tinyint(1) NOT NULL DEFAULT 0,
|
||||
`partname_regex` text COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`partname_hint` text COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`default_description` text COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`default_comment` text COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`comment` text COLLATE utf8mb3_unicode_ci DEFAULT NULL,
|
||||
`datetime_added` timestamp NOT NULL DEFAULT current_timestamp(),
|
||||
`last_modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
|
||||
|
||||
--
|
||||
-- Daten für Tabelle `categories`
|
||||
--
|
||||
|
||||
INSERT INTO `categories` (`id`, `name`, `parent_id`, `disable_footprints`, `disable_manufacturers`, `disable_autodatasheets`, `disable_properties`, `partname_regex`, `partname_hint`, `default_description`, `default_comment`, `comment`, `datetime_added`, `last_modified`) VALUES
|
||||
(1, 'aktive Bauteile', NULL, 0, 0, 0, 0, '', '', '', '', NULL, '2017-10-21 17:58:49', '0000-00-00 00:00:00');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabellenstruktur für Tabelle `devices`
|
||||
--
|
||||
|
||||
CREATE TABLE `devices` (
|
||||
`id` int(11) NOT NULL,
|
||||
`name` tinytext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`parent_id` int(11) DEFAULT NULL,
|
||||
`order_quantity` int(11) NOT NULL DEFAULT 0,
|
||||
`order_only_missing_parts` tinyint(1) NOT NULL DEFAULT 0,
|
||||
`datetime_added` timestamp NOT NULL DEFAULT current_timestamp(),
|
||||
`last_modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||
`comment` text COLLATE utf8mb3_unicode_ci DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
|
||||
|
||||
--
|
||||
-- Daten für Tabelle `devices`
|
||||
--
|
||||
|
||||
INSERT INTO `devices` (`id`, `name`, `parent_id`, `order_quantity`, `order_only_missing_parts`, `datetime_added`, `last_modified`, `comment`) VALUES
|
||||
(1, 'Test', NULL, 0, 0, '2015-04-16 15:08:56', '0000-00-00 00:00:00', NULL);
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabellenstruktur für Tabelle `device_parts`
|
||||
--
|
||||
|
||||
CREATE TABLE `device_parts` (
|
||||
`id` int(11) NOT NULL,
|
||||
`id_part` int(11) NOT NULL DEFAULT 0,
|
||||
`id_device` int(11) NOT NULL DEFAULT 0,
|
||||
`quantity` int(11) NOT NULL DEFAULT 0,
|
||||
`mountnames` mediumtext COLLATE utf8mb3_unicode_ci NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
|
||||
|
||||
--
|
||||
-- Daten für Tabelle `device_parts`
|
||||
--
|
||||
|
||||
INSERT INTO `device_parts` (`id`, `id_part`, `id_device`, `quantity`, `mountnames`) VALUES
|
||||
(1, 2, 1, 1, '');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabellenstruktur für Tabelle `footprints`
|
||||
--
|
||||
|
||||
CREATE TABLE `footprints` (
|
||||
`id` int(11) NOT NULL,
|
||||
`name` tinytext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`filename` mediumtext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`filename_3d` mediumtext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`parent_id` int(11) DEFAULT NULL,
|
||||
`comment` text COLLATE utf8mb3_unicode_ci DEFAULT NULL,
|
||||
`datetime_added` timestamp NOT NULL DEFAULT current_timestamp(),
|
||||
`last_modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
|
||||
|
||||
--
|
||||
-- Daten für Tabelle `footprints`
|
||||
--
|
||||
|
||||
INSERT INTO `footprints` (`id`, `name`, `filename`, `filename_3d`, `parent_id`, `comment`, `datetime_added`, `last_modified`) VALUES
|
||||
(1, 'LEDs', '%BASE%/img/footprints/Optik/LEDs/Bedrahtet/LED-GELB_3MM.png', '', NULL, NULL, '2017-10-21 17:58:49', '0000-00-00 00:00:00');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabellenstruktur für Tabelle `groups`
|
||||
--
|
||||
|
||||
CREATE TABLE `groups` (
|
||||
`id` int(11) NOT NULL,
|
||||
`name` varchar(32) NOT NULL,
|
||||
`parent_id` int(11) DEFAULT NULL,
|
||||
`comment` mediumtext DEFAULT NULL,
|
||||
`perms_system` int(11) NOT NULL,
|
||||
`perms_groups` int(11) NOT NULL,
|
||||
`perms_users` int(11) NOT NULL,
|
||||
`perms_self` int(11) NOT NULL,
|
||||
`perms_system_config` int(11) NOT NULL,
|
||||
`perms_system_database` int(11) NOT NULL,
|
||||
`perms_parts` bigint(11) NOT NULL,
|
||||
`perms_parts_name` smallint(6) NOT NULL,
|
||||
`perms_parts_description` smallint(6) NOT NULL,
|
||||
`perms_parts_instock` smallint(6) NOT NULL,
|
||||
`perms_parts_mininstock` smallint(6) NOT NULL,
|
||||
`perms_parts_footprint` smallint(6) NOT NULL,
|
||||
`perms_parts_storelocation` smallint(6) NOT NULL,
|
||||
`perms_parts_manufacturer` smallint(6) NOT NULL,
|
||||
`perms_parts_comment` smallint(6) NOT NULL,
|
||||
`perms_parts_order` smallint(6) NOT NULL,
|
||||
`perms_parts_orderdetails` smallint(6) NOT NULL,
|
||||
`perms_parts_prices` smallint(6) NOT NULL,
|
||||
`perms_parts_attachements` smallint(6) NOT NULL,
|
||||
`perms_devices` int(11) NOT NULL,
|
||||
`perms_devices_parts` int(11) NOT NULL,
|
||||
`perms_storelocations` int(11) NOT NULL,
|
||||
`perms_footprints` int(11) NOT NULL,
|
||||
`perms_categories` int(11) NOT NULL,
|
||||
`perms_suppliers` int(11) NOT NULL,
|
||||
`perms_manufacturers` int(11) NOT NULL,
|
||||
`perms_attachement_types` int(11) NOT NULL,
|
||||
`perms_tools` int(11) NOT NULL,
|
||||
`perms_labels` smallint(6) NOT NULL,
|
||||
`datetime_added` timestamp NOT NULL DEFAULT current_timestamp(),
|
||||
`last_modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
|
||||
|
||||
--
|
||||
-- Daten für Tabelle `groups`
|
||||
--
|
||||
|
||||
INSERT INTO `groups` (`id`, `name`, `parent_id`, `comment`, `perms_system`, `perms_groups`, `perms_users`, `perms_self`, `perms_system_config`, `perms_system_database`, `perms_parts`, `perms_parts_name`, `perms_parts_description`, `perms_parts_instock`, `perms_parts_mininstock`, `perms_parts_footprint`, `perms_parts_storelocation`, `perms_parts_manufacturer`, `perms_parts_comment`, `perms_parts_order`, `perms_parts_orderdetails`, `perms_parts_prices`, `perms_parts_attachements`, `perms_devices`, `perms_devices_parts`, `perms_storelocations`, `perms_footprints`, `perms_categories`, `perms_suppliers`, `perms_manufacturers`, `perms_attachement_types`, `perms_tools`, `perms_labels`, `datetime_added`, `last_modified`) VALUES
|
||||
(1, 'admins', NULL, 'Users of this group can do everything: Read, Write and Administrative actions.', 21, 1365, 87381, 85, 85, 21, 1431655765, 5, 5, 5, 5, 5, 5, 5, 5, 5, 325, 325, 325, 5461, 325, 5461, 5461, 5461, 5461, 5461, 1365, 1365, 85, '2017-10-21 17:58:46', '2018-10-08 17:27:41'),
|
||||
(2, 'readonly', NULL, 'Users of this group can only read informations, use tools, and don\'t have access to administrative tools.', 2, 2730, 43690, 25, 170, 42, 2778027689, 9, 9, 9, 9, 9, 9, 9, 9, 9, 649, 649, 649, 1705, 649, 1705, 1705, 1705, 1705, 1705, 681, 1366, 165, '2017-10-21 17:58:46', '2018-10-08 17:28:35'),
|
||||
(3, 'users', NULL, 'Users of this group, can edit part informations, create new ones, etc. but are not allowed to use administrative tools. (But can read current configuration, and see Server status)', 42, 2730, 43689, 89, 105, 41, 1431655765, 5, 5, 5, 5, 5, 5, 5, 5, 5, 325, 325, 325, 5461, 325, 5461, 5461, 5461, 5461, 5461, 1365, 1365, 85, '2017-10-21 17:58:46', '2018-10-08 17:28:17');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabellenstruktur für Tabelle `internal`
|
||||
--
|
||||
|
||||
CREATE TABLE `internal` (
|
||||
`keyName` char(30) CHARACTER SET ascii NOT NULL,
|
||||
`keyValue` varchar(255) COLLATE utf8mb3_unicode_ci DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
|
||||
|
||||
--
|
||||
-- Daten für Tabelle `internal`
|
||||
--
|
||||
|
||||
INSERT INTO `internal` (`keyName`, `keyValue`) VALUES
|
||||
('dbVersion', '26');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabellenstruktur für Tabelle `log`
|
||||
--
|
||||
|
||||
CREATE TABLE `log` (
|
||||
`id` int(11) NOT NULL,
|
||||
`datetime` timestamp NOT NULL DEFAULT current_timestamp(),
|
||||
`id_user` int(11) NOT NULL,
|
||||
`level` tinyint(4) NOT NULL,
|
||||
`type` smallint(6) NOT NULL,
|
||||
`target_id` int(11) NOT NULL,
|
||||
`target_type` smallint(6) NOT NULL,
|
||||
`extra` mediumtext NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabellenstruktur für Tabelle `manufacturers`
|
||||
--
|
||||
|
||||
CREATE TABLE `manufacturers` (
|
||||
`id` int(11) NOT NULL,
|
||||
`name` tinytext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`parent_id` int(11) DEFAULT NULL,
|
||||
`address` mediumtext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`phone_number` tinytext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`fax_number` tinytext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`email_address` tinytext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`website` tinytext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`auto_product_url` tinytext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`datetime_added` timestamp NOT NULL DEFAULT current_timestamp(),
|
||||
`comment` text COLLATE utf8mb3_unicode_ci DEFAULT NULL,
|
||||
`last_modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
|
||||
|
||||
--
|
||||
-- Daten für Tabelle `manufacturers`
|
||||
--
|
||||
|
||||
INSERT INTO `manufacturers` (`id`, `name`, `parent_id`, `address`, `phone_number`, `fax_number`, `email_address`, `website`, `auto_product_url`, `datetime_added`, `comment`, `last_modified`) VALUES
|
||||
(1, 'Atmel', NULL, '', '', '', '', '', '', '2015-03-01 11:27:10', NULL, '0000-00-00 00:00:00');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabellenstruktur für Tabelle `orderdetails`
|
||||
--
|
||||
|
||||
CREATE TABLE `orderdetails` (
|
||||
`id` int(11) NOT NULL,
|
||||
`part_id` int(11) NOT NULL,
|
||||
`id_supplier` int(11) NOT NULL DEFAULT 0,
|
||||
`supplierpartnr` tinytext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`obsolete` tinyint(1) DEFAULT 0,
|
||||
`supplier_product_url` tinytext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`datetime_added` timestamp NOT NULL DEFAULT current_timestamp()
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabellenstruktur für Tabelle `parts`
|
||||
--
|
||||
|
||||
CREATE TABLE `parts` (
|
||||
`id` int(11) NOT NULL,
|
||||
`id_category` int(11) NOT NULL DEFAULT 0,
|
||||
`name` mediumtext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`description` mediumtext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`instock` int(11) NOT NULL DEFAULT 0,
|
||||
`mininstock` int(11) NOT NULL DEFAULT 0,
|
||||
`comment` mediumtext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`visible` tinyint(1) NOT NULL,
|
||||
`id_footprint` int(11) DEFAULT NULL,
|
||||
`id_storelocation` int(11) DEFAULT NULL,
|
||||
`order_orderdetails_id` int(11) DEFAULT NULL,
|
||||
`order_quantity` int(11) NOT NULL DEFAULT 1,
|
||||
`manual_order` tinyint(1) NOT NULL DEFAULT 0,
|
||||
`id_manufacturer` int(11) DEFAULT NULL,
|
||||
`id_master_picture_attachement` int(11) DEFAULT NULL,
|
||||
`manufacturer_product_url` tinytext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`datetime_added` timestamp NOT NULL DEFAULT current_timestamp(),
|
||||
`last_modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||
`favorite` tinyint(1) NOT NULL DEFAULT 0
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
|
||||
|
||||
--
|
||||
-- Daten für Tabelle `parts`
|
||||
--
|
||||
|
||||
INSERT INTO `parts` (`id`, `id_category`, `name`, `description`, `instock`, `mininstock`, `comment`, `visible`, `id_footprint`, `id_storelocation`, `order_orderdetails_id`, `order_quantity`, `manual_order`, `id_manufacturer`, `id_master_picture_attachement`, `manufacturer_product_url`, `datetime_added`, `last_modified`, `favorite`) VALUES
|
||||
(2, 1, 'BC547C', 'NPN 45V 0,1A 0,5W', 59, 0, '', 0, 1, 1, NULL, 1, 0, NULL, NULL, '', '2015-03-01 10:40:31', '2016-12-26 10:48:49', 0);
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabellenstruktur für Tabelle `pricedetails`
|
||||
--
|
||||
|
||||
CREATE TABLE `pricedetails` (
|
||||
`id` int(11) NOT NULL,
|
||||
`orderdetails_id` int(11) NOT NULL,
|
||||
`price` decimal(11,5) DEFAULT NULL,
|
||||
`price_related_quantity` int(11) NOT NULL DEFAULT 1,
|
||||
`min_discount_quantity` int(11) NOT NULL DEFAULT 1,
|
||||
`manual_input` tinyint(1) NOT NULL DEFAULT 1,
|
||||
`last_modified` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp()
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabellenstruktur für Tabelle `storelocations`
|
||||
--
|
||||
|
||||
CREATE TABLE `storelocations` (
|
||||
`id` int(11) NOT NULL,
|
||||
`name` tinytext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`parent_id` int(11) DEFAULT NULL,
|
||||
`is_full` tinyint(1) NOT NULL DEFAULT 0,
|
||||
`datetime_added` timestamp NOT NULL DEFAULT current_timestamp(),
|
||||
`comment` text COLLATE utf8mb3_unicode_ci DEFAULT NULL,
|
||||
`last_modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
|
||||
|
||||
--
|
||||
-- Daten für Tabelle `storelocations`
|
||||
--
|
||||
|
||||
INSERT INTO `storelocations` (`id`, `name`, `parent_id`, `is_full`, `datetime_added`, `comment`, `last_modified`) VALUES
|
||||
(1, 'Halbleiter I', NULL, 0, '2015-03-01 11:26:37', NULL, '0000-00-00 00:00:00');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabellenstruktur für Tabelle `suppliers`
|
||||
--
|
||||
|
||||
CREATE TABLE `suppliers` (
|
||||
`id` int(11) NOT NULL,
|
||||
`name` tinytext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`parent_id` int(11) DEFAULT NULL,
|
||||
`address` mediumtext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`phone_number` tinytext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`fax_number` tinytext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`email_address` tinytext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`website` tinytext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`auto_product_url` tinytext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`datetime_added` timestamp NOT NULL DEFAULT current_timestamp(),
|
||||
`comment` text COLLATE utf8mb3_unicode_ci DEFAULT NULL,
|
||||
`last_modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
|
||||
|
||||
--
|
||||
-- Daten für Tabelle `suppliers`
|
||||
--
|
||||
|
||||
INSERT INTO `suppliers` (`id`, `name`, `parent_id`, `address`, `phone_number`, `fax_number`, `email_address`, `website`, `auto_product_url`, `datetime_added`, `comment`, `last_modified`) VALUES
|
||||
(1, 'Test', NULL, '', '', '', '', '', 'Test', '2015-03-01 10:37:23', NULL, '0000-00-00 00:00:00');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabellenstruktur für Tabelle `users`
|
||||
--
|
||||
|
||||
CREATE TABLE `users` (
|
||||
`id` int(11) NOT NULL,
|
||||
`name` varchar(32) NOT NULL,
|
||||
`password` varchar(255) DEFAULT NULL,
|
||||
`first_name` tinytext DEFAULT NULL,
|
||||
`last_name` tinytext DEFAULT NULL,
|
||||
`department` tinytext DEFAULT NULL,
|
||||
`email` tinytext DEFAULT NULL,
|
||||
`need_pw_change` tinyint(1) NOT NULL DEFAULT 0,
|
||||
`group_id` int(11) DEFAULT NULL,
|
||||
`config_language` tinytext DEFAULT NULL,
|
||||
`config_timezone` tinytext DEFAULT NULL,
|
||||
`config_theme` tinytext DEFAULT NULL,
|
||||
`config_currency` tinytext DEFAULT NULL,
|
||||
`config_image_path` text NOT NULL,
|
||||
`config_instock_comment_w` text NOT NULL,
|
||||
`config_instock_comment_a` text NOT NULL,
|
||||
`perms_system` int(11) NOT NULL,
|
||||
`perms_groups` int(11) NOT NULL,
|
||||
`perms_users` int(11) NOT NULL,
|
||||
`perms_self` int(11) NOT NULL,
|
||||
`perms_system_config` int(11) NOT NULL,
|
||||
`perms_system_database` int(11) NOT NULL,
|
||||
`perms_parts` bigint(11) NOT NULL,
|
||||
`perms_parts_name` smallint(6) NOT NULL,
|
||||
`perms_parts_description` smallint(6) NOT NULL,
|
||||
`perms_parts_instock` smallint(6) NOT NULL,
|
||||
`perms_parts_mininstock` smallint(6) NOT NULL,
|
||||
`perms_parts_footprint` smallint(6) NOT NULL,
|
||||
`perms_parts_storelocation` smallint(6) NOT NULL,
|
||||
`perms_parts_manufacturer` smallint(6) NOT NULL,
|
||||
`perms_parts_comment` smallint(6) NOT NULL,
|
||||
`perms_parts_order` smallint(6) NOT NULL,
|
||||
`perms_parts_orderdetails` smallint(6) NOT NULL,
|
||||
`perms_parts_prices` smallint(6) NOT NULL,
|
||||
`perms_parts_attachements` smallint(6) NOT NULL,
|
||||
`perms_devices` int(11) NOT NULL,
|
||||
`perms_devices_parts` int(11) NOT NULL,
|
||||
`perms_storelocations` int(11) NOT NULL,
|
||||
`perms_footprints` int(11) NOT NULL,
|
||||
`perms_categories` int(11) NOT NULL,
|
||||
`perms_suppliers` int(11) NOT NULL,
|
||||
`perms_manufacturers` int(11) NOT NULL,
|
||||
`perms_attachement_types` int(11) NOT NULL,
|
||||
`perms_tools` int(11) NOT NULL,
|
||||
`perms_labels` smallint(6) NOT NULL,
|
||||
`datetime_added` timestamp NOT NULL DEFAULT current_timestamp(),
|
||||
`last_modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
|
||||
|
||||
--
|
||||
-- Daten für Tabelle `users`
|
||||
--
|
||||
|
||||
INSERT INTO `users` (`id`, `name`, `password`, `first_name`, `last_name`, `department`, `email`, `need_pw_change`, `group_id`, `config_language`, `config_timezone`, `config_theme`, `config_currency`, `config_image_path`, `config_instock_comment_w`, `config_instock_comment_a`, `perms_system`, `perms_groups`, `perms_users`, `perms_self`, `perms_system_config`, `perms_system_database`, `perms_parts`, `perms_parts_name`, `perms_parts_description`, `perms_parts_instock`, `perms_parts_mininstock`, `perms_parts_footprint`, `perms_parts_storelocation`, `perms_parts_manufacturer`, `perms_parts_comment`, `perms_parts_order`, `perms_parts_orderdetails`, `perms_parts_prices`, `perms_parts_attachements`, `perms_devices`, `perms_devices_parts`, `perms_storelocations`, `perms_footprints`, `perms_categories`, `perms_suppliers`, `perms_manufacturers`, `perms_attachement_types`, `perms_tools`, `perms_labels`, `datetime_added`, `last_modified`) VALUES
|
||||
(1, 'anonymous', '', '', '', '', '', 0, 2, '', '', '', NULL, '', '', '', 21848, 20480, 0, 0, 0, 0, 0, 21840, 21840, 21840, 21840, 21840, 21840, 21840, 21840, 21840, 21520, 21520, 21520, 20480, 21520, 20480, 20480, 20480, 20480, 20480, 21504, 20480, 0, '2017-10-21 17:58:46', '2018-02-18 12:46:58'),
|
||||
(2, 'admin', '$2a$12$j0RKrKlx60bzX1DWMyXwjeaW.pe3bFjAK8ByIGnvjrRnET2JtsFoe', 'Admin', 'Ad', NULL, 'admin@ras.pi', 0, 1, '', '', '', NULL, '', '', '', 21845, 21845, 21845, 21, 85, 21, 349525, 21845, 21845, 21845, 21845, 21845, 21845, 21845, 21845, 21845, 21845, 21845, 21845, 21845, 21845, 21845, 21845, 21845, 21845, 21845, 21845, 21845, 0, '2017-10-21 17:58:46', '2017-12-23 11:04:48');
|
||||
|
||||
--
|
||||
-- Indizes der exportierten Tabellen
|
||||
--
|
||||
|
||||
--
|
||||
-- Indizes für die Tabelle `attachements`
|
||||
--
|
||||
ALTER TABLE `attachements`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD KEY `attachements_class_name_k` (`class_name`),
|
||||
ADD KEY `attachements_element_id_k` (`element_id`),
|
||||
ADD KEY `attachements_type_id_fk` (`type_id`);
|
||||
|
||||
--
|
||||
-- Indizes für die Tabelle `attachement_types`
|
||||
--
|
||||
ALTER TABLE `attachement_types`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD KEY `attachement_types_parent_id_k` (`parent_id`);
|
||||
|
||||
--
|
||||
-- Indizes für die Tabelle `categories`
|
||||
--
|
||||
ALTER TABLE `categories`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD KEY `categories_parent_id_k` (`parent_id`);
|
||||
|
||||
--
|
||||
-- Indizes für die Tabelle `devices`
|
||||
--
|
||||
ALTER TABLE `devices`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD KEY `devices_parent_id_k` (`parent_id`);
|
||||
|
||||
--
|
||||
-- Indizes für die Tabelle `device_parts`
|
||||
--
|
||||
ALTER TABLE `device_parts`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `device_parts_combination_uk` (`id_part`,`id_device`),
|
||||
ADD KEY `device_parts_id_part_k` (`id_part`),
|
||||
ADD KEY `device_parts_id_device_k` (`id_device`);
|
||||
|
||||
--
|
||||
-- Indizes für die Tabelle `footprints`
|
||||
--
|
||||
ALTER TABLE `footprints`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD KEY `footprints_parent_id_k` (`parent_id`);
|
||||
|
||||
--
|
||||
-- Indizes für die Tabelle `groups`
|
||||
--
|
||||
ALTER TABLE `groups`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `name` (`name`);
|
||||
|
||||
--
|
||||
-- Indizes für die Tabelle `internal`
|
||||
--
|
||||
ALTER TABLE `internal`
|
||||
ADD UNIQUE KEY `keyName` (`keyName`);
|
||||
|
||||
--
|
||||
-- Indizes für die Tabelle `log`
|
||||
--
|
||||
ALTER TABLE `log`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD KEY `id_user` (`id_user`);
|
||||
|
||||
--
|
||||
-- Indizes für die Tabelle `manufacturers`
|
||||
--
|
||||
ALTER TABLE `manufacturers`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD KEY `manufacturers_parent_id_k` (`parent_id`);
|
||||
|
||||
--
|
||||
-- Indizes für die Tabelle `orderdetails`
|
||||
--
|
||||
ALTER TABLE `orderdetails`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD KEY `orderdetails_part_id_k` (`part_id`),
|
||||
ADD KEY `orderdetails_id_supplier_k` (`id_supplier`);
|
||||
|
||||
--
|
||||
-- Indizes für die Tabelle `parts`
|
||||
--
|
||||
ALTER TABLE `parts`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD KEY `parts_id_category_k` (`id_category`),
|
||||
ADD KEY `parts_id_footprint_k` (`id_footprint`),
|
||||
ADD KEY `parts_id_storelocation_k` (`id_storelocation`),
|
||||
ADD KEY `parts_order_orderdetails_id_k` (`order_orderdetails_id`),
|
||||
ADD KEY `parts_id_manufacturer_k` (`id_manufacturer`),
|
||||
ADD KEY `favorite` (`favorite`);
|
||||
|
||||
--
|
||||
-- Indizes für die Tabelle `pricedetails`
|
||||
--
|
||||
ALTER TABLE `pricedetails`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `pricedetails_combination_uk` (`orderdetails_id`,`min_discount_quantity`),
|
||||
ADD KEY `pricedetails_orderdetails_id_k` (`orderdetails_id`);
|
||||
|
||||
--
|
||||
-- Indizes für die Tabelle `storelocations`
|
||||
--
|
||||
ALTER TABLE `storelocations`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD KEY `storelocations_parent_id_k` (`parent_id`);
|
||||
|
||||
--
|
||||
-- Indizes für die Tabelle `suppliers`
|
||||
--
|
||||
ALTER TABLE `suppliers`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD KEY `suppliers_parent_id_k` (`parent_id`);
|
||||
|
||||
--
|
||||
-- Indizes für die Tabelle `users`
|
||||
--
|
||||
ALTER TABLE `users`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `name` (`name`);
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT für exportierte Tabellen
|
||||
--
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT für Tabelle `attachements`
|
||||
--
|
||||
ALTER TABLE `attachements`
|
||||
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=201;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT für Tabelle `attachement_types`
|
||||
--
|
||||
ALTER TABLE `attachement_types`
|
||||
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=3;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT für Tabelle `categories`
|
||||
--
|
||||
ALTER TABLE `categories`
|
||||
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=123;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT für Tabelle `devices`
|
||||
--
|
||||
ALTER TABLE `devices`
|
||||
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT für Tabelle `device_parts`
|
||||
--
|
||||
ALTER TABLE `device_parts`
|
||||
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=12;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT für Tabelle `footprints`
|
||||
--
|
||||
ALTER TABLE `footprints`
|
||||
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=82;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT für Tabelle `groups`
|
||||
--
|
||||
ALTER TABLE `groups`
|
||||
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=4;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT für Tabelle `log`
|
||||
--
|
||||
ALTER TABLE `log`
|
||||
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=218;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT für Tabelle `manufacturers`
|
||||
--
|
||||
ALTER TABLE `manufacturers`
|
||||
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT für Tabelle `orderdetails`
|
||||
--
|
||||
ALTER TABLE `orderdetails`
|
||||
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=650;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT für Tabelle `parts`
|
||||
--
|
||||
ALTER TABLE `parts`
|
||||
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=1171;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT für Tabelle `pricedetails`
|
||||
--
|
||||
ALTER TABLE `pricedetails`
|
||||
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=437;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT für Tabelle `storelocations`
|
||||
--
|
||||
ALTER TABLE `storelocations`
|
||||
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=340;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT für Tabelle `suppliers`
|
||||
--
|
||||
ALTER TABLE `suppliers`
|
||||
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=5;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT für Tabelle `users`
|
||||
--
|
||||
ALTER TABLE `users`
|
||||
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=6;
|
||||
|
||||
--
|
||||
-- Constraints der exportierten Tabellen
|
||||
--
|
||||
|
||||
--
|
||||
-- Constraints der Tabelle `attachements`
|
||||
--
|
||||
ALTER TABLE `attachements`
|
||||
ADD CONSTRAINT `attachements_type_id_fk` FOREIGN KEY (`type_id`) REFERENCES `attachement_types` (`id`);
|
||||
|
||||
--
|
||||
-- Constraints der Tabelle `attachement_types`
|
||||
--
|
||||
ALTER TABLE `attachement_types`
|
||||
ADD CONSTRAINT `attachement_types_parent_id_fk` FOREIGN KEY (`parent_id`) REFERENCES `attachement_types` (`id`);
|
||||
|
||||
--
|
||||
-- Constraints der Tabelle `categories`
|
||||
--
|
||||
ALTER TABLE `categories`
|
||||
ADD CONSTRAINT `categories_parent_id_fk` FOREIGN KEY (`parent_id`) REFERENCES `categories` (`id`);
|
||||
|
||||
--
|
||||
-- Constraints der Tabelle `devices`
|
||||
--
|
||||
ALTER TABLE `devices`
|
||||
ADD CONSTRAINT `devices_parent_id_fk` FOREIGN KEY (`parent_id`) REFERENCES `devices` (`id`);
|
||||
|
||||
--
|
||||
-- Constraints der Tabelle `footprints`
|
||||
--
|
||||
ALTER TABLE `footprints`
|
||||
ADD CONSTRAINT `footprints_parent_id_fk` FOREIGN KEY (`parent_id`) REFERENCES `footprints` (`id`);
|
||||
|
||||
--
|
||||
-- Constraints der Tabelle `manufacturers`
|
||||
--
|
||||
ALTER TABLE `manufacturers`
|
||||
ADD CONSTRAINT `manufacturers_parent_id_fk` FOREIGN KEY (`parent_id`) REFERENCES `manufacturers` (`id`);
|
||||
|
||||
--
|
||||
-- Constraints der Tabelle `parts`
|
||||
--
|
||||
ALTER TABLE `parts`
|
||||
ADD CONSTRAINT `parts_id_footprint_fk` FOREIGN KEY (`id_footprint`) REFERENCES `footprints` (`id`),
|
||||
ADD CONSTRAINT `parts_id_manufacturer_fk` FOREIGN KEY (`id_manufacturer`) REFERENCES `manufacturers` (`id`),
|
||||
ADD CONSTRAINT `parts_id_storelocation_fk` FOREIGN KEY (`id_storelocation`) REFERENCES `storelocations` (`id`),
|
||||
ADD CONSTRAINT `parts_order_orderdetails_id_fk` FOREIGN KEY (`order_orderdetails_id`) REFERENCES `orderdetails` (`id`);
|
||||
|
||||
--
|
||||
-- Constraints der Tabelle `storelocations`
|
||||
--
|
||||
ALTER TABLE `storelocations`
|
||||
ADD CONSTRAINT `storelocations_parent_id_fk` FOREIGN KEY (`parent_id`) REFERENCES `storelocations` (`id`);
|
||||
|
||||
--
|
||||
-- Constraints der Tabelle `suppliers`
|
||||
--
|
||||
ALTER TABLE `suppliers`
|
||||
ADD CONSTRAINT `suppliers_parent_id_fk` FOREIGN KEY (`parent_id`) REFERENCES `suppliers` (`id`);
|
||||
COMMIT;
|
||||
|
||||
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
|
||||
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
||||
736
.github/assets/legacy_import/db_minimal.sql
vendored
Normal file
736
.github/assets/legacy_import/db_minimal.sql
vendored
Normal file
@@ -0,0 +1,736 @@
|
||||
-- phpMyAdmin SQL Dump
|
||||
-- version 5.1.3
|
||||
-- https://www.phpmyadmin.net/
|
||||
--
|
||||
-- Host: 127.0.0.1
|
||||
-- Erstellungszeit: 07. Mai 2023 um 01:48
|
||||
-- Server-Version: 10.6.5-MariaDB-log
|
||||
-- PHP-Version: 8.1.2
|
||||
|
||||
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
|
||||
START TRANSACTION;
|
||||
SET time_zone = "+00:00";
|
||||
|
||||
|
||||
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
|
||||
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
|
||||
/*!40101 SET NAMES utf8mb4 */;
|
||||
|
||||
--
|
||||
-- Datenbank: `partdb-legacy`
|
||||
--
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabellenstruktur für Tabelle `attachements`
|
||||
--
|
||||
|
||||
CREATE TABLE `attachements` (
|
||||
`id` int(11) NOT NULL,
|
||||
`name` tinytext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`class_name` varchar(255) COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`element_id` int(11) NOT NULL,
|
||||
`type_id` int(11) NOT NULL,
|
||||
`filename` mediumtext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`show_in_table` tinyint(1) NOT NULL DEFAULT 0,
|
||||
`last_modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabellenstruktur für Tabelle `attachement_types`
|
||||
--
|
||||
|
||||
CREATE TABLE `attachement_types` (
|
||||
`id` int(11) NOT NULL,
|
||||
`name` tinytext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`parent_id` int(11) DEFAULT NULL,
|
||||
`comment` text COLLATE utf8mb3_unicode_ci DEFAULT NULL,
|
||||
`datetime_added` timestamp NOT NULL DEFAULT current_timestamp(),
|
||||
`last_modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
|
||||
|
||||
--
|
||||
-- Daten für Tabelle `attachement_types`
|
||||
--
|
||||
|
||||
INSERT INTO `attachement_types` (`id`, `name`, `parent_id`, `comment`, `datetime_added`, `last_modified`) VALUES
|
||||
(1, 'Bilder', NULL, NULL, '2023-01-07 18:31:48', '0000-00-00 00:00:00'),
|
||||
(2, 'Datenblätter', NULL, NULL, '2023-01-07 18:31:48', '0000-00-00 00:00:00');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabellenstruktur für Tabelle `categories`
|
||||
--
|
||||
|
||||
CREATE TABLE `categories` (
|
||||
`id` int(11) NOT NULL,
|
||||
`name` tinytext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`parent_id` int(11) DEFAULT NULL,
|
||||
`disable_footprints` tinyint(1) NOT NULL DEFAULT 0,
|
||||
`disable_manufacturers` tinyint(1) NOT NULL DEFAULT 0,
|
||||
`disable_autodatasheets` tinyint(1) NOT NULL DEFAULT 0,
|
||||
`disable_properties` tinyint(1) NOT NULL DEFAULT 0,
|
||||
`partname_regex` text COLLATE utf8mb3_unicode_ci NOT NULL DEFAULT '',
|
||||
`partname_hint` text COLLATE utf8mb3_unicode_ci NOT NULL DEFAULT '',
|
||||
`default_description` text COLLATE utf8mb3_unicode_ci NOT NULL DEFAULT '',
|
||||
`default_comment` text COLLATE utf8mb3_unicode_ci NOT NULL DEFAULT '',
|
||||
`comment` text COLLATE utf8mb3_unicode_ci DEFAULT NULL,
|
||||
`datetime_added` timestamp NOT NULL DEFAULT current_timestamp(),
|
||||
`last_modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
|
||||
|
||||
--
|
||||
-- Daten für Tabelle `categories`
|
||||
--
|
||||
|
||||
INSERT INTO `categories` (`id`, `name`, `parent_id`, `disable_footprints`, `disable_manufacturers`, `disable_autodatasheets`, `disable_properties`, `partname_regex`, `partname_hint`, `default_description`, `default_comment`, `comment`, `datetime_added`, `last_modified`) VALUES
|
||||
(1, 'Test', NULL, 0, 0, 0, 0, '', '', '', '', '', '2023-01-07 18:32:29', '2023-01-07 18:32:29');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabellenstruktur für Tabelle `devices`
|
||||
--
|
||||
|
||||
CREATE TABLE `devices` (
|
||||
`id` int(11) NOT NULL,
|
||||
`name` tinytext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`parent_id` int(11) DEFAULT NULL,
|
||||
`order_quantity` int(11) NOT NULL DEFAULT 0,
|
||||
`order_only_missing_parts` tinyint(1) NOT NULL DEFAULT 0,
|
||||
`datetime_added` timestamp NOT NULL DEFAULT current_timestamp(),
|
||||
`last_modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||
`comment` text COLLATE utf8mb3_unicode_ci DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabellenstruktur für Tabelle `device_parts`
|
||||
--
|
||||
|
||||
CREATE TABLE `device_parts` (
|
||||
`id` int(11) NOT NULL,
|
||||
`id_part` int(11) NOT NULL DEFAULT 0,
|
||||
`id_device` int(11) NOT NULL DEFAULT 0,
|
||||
`quantity` int(11) NOT NULL DEFAULT 0,
|
||||
`mountnames` mediumtext COLLATE utf8mb3_unicode_ci NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabellenstruktur für Tabelle `footprints`
|
||||
--
|
||||
|
||||
CREATE TABLE `footprints` (
|
||||
`id` int(11) NOT NULL,
|
||||
`name` tinytext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`filename` mediumtext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`filename_3d` mediumtext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`parent_id` int(11) DEFAULT NULL,
|
||||
`comment` text COLLATE utf8mb3_unicode_ci DEFAULT NULL,
|
||||
`datetime_added` timestamp NOT NULL DEFAULT current_timestamp(),
|
||||
`last_modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabellenstruktur für Tabelle `groups`
|
||||
--
|
||||
|
||||
CREATE TABLE `groups` (
|
||||
`id` int(11) NOT NULL,
|
||||
`name` varchar(32) NOT NULL,
|
||||
`parent_id` int(11) DEFAULT NULL,
|
||||
`comment` mediumtext DEFAULT NULL,
|
||||
`perms_system` int(11) NOT NULL,
|
||||
`perms_groups` int(11) NOT NULL,
|
||||
`perms_users` int(11) NOT NULL,
|
||||
`perms_self` int(11) NOT NULL,
|
||||
`perms_system_config` int(11) NOT NULL,
|
||||
`perms_system_database` int(11) NOT NULL,
|
||||
`perms_parts` bigint(11) NOT NULL,
|
||||
`perms_parts_name` smallint(6) NOT NULL,
|
||||
`perms_parts_description` smallint(6) NOT NULL,
|
||||
`perms_parts_instock` smallint(6) NOT NULL,
|
||||
`perms_parts_mininstock` smallint(6) NOT NULL,
|
||||
`perms_parts_footprint` smallint(6) NOT NULL,
|
||||
`perms_parts_storelocation` smallint(6) NOT NULL,
|
||||
`perms_parts_manufacturer` smallint(6) NOT NULL,
|
||||
`perms_parts_comment` smallint(6) NOT NULL,
|
||||
`perms_parts_order` smallint(6) NOT NULL,
|
||||
`perms_parts_orderdetails` smallint(6) NOT NULL,
|
||||
`perms_parts_prices` smallint(6) NOT NULL,
|
||||
`perms_parts_attachements` smallint(6) NOT NULL,
|
||||
`perms_devices` int(11) NOT NULL,
|
||||
`perms_devices_parts` int(11) NOT NULL,
|
||||
`perms_storelocations` int(11) NOT NULL,
|
||||
`perms_footprints` int(11) NOT NULL,
|
||||
`perms_categories` int(11) NOT NULL,
|
||||
`perms_suppliers` int(11) NOT NULL,
|
||||
`perms_manufacturers` int(11) NOT NULL,
|
||||
`perms_attachement_types` int(11) NOT NULL,
|
||||
`perms_tools` int(11) NOT NULL,
|
||||
`perms_labels` smallint(6) NOT NULL,
|
||||
`datetime_added` timestamp NOT NULL DEFAULT current_timestamp(),
|
||||
`last_modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
|
||||
--
|
||||
-- Daten für Tabelle `groups`
|
||||
--
|
||||
|
||||
INSERT INTO `groups` (`id`, `name`, `parent_id`, `comment`, `perms_system`, `perms_groups`, `perms_users`, `perms_self`, `perms_system_config`, `perms_system_database`, `perms_parts`, `perms_parts_name`, `perms_parts_description`, `perms_parts_instock`, `perms_parts_mininstock`, `perms_parts_footprint`, `perms_parts_storelocation`, `perms_parts_manufacturer`, `perms_parts_comment`, `perms_parts_order`, `perms_parts_orderdetails`, `perms_parts_prices`, `perms_parts_attachements`, `perms_devices`, `perms_devices_parts`, `perms_storelocations`, `perms_footprints`, `perms_categories`, `perms_suppliers`, `perms_manufacturers`, `perms_attachement_types`, `perms_tools`, `perms_labels`, `datetime_added`, `last_modified`) VALUES
|
||||
(1, 'admins', NULL, 'Users of this group can do everything: Read, Write and Administrative actions.', 21, 1365, 87381, 85, 85, 21, 1431655765, 5, 5, 5, 5, 5, 5, 5, 5, 5, 325, 325, 325, 5461, 325, 5461, 5461, 5461, 5461, 5461, 1365, 1365, 85, '2023-01-07 18:31:48', '0000-00-00 00:00:00'),
|
||||
(2, 'readonly', NULL, 'Users of this group can only read informations, use tools, and don\'t have access to administrative tools.', 42, 2730, 174762, 154, 170, 42, -1516939607, 9, 9, 9, 9, 9, 9, 9, 9, 9, 649, 649, 649, 1705, 649, 1705, 1705, 1705, 1705, 1705, 681, 1366, 165, '2023-01-07 18:31:48', '0000-00-00 00:00:00'),
|
||||
(3, 'users', NULL, 'Users of this group, can edit part informations, create new ones, etc. but are not allowed to use administrative tools. (But can read current configuration, and see Server status)', 42, 2730, 109226, 89, 105, 41, 1431655765, 5, 5, 5, 5, 5, 5, 5, 5, 5, 325, 325, 325, 5461, 325, 5461, 5461, 5461, 5461, 5461, 1365, 1365, 85, '2023-01-07 18:31:48', '0000-00-00 00:00:00');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabellenstruktur für Tabelle `internal`
|
||||
--
|
||||
|
||||
CREATE TABLE `internal` (
|
||||
`keyName` char(30) CHARACTER SET ascii NOT NULL,
|
||||
`keyValue` varchar(255) COLLATE utf8mb3_unicode_ci DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
|
||||
|
||||
--
|
||||
-- Daten für Tabelle `internal`
|
||||
--
|
||||
|
||||
INSERT INTO `internal` (`keyName`, `keyValue`) VALUES
|
||||
('dbVersion', '26');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabellenstruktur für Tabelle `log`
|
||||
--
|
||||
|
||||
CREATE TABLE `log` (
|
||||
`id` int(11) NOT NULL,
|
||||
`datetime` timestamp NOT NULL DEFAULT current_timestamp(),
|
||||
`id_user` int(11) NOT NULL,
|
||||
`level` tinyint(4) NOT NULL,
|
||||
`type` smallint(6) NOT NULL,
|
||||
`target_id` int(11) NOT NULL,
|
||||
`target_type` smallint(6) NOT NULL,
|
||||
`extra` mediumtext NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
|
||||
--
|
||||
-- Daten für Tabelle `log`
|
||||
--
|
||||
|
||||
INSERT INTO `log` (`id`, `datetime`, `id_user`, `level`, `type`, `target_id`, `target_type`, `extra`) VALUES
|
||||
(1, '2023-01-07 18:31:48', 1, 4, 10, 0, 0, '{\"o\":0,\"n\":26,\"s\":true}'),
|
||||
(2, '2023-01-07 18:32:13', 2, 6, 1, 2, 1, '{\"i\":\"::\"}'),
|
||||
(3, '2023-01-07 18:32:29', 2, 6, 6, 1, 4, '[]'),
|
||||
(4, '2023-01-07 18:32:53', 2, 6, 6, 1, 12, '[]'),
|
||||
(5, '2023-01-07 18:33:26', 2, 6, 6, 1, 10, '{\"i\":0}');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabellenstruktur für Tabelle `manufacturers`
|
||||
--
|
||||
|
||||
CREATE TABLE `manufacturers` (
|
||||
`id` int(11) NOT NULL,
|
||||
`name` tinytext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`parent_id` int(11) DEFAULT NULL,
|
||||
`address` mediumtext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`phone_number` tinytext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`fax_number` tinytext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`email_address` tinytext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`website` tinytext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`auto_product_url` tinytext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`datetime_added` timestamp NOT NULL DEFAULT current_timestamp(),
|
||||
`comment` text COLLATE utf8mb3_unicode_ci DEFAULT NULL,
|
||||
`last_modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabellenstruktur für Tabelle `orderdetails`
|
||||
--
|
||||
|
||||
CREATE TABLE `orderdetails` (
|
||||
`id` int(11) NOT NULL,
|
||||
`part_id` int(11) NOT NULL,
|
||||
`id_supplier` int(11) NOT NULL DEFAULT 0,
|
||||
`supplierpartnr` tinytext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`obsolete` tinyint(1) DEFAULT 0,
|
||||
`supplier_product_url` tinytext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`datetime_added` timestamp NOT NULL DEFAULT current_timestamp()
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
|
||||
|
||||
--
|
||||
-- Daten für Tabelle `orderdetails`
|
||||
--
|
||||
|
||||
INSERT INTO `orderdetails` (`id`, `part_id`, `id_supplier`, `supplierpartnr`, `obsolete`, `supplier_product_url`, `datetime_added`) VALUES
|
||||
(1, 1, 1, 'BC547', 0, '', '2023-01-07 18:45:59'),
|
||||
(2, 1, 1, 'Test', 0, '', '2023-01-07 18:46:09');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabellenstruktur für Tabelle `parts`
|
||||
--
|
||||
|
||||
CREATE TABLE `parts` (
|
||||
`id` int(11) NOT NULL,
|
||||
`id_category` int(11) NOT NULL DEFAULT 0,
|
||||
`name` mediumtext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`description` mediumtext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`instock` int(11) NOT NULL DEFAULT 0,
|
||||
`mininstock` int(11) NOT NULL DEFAULT 0,
|
||||
`comment` mediumtext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`visible` tinyint(1) NOT NULL,
|
||||
`id_footprint` int(11) DEFAULT NULL,
|
||||
`id_storelocation` int(11) DEFAULT NULL,
|
||||
`order_orderdetails_id` int(11) DEFAULT NULL,
|
||||
`order_quantity` int(11) NOT NULL DEFAULT 1,
|
||||
`manual_order` tinyint(1) NOT NULL DEFAULT 0,
|
||||
`id_manufacturer` int(11) DEFAULT NULL,
|
||||
`id_master_picture_attachement` int(11) DEFAULT NULL,
|
||||
`manufacturer_product_url` tinytext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`datetime_added` timestamp NOT NULL DEFAULT current_timestamp(),
|
||||
`last_modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||
`favorite` tinyint(1) NOT NULL DEFAULT 0
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
|
||||
|
||||
--
|
||||
-- Daten für Tabelle `parts`
|
||||
--
|
||||
|
||||
INSERT INTO `parts` (`id`, `id_category`, `name`, `description`, `instock`, `mininstock`, `comment`, `visible`, `id_footprint`, `id_storelocation`, `order_orderdetails_id`, `order_quantity`, `manual_order`, `id_manufacturer`, `id_master_picture_attachement`, `manufacturer_product_url`, `datetime_added`, `last_modified`, `favorite`) VALUES
|
||||
(1, 1, 'BC547', '', 0, 0, '', 0, NULL, NULL, NULL, 1, 0, NULL, NULL, '', '2023-01-07 18:33:26', '2023-01-07 18:33:26', 0);
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabellenstruktur für Tabelle `pricedetails`
|
||||
--
|
||||
|
||||
CREATE TABLE `pricedetails` (
|
||||
`id` int(11) NOT NULL,
|
||||
`orderdetails_id` int(11) NOT NULL,
|
||||
`price` decimal(11,5) DEFAULT NULL,
|
||||
`price_related_quantity` int(11) NOT NULL DEFAULT 1,
|
||||
`min_discount_quantity` int(11) NOT NULL DEFAULT 1,
|
||||
`manual_input` tinyint(1) NOT NULL DEFAULT 1,
|
||||
`last_modified` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp()
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
|
||||
|
||||
--
|
||||
-- Daten für Tabelle `pricedetails`
|
||||
--
|
||||
|
||||
INSERT INTO `pricedetails` (`id`, `orderdetails_id`, `price`, `price_related_quantity`, `min_discount_quantity`, `manual_input`, `last_modified`) VALUES
|
||||
(1, 2, '3.55000', 1, 1, 1, '2023-01-07 18:46:19');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabellenstruktur für Tabelle `storelocations`
|
||||
--
|
||||
|
||||
CREATE TABLE `storelocations` (
|
||||
`id` int(11) NOT NULL,
|
||||
`name` tinytext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`parent_id` int(11) DEFAULT NULL,
|
||||
`is_full` tinyint(1) NOT NULL DEFAULT 0,
|
||||
`datetime_added` timestamp NOT NULL DEFAULT current_timestamp(),
|
||||
`comment` text COLLATE utf8mb3_unicode_ci DEFAULT NULL,
|
||||
`last_modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabellenstruktur für Tabelle `suppliers`
|
||||
--
|
||||
|
||||
CREATE TABLE `suppliers` (
|
||||
`id` int(11) NOT NULL,
|
||||
`name` tinytext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`parent_id` int(11) DEFAULT NULL,
|
||||
`address` mediumtext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`phone_number` tinytext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`fax_number` tinytext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`email_address` tinytext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`website` tinytext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`auto_product_url` tinytext COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||
`datetime_added` timestamp NOT NULL DEFAULT current_timestamp(),
|
||||
`comment` text COLLATE utf8mb3_unicode_ci DEFAULT NULL,
|
||||
`last_modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
|
||||
|
||||
--
|
||||
-- Daten für Tabelle `suppliers`
|
||||
--
|
||||
|
||||
INSERT INTO `suppliers` (`id`, `name`, `parent_id`, `address`, `phone_number`, `fax_number`, `email_address`, `website`, `auto_product_url`, `datetime_added`, `comment`, `last_modified`) VALUES
|
||||
(1, 'Reichelt', NULL, '', '', '', '', '', '', '2023-01-07 18:32:53', '', '2023-01-07 18:32:53');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabellenstruktur für Tabelle `users`
|
||||
--
|
||||
|
||||
CREATE TABLE `users` (
|
||||
`id` int(11) NOT NULL,
|
||||
`name` varchar(32) NOT NULL,
|
||||
`password` varchar(255) DEFAULT NULL,
|
||||
`first_name` tinytext DEFAULT NULL,
|
||||
`last_name` tinytext DEFAULT NULL,
|
||||
`department` tinytext DEFAULT NULL,
|
||||
`email` tinytext DEFAULT NULL,
|
||||
`need_pw_change` tinyint(1) NOT NULL DEFAULT 0,
|
||||
`group_id` int(11) DEFAULT NULL,
|
||||
`config_language` tinytext DEFAULT NULL,
|
||||
`config_timezone` tinytext DEFAULT NULL,
|
||||
`config_theme` tinytext DEFAULT NULL,
|
||||
`config_currency` tinytext DEFAULT NULL,
|
||||
`config_image_path` text NOT NULL,
|
||||
`config_instock_comment_w` text NOT NULL,
|
||||
`config_instock_comment_a` text NOT NULL,
|
||||
`perms_system` int(11) NOT NULL,
|
||||
`perms_groups` int(11) NOT NULL,
|
||||
`perms_users` int(11) NOT NULL,
|
||||
`perms_self` int(11) NOT NULL,
|
||||
`perms_system_config` int(11) NOT NULL,
|
||||
`perms_system_database` int(11) NOT NULL,
|
||||
`perms_parts` bigint(11) NOT NULL,
|
||||
`perms_parts_name` smallint(6) NOT NULL,
|
||||
`perms_parts_description` smallint(6) NOT NULL,
|
||||
`perms_parts_instock` smallint(6) NOT NULL,
|
||||
`perms_parts_mininstock` smallint(6) NOT NULL,
|
||||
`perms_parts_footprint` smallint(6) NOT NULL,
|
||||
`perms_parts_storelocation` smallint(6) NOT NULL,
|
||||
`perms_parts_manufacturer` smallint(6) NOT NULL,
|
||||
`perms_parts_comment` smallint(6) NOT NULL,
|
||||
`perms_parts_order` smallint(6) NOT NULL,
|
||||
`perms_parts_orderdetails` smallint(6) NOT NULL,
|
||||
`perms_parts_prices` smallint(6) NOT NULL,
|
||||
`perms_parts_attachements` smallint(6) NOT NULL,
|
||||
`perms_devices` int(11) NOT NULL,
|
||||
`perms_devices_parts` int(11) NOT NULL,
|
||||
`perms_storelocations` int(11) NOT NULL,
|
||||
`perms_footprints` int(11) NOT NULL,
|
||||
`perms_categories` int(11) NOT NULL,
|
||||
`perms_suppliers` int(11) NOT NULL,
|
||||
`perms_manufacturers` int(11) NOT NULL,
|
||||
`perms_attachement_types` int(11) NOT NULL,
|
||||
`perms_tools` int(11) NOT NULL,
|
||||
`perms_labels` smallint(6) NOT NULL,
|
||||
`datetime_added` timestamp NOT NULL DEFAULT current_timestamp(),
|
||||
`last_modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
|
||||
--
|
||||
-- Daten für Tabelle `users`
|
||||
--
|
||||
|
||||
INSERT INTO `users` (`id`, `name`, `password`, `first_name`, `last_name`, `department`, `email`, `need_pw_change`, `group_id`, `config_language`, `config_timezone`, `config_theme`, `config_currency`, `config_image_path`, `config_instock_comment_w`, `config_instock_comment_a`, `perms_system`, `perms_groups`, `perms_users`, `perms_self`, `perms_system_config`, `perms_system_database`, `perms_parts`, `perms_parts_name`, `perms_parts_description`, `perms_parts_instock`, `perms_parts_mininstock`, `perms_parts_footprint`, `perms_parts_storelocation`, `perms_parts_manufacturer`, `perms_parts_comment`, `perms_parts_order`, `perms_parts_orderdetails`, `perms_parts_prices`, `perms_parts_attachements`, `perms_devices`, `perms_devices_parts`, `perms_storelocations`, `perms_footprints`, `perms_categories`, `perms_suppliers`, `perms_manufacturers`, `perms_attachement_types`, `perms_tools`, `perms_labels`, `datetime_added`, `last_modified`) VALUES
|
||||
(1, 'anonymous', '', '', '', '', '', 0, 2, NULL, NULL, NULL, NULL, '', '', '', 21844, 20480, 0, 0, 0, 0, 0, 21840, 21840, 21840, 21840, 21840, 21840, 21840, 21840, 21840, 21520, 21520, 21520, 20480, 21520, 20480, 20480, 20480, 20480, 20480, 21504, 20480, 0, '2023-01-07 18:31:48', '0000-00-00 00:00:00'),
|
||||
(2, 'admin', '$2a$12$j0RKrKlx60bzX1DWMyXwjeaW.pe3bFjAK8ByIGnvjrRnET2JtsFoe$2a$12$j0RKrKlx60bzX1DWMyXwjeaW.pe3bFjAK8ByIGnvjrRnET2JtsFoe', '', '', '', '', 1, 1, NULL, NULL, NULL, NULL, '', '', '', 21845, 21845, 21845, 21, 85, 21, 349525, 21845, 21845, 21845, 21845, 21845, 21845, 21845, 21845, 21845, 21845, 21845, 21845, 21845, 21845, 21845, 21845, 21845, 21845, 21845, 21845, 21845, 0, '2023-01-07 18:31:48', '0000-00-00 00:00:00');
|
||||
|
||||
--
|
||||
-- Indizes der exportierten Tabellen
|
||||
--
|
||||
|
||||
--
|
||||
-- Indizes für die Tabelle `attachements`
|
||||
--
|
||||
ALTER TABLE `attachements`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD KEY `attachements_class_name_k` (`class_name`),
|
||||
ADD KEY `attachements_element_id_k` (`element_id`),
|
||||
ADD KEY `attachements_type_id_fk` (`type_id`);
|
||||
|
||||
--
|
||||
-- Indizes für die Tabelle `attachement_types`
|
||||
--
|
||||
ALTER TABLE `attachement_types`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD KEY `attachement_types_parent_id_k` (`parent_id`);
|
||||
|
||||
--
|
||||
-- Indizes für die Tabelle `categories`
|
||||
--
|
||||
ALTER TABLE `categories`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD KEY `categories_parent_id_k` (`parent_id`);
|
||||
|
||||
--
|
||||
-- Indizes für die Tabelle `devices`
|
||||
--
|
||||
ALTER TABLE `devices`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD KEY `devices_parent_id_k` (`parent_id`);
|
||||
|
||||
--
|
||||
-- Indizes für die Tabelle `device_parts`
|
||||
--
|
||||
ALTER TABLE `device_parts`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `device_parts_combination_uk` (`id_part`,`id_device`),
|
||||
ADD KEY `device_parts_id_part_k` (`id_part`),
|
||||
ADD KEY `device_parts_id_device_k` (`id_device`);
|
||||
|
||||
--
|
||||
-- Indizes für die Tabelle `footprints`
|
||||
--
|
||||
ALTER TABLE `footprints`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD KEY `footprints_parent_id_k` (`parent_id`);
|
||||
|
||||
--
|
||||
-- Indizes für die Tabelle `groups`
|
||||
--
|
||||
ALTER TABLE `groups`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `name` (`name`);
|
||||
|
||||
--
|
||||
-- Indizes für die Tabelle `internal`
|
||||
--
|
||||
ALTER TABLE `internal`
|
||||
ADD UNIQUE KEY `keyName` (`keyName`);
|
||||
|
||||
--
|
||||
-- Indizes für die Tabelle `log`
|
||||
--
|
||||
ALTER TABLE `log`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD KEY `id_user` (`id_user`);
|
||||
|
||||
--
|
||||
-- Indizes für die Tabelle `manufacturers`
|
||||
--
|
||||
ALTER TABLE `manufacturers`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD KEY `manufacturers_parent_id_k` (`parent_id`);
|
||||
|
||||
--
|
||||
-- Indizes für die Tabelle `orderdetails`
|
||||
--
|
||||
ALTER TABLE `orderdetails`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD KEY `orderdetails_part_id_k` (`part_id`),
|
||||
ADD KEY `orderdetails_id_supplier_k` (`id_supplier`);
|
||||
|
||||
--
|
||||
-- Indizes für die Tabelle `parts`
|
||||
--
|
||||
ALTER TABLE `parts`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD KEY `parts_id_category_k` (`id_category`),
|
||||
ADD KEY `parts_id_footprint_k` (`id_footprint`),
|
||||
ADD KEY `parts_id_storelocation_k` (`id_storelocation`),
|
||||
ADD KEY `parts_order_orderdetails_id_k` (`order_orderdetails_id`),
|
||||
ADD KEY `parts_id_manufacturer_k` (`id_manufacturer`),
|
||||
ADD KEY `favorite` (`favorite`);
|
||||
|
||||
--
|
||||
-- Indizes für die Tabelle `pricedetails`
|
||||
--
|
||||
ALTER TABLE `pricedetails`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `pricedetails_combination_uk` (`orderdetails_id`,`min_discount_quantity`),
|
||||
ADD KEY `pricedetails_orderdetails_id_k` (`orderdetails_id`);
|
||||
|
||||
--
|
||||
-- Indizes für die Tabelle `storelocations`
|
||||
--
|
||||
ALTER TABLE `storelocations`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD KEY `storelocations_parent_id_k` (`parent_id`);
|
||||
|
||||
--
|
||||
-- Indizes für die Tabelle `suppliers`
|
||||
--
|
||||
ALTER TABLE `suppliers`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD KEY `suppliers_parent_id_k` (`parent_id`);
|
||||
|
||||
--
|
||||
-- Indizes für die Tabelle `users`
|
||||
--
|
||||
ALTER TABLE `users`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `name` (`name`);
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT für exportierte Tabellen
|
||||
--
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT für Tabelle `attachements`
|
||||
--
|
||||
ALTER TABLE `attachements`
|
||||
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT für Tabelle `attachement_types`
|
||||
--
|
||||
ALTER TABLE `attachement_types`
|
||||
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=3;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT für Tabelle `categories`
|
||||
--
|
||||
ALTER TABLE `categories`
|
||||
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT für Tabelle `devices`
|
||||
--
|
||||
ALTER TABLE `devices`
|
||||
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT für Tabelle `device_parts`
|
||||
--
|
||||
ALTER TABLE `device_parts`
|
||||
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT für Tabelle `footprints`
|
||||
--
|
||||
ALTER TABLE `footprints`
|
||||
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT für Tabelle `groups`
|
||||
--
|
||||
ALTER TABLE `groups`
|
||||
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=4;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT für Tabelle `log`
|
||||
--
|
||||
ALTER TABLE `log`
|
||||
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=6;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT für Tabelle `manufacturers`
|
||||
--
|
||||
ALTER TABLE `manufacturers`
|
||||
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT für Tabelle `orderdetails`
|
||||
--
|
||||
ALTER TABLE `orderdetails`
|
||||
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=3;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT für Tabelle `parts`
|
||||
--
|
||||
ALTER TABLE `parts`
|
||||
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT für Tabelle `pricedetails`
|
||||
--
|
||||
ALTER TABLE `pricedetails`
|
||||
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT für Tabelle `storelocations`
|
||||
--
|
||||
ALTER TABLE `storelocations`
|
||||
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT für Tabelle `suppliers`
|
||||
--
|
||||
ALTER TABLE `suppliers`
|
||||
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT für Tabelle `users`
|
||||
--
|
||||
ALTER TABLE `users`
|
||||
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=3;
|
||||
|
||||
--
|
||||
-- Constraints der exportierten Tabellen
|
||||
--
|
||||
|
||||
--
|
||||
-- Constraints der Tabelle `attachements`
|
||||
--
|
||||
ALTER TABLE `attachements`
|
||||
ADD CONSTRAINT `attachements_type_id_fk` FOREIGN KEY (`type_id`) REFERENCES `attachement_types` (`id`);
|
||||
|
||||
--
|
||||
-- Constraints der Tabelle `attachement_types`
|
||||
--
|
||||
ALTER TABLE `attachement_types`
|
||||
ADD CONSTRAINT `attachement_types_parent_id_fk` FOREIGN KEY (`parent_id`) REFERENCES `attachement_types` (`id`);
|
||||
|
||||
--
|
||||
-- Constraints der Tabelle `categories`
|
||||
--
|
||||
ALTER TABLE `categories`
|
||||
ADD CONSTRAINT `categories_parent_id_fk` FOREIGN KEY (`parent_id`) REFERENCES `categories` (`id`);
|
||||
|
||||
--
|
||||
-- Constraints der Tabelle `devices`
|
||||
--
|
||||
ALTER TABLE `devices`
|
||||
ADD CONSTRAINT `devices_parent_id_fk` FOREIGN KEY (`parent_id`) REFERENCES `devices` (`id`);
|
||||
|
||||
--
|
||||
-- Constraints der Tabelle `footprints`
|
||||
--
|
||||
ALTER TABLE `footprints`
|
||||
ADD CONSTRAINT `footprints_parent_id_fk` FOREIGN KEY (`parent_id`) REFERENCES `footprints` (`id`);
|
||||
|
||||
--
|
||||
-- Constraints der Tabelle `manufacturers`
|
||||
--
|
||||
ALTER TABLE `manufacturers`
|
||||
ADD CONSTRAINT `manufacturers_parent_id_fk` FOREIGN KEY (`parent_id`) REFERENCES `manufacturers` (`id`);
|
||||
|
||||
--
|
||||
-- Constraints der Tabelle `parts`
|
||||
--
|
||||
ALTER TABLE `parts`
|
||||
ADD CONSTRAINT `parts_id_footprint_fk` FOREIGN KEY (`id_footprint`) REFERENCES `footprints` (`id`),
|
||||
ADD CONSTRAINT `parts_id_manufacturer_fk` FOREIGN KEY (`id_manufacturer`) REFERENCES `manufacturers` (`id`),
|
||||
ADD CONSTRAINT `parts_id_storelocation_fk` FOREIGN KEY (`id_storelocation`) REFERENCES `storelocations` (`id`),
|
||||
ADD CONSTRAINT `parts_order_orderdetails_id_fk` FOREIGN KEY (`order_orderdetails_id`) REFERENCES `orderdetails` (`id`);
|
||||
|
||||
--
|
||||
-- Constraints der Tabelle `storelocations`
|
||||
--
|
||||
ALTER TABLE `storelocations`
|
||||
ADD CONSTRAINT `storelocations_parent_id_fk` FOREIGN KEY (`parent_id`) REFERENCES `storelocations` (`id`);
|
||||
|
||||
--
|
||||
-- Constraints der Tabelle `suppliers`
|
||||
--
|
||||
ALTER TABLE `suppliers`
|
||||
ADD CONSTRAINT `suppliers_parent_id_fk` FOREIGN KEY (`parent_id`) REFERENCES `suppliers` (`id`);
|
||||
COMMIT;
|
||||
|
||||
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
|
||||
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
||||
54
.github/assets/legacy_import/test_legacy_import.sh
vendored
Normal file
54
.github/assets/legacy_import/test_legacy_import.sh
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
#
|
||||
# This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
|
||||
#
|
||||
# Copyright (C) 2019 - 2023 Jan Böhmer (https://github.com/jbtronics)
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
#!/bin/bash
|
||||
|
||||
# This script is used to test the legacy import of Part-DB
|
||||
|
||||
SQL_FILES_TO_TEST=("db_minimal.sql" "db_jbtronics.sql")
|
||||
|
||||
DB_NAME="legacy_db_test"
|
||||
DB_USER="root"
|
||||
DB_PASSWORD="root"
|
||||
|
||||
# Iterate over all given SQL files and import them into the mysql database with the given name, drop the database if it already exists before
|
||||
for SQL_FILE in "${SQL_FILES_TO_TEST[@]}"
|
||||
do
|
||||
echo "Testing for $SQL_FILE"
|
||||
mysql -u $DB_USER --password=$DB_PASSWORD -e "DROP DATABASE IF EXISTS $DB_NAME; CREATE DATABASE $DB_NAME;"
|
||||
# If the last command failed, exit the script
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Failed to create database $DB_NAME"
|
||||
exit 1
|
||||
fi
|
||||
# Import the SQL file into the database. The file pathes are relative to the current script location
|
||||
mysql -u $DB_USER --password=$DB_PASSWORD $DB_NAME < .github/assets/legacy_import/$SQL_FILE
|
||||
# If the last command failed, exit the script
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Failed to import $SQL_FILE into database $DB_NAME"
|
||||
exit 1
|
||||
fi
|
||||
# Run doctrine migrations, this will migrate the database to the current version. This process should not fail
|
||||
php bin/console doctrine:migrations:migrate -n
|
||||
# If the last command failed, exit the script
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Failed to migrate database $DB_NAME"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
11
.github/dependabot.yml
vendored
Normal file
11
.github/dependabot.yml
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
# To get started with Dependabot version updates, you'll need to specify which
|
||||
# package ecosystems to update and where the package manifests are located.
|
||||
# Please see the documentation for all configuration options:
|
||||
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions" # See documentation for possible values
|
||||
directory: "/" # Location of package manifests
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
2
.github/workflows/assets_artifact_build.yml
vendored
2
.github/workflows/assets_artifact_build.yml
vendored
@@ -19,7 +19,7 @@ jobs:
|
||||
APP_ENV: prod
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Get Composer Cache Directory
|
||||
id: composer-cache
|
||||
|
||||
54
.github/workflows/codeql-analysis.yml
vendored
54
.github/workflows/codeql-analysis.yml
vendored
@@ -1,54 +0,0 @@
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master, ]
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: [master]
|
||||
schedule:
|
||||
- cron: '0 14 * * 3'
|
||||
|
||||
jobs:
|
||||
analyse:
|
||||
name: Analyse
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
# We must fetch at least the immediate parents so that if this is
|
||||
# a pull request then we can checkout the head.
|
||||
fetch-depth: 2
|
||||
|
||||
# If this run was triggered by a pull request event, then checkout
|
||||
# the head of the pull request instead of the merge commit.
|
||||
- run: git checkout HEAD^2
|
||||
if: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v1
|
||||
# Override language selection by uncommenting this and choosing your languages
|
||||
# with:
|
||||
# languages: go, javascript, csharp, python, cpp, java
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v1
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
|
||||
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
||||
# and modify them (or add more) to build your code if your project
|
||||
# uses a compiled language
|
||||
|
||||
#- run: |
|
||||
# make bootstrap
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v1
|
||||
13
.github/workflows/docker_build.yml
vendored
13
.github/workflows/docker_build.yml
vendored
@@ -10,9 +10,6 @@ on:
|
||||
tags:
|
||||
- 'v*.*.*'
|
||||
- 'v*.*.*-**'
|
||||
pull_request:
|
||||
branches:
|
||||
- 'master'
|
||||
|
||||
jobs:
|
||||
docker:
|
||||
@@ -20,11 +17,11 @@ jobs:
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
-
|
||||
name: Docker meta
|
||||
id: docker_meta
|
||||
uses: docker/metadata-action@v4
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
# list of Docker images to use as base name for tags
|
||||
images: |
|
||||
@@ -52,12 +49,12 @@ jobs:
|
||||
|
||||
-
|
||||
name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
uses: docker/setup-qemu-action@v3
|
||||
with:
|
||||
platforms: 'arm64,arm'
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
uses: docker/setup-buildx-action@v3
|
||||
-
|
||||
name: Login to DockerHub
|
||||
if: github.event_name != 'pull_request'
|
||||
@@ -68,7 +65,7 @@ jobs:
|
||||
|
||||
-
|
||||
name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64,linux/arm/v7
|
||||
|
||||
11
.github/workflows/static_analysis.yml
vendored
11
.github/workflows/static_analysis.yml
vendored
@@ -16,7 +16,7 @@ jobs:
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Get Composer Cache Directory
|
||||
id: composer-cache
|
||||
@@ -38,12 +38,13 @@ jobs:
|
||||
|
||||
- name: Lint twig templates
|
||||
run: ./bin/console lint:twig templates --env=prod
|
||||
|
||||
- name: Lint translations
|
||||
run: ./bin/console lint:xliff translations
|
||||
|
||||
# This causes problems with emtpy language files
|
||||
#- name: Lint translations
|
||||
# run: ./bin/console lint:xliff translations
|
||||
|
||||
- name: Check dependencies for security
|
||||
uses: symfonycorp/security-checker-action@v3
|
||||
uses: symfonycorp/security-checker-action@v5
|
||||
|
||||
- name: Check doctrine mapping
|
||||
run: ./bin/console doctrine:schema:validate --skip-sync -vvv --no-interaction
|
||||
|
||||
16
.github/workflows/tests.yml
vendored
16
.github/workflows/tests.yml
vendored
@@ -18,7 +18,7 @@ jobs:
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
php-versions: [ '7.4', '8.0', '8.1', '8.2' ]
|
||||
php-versions: [ '8.1', '8.2' ]
|
||||
db-type: [ 'mysql', 'sqlite' ]
|
||||
|
||||
env:
|
||||
@@ -38,7 +38,7 @@ jobs:
|
||||
if: matrix.db-type == 'sqlite'
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
@@ -63,7 +63,7 @@ jobs:
|
||||
id: composer-cache
|
||||
run: |
|
||||
echo "::set-output name=dir::$(composer config cache-files-dir)"
|
||||
- uses: actions/cache@v1
|
||||
- uses: actions/cache@v3
|
||||
with:
|
||||
path: ${{ steps.composer-cache.outputs.dir }}
|
||||
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
|
||||
@@ -109,7 +109,7 @@ jobs:
|
||||
run: php bin/console --env test doctrine:migrations:migrate -n
|
||||
|
||||
- name: Load fixtures
|
||||
run: php bin/console --env test doctrine:fixtures:load -n --purger reset_autoincrement_purger
|
||||
run: php bin/console --env test doctrine:fixtures:load -n
|
||||
|
||||
- name: Run PHPunit and generate coverage
|
||||
run: ./bin/phpunit --coverage-clover=coverage.xml
|
||||
@@ -130,4 +130,12 @@ jobs:
|
||||
|
||||
- name: Test check-requirements command
|
||||
run: php bin/console partdb:check-requirements -n
|
||||
|
||||
- name: Test legacy Part-DB import
|
||||
run: bash .github/assets/legacy_import/test_legacy_import.sh
|
||||
if: matrix.db-type == 'mysql' && matrix.php-versions == '8.2'
|
||||
env:
|
||||
DATABASE_URL: mysql://root:root@localhost:3306/legacy_db
|
||||
|
||||
|
||||
|
||||
|
||||
28
Dockerfile
28
Dockerfile
@@ -9,7 +9,7 @@ RUN apt-get update && apt-get -y install apt-transport-https lsb-release ca-cert
|
||||
&& curl -sSLo /usr/share/keyrings/deb.sury.org-php.gpg https://packages.sury.org/php/apt.gpg \
|
||||
&& sh -c 'echo "deb [signed-by=/usr/share/keyrings/deb.sury.org-php.gpg] https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/php.list' \
|
||||
&& apt-get update && apt-get upgrade -y \
|
||||
&& apt-get install -y apache2 php8.1 libapache2-mod-php8.1 php8.1-opcache php8.1-curl php8.1-gd php8.1-mbstring php8.1-xml php8.1-bcmath php8.1-intl php8.1-zip php8.1-xsl php8.1-sqlite3 php8.1-mysql gpg \
|
||||
&& apt-get install -y apache2 php8.1 php8.1-fpm php8.1-opcache php8.1-curl php8.1-gd php8.1-mbstring php8.1-xml php8.1-bcmath php8.1-intl php8.1-zip php8.1-xsl php8.1-sqlite3 php8.1-mysql gpg \
|
||||
&& apt-get -y autoremove && apt-get clean autoclean && rm -rf /var/lib/apt/lists/*;
|
||||
|
||||
ENV APACHE_CONFDIR /etc/apache2
|
||||
@@ -36,8 +36,22 @@ RUN sed -ri 's/^export ([^=]+)=(.*)$/: ${\1:=\2}\nexport \1/' "$APACHE_ENVVARS"
|
||||
ln -sfT /dev/stdout "$APACHE_LOG_DIR/other_vhosts_access.log"; \
|
||||
chown -R --no-dereference "$APACHE_RUN_USER:$APACHE_RUN_GROUP" "$APACHE_LOG_DIR";
|
||||
|
||||
# Enable mpm_prefork
|
||||
RUN a2dismod mpm_event && a2enmod mpm_prefork
|
||||
# Enable php-fpm
|
||||
RUN a2enmod proxy_fcgi setenvif && a2enconf php8.1-fpm
|
||||
|
||||
# Configure php-fpm to log to stdout of the container (stdout of PID 1)
|
||||
# We have to use /proc/1/fd/1 because /dev/stdout or /proc/self/fd/1 does not point to the container stdout (because we use apache as entrypoint)
|
||||
# We also disable the clear_env option to allow the use of environment variables in php-fpm
|
||||
RUN { \
|
||||
echo '[global]'; \
|
||||
echo 'error_log = /proc/1/fd/1'; \
|
||||
echo; \
|
||||
echo '[www]'; \
|
||||
echo 'access.log = /proc/1/fd/1'; \
|
||||
echo 'catch_workers_output = yes'; \
|
||||
echo 'decorate_workers_output = no'; \
|
||||
echo 'clear_env = no'; \
|
||||
} | tee "/etc/php/8.1/fpm/pool.d/zz-docker.conf"
|
||||
|
||||
# PHP files should be handled by PHP, and should be preferred over any other file type
|
||||
RUN { \
|
||||
@@ -64,14 +78,16 @@ RUN \
|
||||
# Configure Realpath cache for performance
|
||||
echo 'realpath_cache_size=4096K'; \
|
||||
echo 'realpath_cache_ttl=600'; \
|
||||
} > /etc/php/8.1/apache2/conf.d/symfony-recommended.ini
|
||||
} > /etc/php/8.1/fpm/conf.d/symfony-recommended.ini
|
||||
|
||||
# Increase upload limit
|
||||
# Increase upload limit and enable preloading
|
||||
RUN \
|
||||
{ \
|
||||
echo 'upload_max_filesize=256M'; \
|
||||
echo 'post_max_size=300M'; \
|
||||
} > /etc/php/8.1/apache2/conf.d/partdb.ini
|
||||
echo 'opcache.preload_user=www-data'; \
|
||||
echo 'opcache.preload=/var/www/html/config/preload.php'; \
|
||||
} > /etc/php/8.1/fpm/conf.d/partdb.ini
|
||||
|
||||
# Install node and yarn
|
||||
RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
|
||||
|
||||
10
README.md
10
README.md
@@ -3,7 +3,7 @@
|
||||

|
||||
[](https://codecov.io/gh/Part-DB/Part-DB-server)
|
||||

|
||||

|
||||

|
||||
|
||||

|
||||

|
||||
@@ -41,7 +41,8 @@ and multiple store locations and price information. Parts can be grouped using t
|
||||
* Barcodes/Labels generator for parts and storage locations, scan barcodes via webcam using the builtin barcode scanner
|
||||
* User system with groups and detailed (fine granular) permissions.
|
||||
Two-factor authentication is supported (Google Authenticator and Webauthn/U2F keys) and can be enforced for groups. Password reset via email can be setuped.
|
||||
* Import/Export system (partial working)
|
||||
* Optional support for single sign-on (SSO) via SAML (using an intermediate service like [Keycloak](https://www.keycloak.org/) you can connect Part-DB to an existing LDAP or Active Directory server)
|
||||
* Import/Export system for parts and datastructure. BOM import for projects from KiCAD is supported.
|
||||
* Project management: Create projects and assign parts to the bill of material (BOM), to show how often you could build this project and directly withdraw all components needed from DB
|
||||
* Event log: Track what changes happens to your inventory, track which user does what. Revert your parts to older versions.
|
||||
* Responsive design: You can use Part-DB on your PC, your tablet and your smartphone using the same interface.
|
||||
@@ -50,6 +51,7 @@ Two-factor authentication is supported (Google Authenticator and Webauthn/U2F ke
|
||||
* Support for multiple currencies and automatic update of exchange rates supported
|
||||
* Powerful search and filter function, including parametric search (search for parts according to some specifications)
|
||||
* Automatic thumbnail generation for pictures
|
||||
* Use cloud providers (like Octopart, Digikey, farnell or TME) to automatically get part information, datasheets and prices for parts
|
||||
|
||||
|
||||
With these features Part-DB is useful to hobbyists, who want to keep track of their private electronic parts inventory,
|
||||
@@ -59,10 +61,10 @@ Part-DB is also used by small companies and universities for managing their inve
|
||||
|
||||
## Requirements
|
||||
* A **web server** (like Apache2 or nginx) that is capable of running [Symfony 5](https://symfony.com/doc/current/reference/requirements.html),
|
||||
this includes a minimum PHP version of **PHP 7.4**
|
||||
this includes a minimum PHP version of **PHP 8.1**
|
||||
* A **MySQL** (at least 5.7) /**MariaDB** (at least 10.2.2) database server if you do not want to use SQLite.
|
||||
* Shell access to your server is highly suggested!
|
||||
* For building the client side assets **yarn** and **nodejs** is needed.
|
||||
* For building the client side assets **yarn** and **nodejs** (>= 18.0) is needed.
|
||||
|
||||
## Installation
|
||||
If you want to upgrade your legacy (< 1.0.0) version of Part-DB to this version, please read [this](https://docs.part-db.de/upgrade_legacy.html) first.
|
||||
|
||||
@@ -9,4 +9,4 @@ fixed before the next release. However, if you find a security vulnerability in
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
If you find a security vulnerability, contact the maintainer directly (Email: security@part-db.de).
|
||||
If you find a security vulnerability, report a vulnerability in the [security section of GitHub](https://github.com/Part-DB/Part-DB-server/security/advisories) or contact the maintainer directly (Email: security@part-db.de)
|
||||
|
||||
3
assets/bootstrap.js
vendored
3
assets/bootstrap.js
vendored
@@ -4,8 +4,7 @@ import { startStimulusApp } from '@symfony/stimulus-bridge';
|
||||
export const app = startStimulusApp(require.context(
|
||||
'@symfony/stimulus-bridge/lazy-controller-loader!./controllers',
|
||||
true,
|
||||
/\.(j|t)sx?$/
|
||||
/\.[jt]sx?$/
|
||||
));
|
||||
|
||||
// register any custom, 3rd party controllers here
|
||||
// app.register('some_controller_name', SomeImportedController);
|
||||
|
||||
@@ -181,7 +181,8 @@ Editor.defaultConfig = {
|
||||
'DejaVu Serif, serif',
|
||||
'Helvetica, Arial, sans-serif',
|
||||
'Times New Roman, Times, serif',
|
||||
'Courier New, Courier, monospace'
|
||||
'Courier New, Courier, monospace',
|
||||
'Unifont, monospace',
|
||||
],
|
||||
supportAllValues: true
|
||||
},
|
||||
|
||||
@@ -76,6 +76,7 @@ const PLACEHOLDERS = [
|
||||
['[[FOOTPRINT_FULL]]', 'Footprint (Full path)'],
|
||||
['[[MASS]]', 'Mass'],
|
||||
['[[MPN]]', 'Manufacturer Product Number (MPN)'],
|
||||
['[[IPN]]', 'Internal Part Number (IPN)'],
|
||||
['[[TAGS]]', 'Tags'],
|
||||
['[[M_STATUS]]', 'Manufacturing status'],
|
||||
['[[DESCRIPTION]]', 'Description'],
|
||||
@@ -96,6 +97,8 @@ const PLACEHOLDERS = [
|
||||
['[[AMOUNT]]', 'Lot amount'],
|
||||
['[[LOCATION]]', 'Storage location'],
|
||||
['[[LOCATION_FULL]]', 'Storage location (Full path)'],
|
||||
['[[OWNER]]', 'Full name of the lot owner'],
|
||||
['[[OWNER_USERNAME]]', 'Username of the lot owner'],
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -110,6 +113,8 @@ const PLACEHOLDERS = [
|
||||
['[[COMMENT_T]]', 'Comment (plain text)'],
|
||||
['[[LAST_MODIFIED]]', 'Last modified datetime'],
|
||||
['[[CREATION_DATE]]', 'Creation datetime'],
|
||||
['[[OWNER]]', 'Full name of the location owner'],
|
||||
['[[OWNER_USERNAME]]', 'Username of the location owner'],
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -39,6 +39,7 @@ Object.assign( window.CKEDITOR_TRANSLATIONS[ 'de' ].dictionary, {
|
||||
'Footprint (Full path)': 'Footprint (Vollständiger Pfad)',
|
||||
'Mass': 'Gewicht',
|
||||
'Manufacturer Product Number (MPN)': 'Hersteller Produktnummer (MPN)',
|
||||
'Internal Part Number (IPN)': 'Internal Part Number (IPN)',
|
||||
'Tags': 'Tags',
|
||||
'Manufacturing status': 'Herstellungsstatus',
|
||||
'Description': 'Beschreibung',
|
||||
@@ -55,6 +56,8 @@ Object.assign( window.CKEDITOR_TRANSLATIONS[ 'de' ].dictionary, {
|
||||
'Lot amount': 'Lot Menge',
|
||||
'Storage location': 'Lagerort',
|
||||
'Storage location (Full path)': 'Lagerort (Vollständiger Pfad)',
|
||||
'Full name of the lot owner': 'Name des Besitzers des Lots',
|
||||
'Username of the lot owner': 'Benutzername des Besitzers des Lots',
|
||||
|
||||
|
||||
'Barcodes': 'Barcodes',
|
||||
@@ -69,6 +72,8 @@ Object.assign( window.CKEDITOR_TRANSLATIONS[ 'de' ].dictionary, {
|
||||
'Full path': 'Vollständiger Pfad',
|
||||
'Parent name': 'Name des Übergeordneten Elements',
|
||||
'Parent full path': 'Ganzer Pfad des Übergeordneten Elements',
|
||||
'Full name of the location owner': 'Name des Besitzers des Lagerorts',
|
||||
'Username of the location owner': 'Benutzername des Besitzers des Lagerorts',
|
||||
|
||||
'Username': 'Benutzername',
|
||||
'Username (including name)': 'Benutzername (inklusive Name)',
|
||||
|
||||
@@ -30,9 +30,73 @@ export default class SpecialCharactersEmoji extends Plugin {
|
||||
const editor = this.editor;
|
||||
const specialCharsPlugin = editor.plugins.get('SpecialCharacters');
|
||||
|
||||
//Add greek characters to special characters
|
||||
specialCharsPlugin.addItems('Greek', this.getGreek());
|
||||
|
||||
//Add Emojis to special characters
|
||||
specialCharsPlugin.addItems('Emoji', this.getEmojis());
|
||||
}
|
||||
|
||||
getGreek() {
|
||||
return [
|
||||
{ title: 'Alpha', character: 'Α' },
|
||||
{ title: 'Beta', character: 'Β' },
|
||||
{ title: 'Gamma', character: 'Γ' },
|
||||
{ title: 'Delta', character: 'Δ' },
|
||||
{ title: 'Epsilon', character: 'Ε' },
|
||||
{ title: 'Zeta', character: 'Ζ' },
|
||||
{ title: 'Eta', character: 'Η' },
|
||||
{ title: 'Theta', character: 'Θ' },
|
||||
{ title: 'Iota', character: 'Ι' },
|
||||
{ title: 'Kappa', character: 'Κ' },
|
||||
{ title: 'Lambda', character: 'Λ' },
|
||||
{ title: 'Mu', character: 'Μ' },
|
||||
{ title: 'Nu', character: 'Ν' },
|
||||
{ title: 'Xi', character: 'Ξ' },
|
||||
{ title: 'Omicron', character: 'Ο' },
|
||||
{ title: 'Pi', character: 'Π' },
|
||||
{ title: 'Rho', character: 'Ρ' },
|
||||
{ title: 'Sigma', character: 'Σ' },
|
||||
{ title: 'Tau', character: 'Τ' },
|
||||
{ title: 'Upsilon', character: 'Υ' },
|
||||
{ title: 'Phi', character: 'Φ' },
|
||||
{ title: 'Chi', character: 'Χ' },
|
||||
{ title: 'Psi', character: 'Ψ' },
|
||||
{ title: 'Omega', character: 'Ω' },
|
||||
{ title: 'alpha', character: 'α' },
|
||||
{ title: 'beta', character: 'β' },
|
||||
{ title: 'gamma', character: 'γ' },
|
||||
{ title: 'delta', character: 'δ' },
|
||||
{ title: 'epsilon', character: 'ε' },
|
||||
{ title: 'zeta', character: 'ζ' },
|
||||
{ title: 'eta', character: 'η' },
|
||||
{ title: 'theta', character: 'θ' },
|
||||
{ title: 'alternate theta', character: 'ϑ' },
|
||||
{ title: 'iota', character: 'ι' },
|
||||
{ title: 'kappa', character: 'κ' },
|
||||
{ title: 'lambda', character: 'λ' },
|
||||
{ title: 'mu', character: 'μ' },
|
||||
{ title: 'nu', character: 'ν' },
|
||||
{ title: 'xi', character: 'ξ' },
|
||||
{ title: 'omicron', character: 'ο' },
|
||||
{ title: 'pi', character: 'π' },
|
||||
{ title: 'rho', character: 'ρ' },
|
||||
{ title: 'sigma', character: 'σ' },
|
||||
{ title: 'tau', character: 'τ' },
|
||||
{ title: 'upsilon', character: 'υ' },
|
||||
{ title: 'phi', character: 'φ' },
|
||||
{ title: 'chi', character: 'χ' },
|
||||
{ title: 'psi', character: 'ψ' },
|
||||
{ title: 'omega', character: 'ω' },
|
||||
{ title: 'digamma', character: 'Ϝ' },
|
||||
{ title: 'stigma', character: 'Ϛ' },
|
||||
{ title: 'heta', character: 'Ͱ' },
|
||||
{ title: 'sampi', character: 'Ϡ' },
|
||||
{ title: 'koppa', character: 'Ϟ' },
|
||||
{ title: 'san', character: 'Ϻ' },
|
||||
];
|
||||
}
|
||||
|
||||
getEmojis() {
|
||||
//Map our emoji data to the format the plugin expects
|
||||
return emoji.map(emoji => {
|
||||
|
||||
@@ -18,43 +18,118 @@
|
||||
*/
|
||||
|
||||
import {Controller} from "@hotwired/stimulus";
|
||||
import Darkmode from "darkmode-js/src";
|
||||
import "darkmode-js"
|
||||
|
||||
export default class extends Controller {
|
||||
|
||||
_darkmode;
|
||||
|
||||
connect() {
|
||||
if (typeof window.getComputedStyle(document.body).mixBlendMode == 'undefined') {
|
||||
console.warn("The browser does not support mix blend mode. Darkmode will not work.");
|
||||
this.setMode(this.getMode());
|
||||
document.querySelectorAll('input[name="darkmode"]').forEach((radio) => {
|
||||
radio.addEventListener('change', this._radioChanged.bind(this));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Event listener for the change of radio buttons
|
||||
* @private
|
||||
*/
|
||||
_radioChanged(event) {
|
||||
const new_mode = this.getSelectedMode();
|
||||
this.setMode(new_mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current mode from the local storage
|
||||
* @return {'dark', 'light', 'auto'}
|
||||
*/
|
||||
getMode() {
|
||||
return localStorage.getItem('darkmode') ?? 'auto';
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the mode in the local storage and apply it and change the state of the radio buttons
|
||||
* @param mode
|
||||
*/
|
||||
setMode(mode) {
|
||||
if (mode !== 'dark' && mode !== 'light' && mode !== 'auto') {
|
||||
console.warn('Invalid darkmode mode: ' + mode);
|
||||
mode = 'auto';
|
||||
}
|
||||
|
||||
localStorage.setItem('darkmode', mode);
|
||||
|
||||
this.setButtonMode(mode);
|
||||
|
||||
if (mode === 'auto') {
|
||||
this._setDarkmodeAuto();
|
||||
} else if (mode === 'dark') {
|
||||
this._enableDarkmode();
|
||||
} else if (mode === 'light') {
|
||||
this._disableDarkmode();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the selected mode via the radio buttons
|
||||
* @return {'dark', 'light', 'auto'}
|
||||
*/
|
||||
getSelectedMode() {
|
||||
return document.querySelector('input[name="darkmode"]:checked').value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the state of the radio buttons
|
||||
* @param mode
|
||||
*/
|
||||
setButtonMode(mode) {
|
||||
document.querySelector('input[name="darkmode"][value="' + mode + '"]').checked = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable darkmode by adding the data-bs-theme="dark" to the html tag
|
||||
* @private
|
||||
*/
|
||||
_enableDarkmode() {
|
||||
//Add data-bs-theme="dark" to the html tag
|
||||
document.documentElement.setAttribute('data-bs-theme', 'dark');
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable darkmode by adding the data-bs-theme="light" to the html tag
|
||||
* @private
|
||||
*/
|
||||
_disableDarkmode() {
|
||||
//Set data-bs-theme to light
|
||||
document.documentElement.setAttribute('data-bs-theme', 'light');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the darkmode to auto and enable/disable it depending on the system settings, also add
|
||||
* an event listener to change the darkmode if the system settings change
|
||||
* @private
|
||||
*/
|
||||
_setDarkmodeAuto() {
|
||||
if (this.getMode() !== 'auto') {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const darkmode = new Darkmode();
|
||||
this._darkmode = darkmode;
|
||||
|
||||
//Unhide darkmode button
|
||||
this._showWidget();
|
||||
|
||||
//Set the switch according to our current darkmode state
|
||||
const toggler = document.getElementById("toggleDarkmode");
|
||||
toggler.checked = darkmode.isActivated();
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
console.error(e);
|
||||
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
||||
this._enableDarkmode();
|
||||
} else {
|
||||
this._disableDarkmode();
|
||||
}
|
||||
|
||||
|
||||
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => {
|
||||
console.log('Prefered color scheme changed to ' + event.matches ? 'dark' : 'light');
|
||||
this._setDarkmodeAuto();
|
||||
});
|
||||
}
|
||||
|
||||
_showWidget() {
|
||||
this.element.classList.remove('hidden');
|
||||
}
|
||||
|
||||
toggleDarkmode() {
|
||||
this._darkmode.toggle();
|
||||
/**
|
||||
* Check if darkmode is activated
|
||||
* @return {boolean}
|
||||
*/
|
||||
isDarkmodeActivated() {
|
||||
return document.documentElement.getAttribute('data-bs-theme') === 'dark';
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,8 @@
|
||||
|
||||
import { Controller } from '@hotwired/stimulus';
|
||||
import { marked } from "marked";
|
||||
import { mangle } from "marked-mangle";
|
||||
import { gfmHeadingId } from "marked-gfm-heading-id";
|
||||
import DOMPurify from 'dompurify';
|
||||
|
||||
import "../../css/app/markdown.css";
|
||||
@@ -81,6 +83,10 @@ export default class extends Controller {
|
||||
*/
|
||||
configureMarked()
|
||||
{
|
||||
marked.use(mangle());
|
||||
marked.use(gfmHeadingId({
|
||||
}));
|
||||
|
||||
marked.setOptions({
|
||||
gfm: true,
|
||||
});
|
||||
|
||||
@@ -27,6 +27,7 @@ export default class extends Controller {
|
||||
deleteMessage: String,
|
||||
prototype: String,
|
||||
rowsToDelete: Number, //How many rows (including the current one) shall be deleted after the current row
|
||||
fieldPlaceholder: String
|
||||
}
|
||||
|
||||
static targets = ["target"];
|
||||
@@ -60,13 +61,16 @@ export default class extends Controller {
|
||||
|
||||
if(!prototype) {
|
||||
console.warn("Prototype is not set, we cannot create a new element. This is most likely due to missing permissions.");
|
||||
bootbox.alert("You do not have the permsissions to create a new element. (No protoype element is set)");
|
||||
bootbox.alert("You do not have the permissions to create a new element. (No protoype element is set)");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const regexString = this.fieldPlaceholderValue || "__name__";
|
||||
const regex = new RegExp(regexString, "g");
|
||||
|
||||
//Apply the index to prototype to create our element to insert
|
||||
const newElementStr = this.htmlDecode(prototype.replace(/__name__/g, this.generateUID()));
|
||||
const newElementStr = this.htmlDecode(prototype.replace(regex, this.generateUID()));
|
||||
|
||||
|
||||
//Insert new html after the last child element
|
||||
|
||||
@@ -65,8 +65,22 @@ export default class extends Controller {
|
||||
localStorage.setItem( this.getStateSaveKey(), JSON.stringify(data) );
|
||||
}
|
||||
|
||||
stateLoadCallback(settings) {
|
||||
return JSON.parse( localStorage.getItem(this.getStateSaveKey()) );
|
||||
stateLoadCallback() {
|
||||
const json = localStorage.getItem(this.getStateSaveKey());
|
||||
if(json === null || json === undefined) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const data = JSON.parse(json);
|
||||
|
||||
if (data) {
|
||||
//Do not save the start value (current page), as we want to always start at the first page on a page reload
|
||||
delete data.start;
|
||||
//Reset the data length to the default value by deleting the length property
|
||||
delete data.length;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
connect() {
|
||||
@@ -81,6 +95,19 @@ export default class extends Controller {
|
||||
//Add url info, as the one available in the history is not enough, as Turbo may have not changed it yet
|
||||
settings.url = this.element.dataset.dtUrl;
|
||||
|
||||
//Add initial_order info to the settings, so that the order on the initial page load is the one saved in the state
|
||||
const saved_state = this.stateLoadCallback();
|
||||
if (saved_state !== null) {
|
||||
const raw_order = saved_state.order;
|
||||
|
||||
settings.initial_order = raw_order.map((order) => {
|
||||
return {
|
||||
column: order[0],
|
||||
dir: order[1]
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
let options = {
|
||||
colReorder: true,
|
||||
responsive: true,
|
||||
@@ -90,7 +117,7 @@ export default class extends Controller {
|
||||
},
|
||||
buttons: [{
|
||||
"extend": 'colvis',
|
||||
'className': 'mr-2 btn-light',
|
||||
'className': 'mr-2 btn-outline-secondary',
|
||||
'columns': ':not(.no-colvis)',
|
||||
"text": "<i class='fa fa-cog'></i>"
|
||||
}],
|
||||
@@ -116,6 +143,22 @@ export default class extends Controller {
|
||||
console.error("Error initializing datatables: " + err);
|
||||
});
|
||||
|
||||
//Fix height of the length selector
|
||||
promise.then((dt) => {
|
||||
//Find all length selectors (select with name dt_length), which are inside a label
|
||||
const lengthSelectors = document.querySelectorAll('label select[name="dt_length"]');
|
||||
//And remove the surrounding label, while keeping the select with all event handlers
|
||||
lengthSelectors.forEach((selector) => {
|
||||
selector.parentElement.replaceWith(selector);
|
||||
});
|
||||
|
||||
//Find all column visibility buttons (button with buttons-colvis class) and remove the btn-secondary class
|
||||
const colVisButtons = document.querySelectorAll('button.buttons-colvis');
|
||||
colVisButtons.forEach((button) => {
|
||||
button.classList.remove('btn-secondary');
|
||||
});
|
||||
});
|
||||
|
||||
//Dispatch an event to let others know that the datatables has been loaded
|
||||
promise.then((dt) => {
|
||||
const event = new CustomEvent(EVENT_DT_LOADED, {bubbles: true});
|
||||
@@ -137,6 +180,27 @@ export default class extends Controller {
|
||||
dt.fixedHeader.headerOffset($("#navbar").outerHeight());
|
||||
});
|
||||
|
||||
//Register event handler to selectAllRows checkbox if available
|
||||
if (this.isSelectable()) {
|
||||
promise.then((dt) => {
|
||||
const selectAllCheckbox = this.element.querySelector('thead th.select-checkbox');
|
||||
selectAllCheckbox.addEventListener('click', () => {
|
||||
if(selectAllCheckbox.parentElement.classList.contains('selected')) {
|
||||
dt.rows().deselect();
|
||||
selectAllCheckbox.parentElement.classList.remove('selected');
|
||||
} else {
|
||||
dt.rows().select();
|
||||
selectAllCheckbox.parentElement.classList.add('selected');
|
||||
}
|
||||
});
|
||||
|
||||
//When any row is deselected, also deselect the selectAll checkbox
|
||||
dt.on('deselect.dt', () => {
|
||||
selectAllCheckbox.parentElement.classList.remove('selected');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
//Allow to further configure the datatable
|
||||
promise.then(this._afterLoaded.bind(this));
|
||||
|
||||
@@ -175,4 +239,16 @@ export default class extends Controller {
|
||||
return this.element.dataset.select ?? false;
|
||||
}
|
||||
|
||||
}
|
||||
invertSelection() {
|
||||
//Do nothing if the datatable is not selectable
|
||||
if(!this.isSelectable()) {
|
||||
return;
|
||||
}
|
||||
|
||||
//Invert the selected rows on the datatable
|
||||
const selected_rows = this._dt.rows({selected: true});
|
||||
this._dt.rows().select();
|
||||
selected_rows.deselect();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -107,6 +107,13 @@ export default class extends DatatablesController {
|
||||
//Hide the select element (the tomselect button is the sibling of the select element)
|
||||
select_target.nextElementSibling.classList.add('d-none');
|
||||
}
|
||||
|
||||
//If the selected option has a data-turbo attribute, set it to the form
|
||||
if (selected_option.dataset.turbo) {
|
||||
this.element.dataset.turbo = selected_option.dataset.turbo;
|
||||
} else {
|
||||
this.element.dataset.turbo = true;
|
||||
}
|
||||
}
|
||||
|
||||
confirmDeletionAtSubmit(event) {
|
||||
|
||||
@@ -29,62 +29,46 @@ export default class extends Controller
|
||||
this._confirmed = false;
|
||||
}
|
||||
|
||||
click(event) {
|
||||
//If a user has not already confirmed the deletion, just let turbo do its work
|
||||
if(this._confirmed) {
|
||||
this._confirmed = false;
|
||||
return;
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
const message = this.element.dataset.deleteMessage;
|
||||
const title = this.element.dataset.deleteTitle;
|
||||
|
||||
const that = this;
|
||||
|
||||
const confirm = bootbox.confirm({
|
||||
message: message, title: title, callback: function (result) {
|
||||
//If the dialog was confirmed, then submit the form.
|
||||
if (result) {
|
||||
that._confirmed = true;
|
||||
event.target.click();
|
||||
} else {
|
||||
that._confirmed = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
submit(event) {
|
||||
//If a user has not already confirmed the deletion, just let turbo do its work
|
||||
if(this._confirmed) {
|
||||
if (this._confirmed) {
|
||||
this._confirmed = false;
|
||||
return;
|
||||
}
|
||||
|
||||
//Prevent turbo from doing its work
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
const message = this.element.dataset.deleteMessage;
|
||||
const title = this.element.dataset.deleteTitle;
|
||||
|
||||
const form = this.element;
|
||||
const submitter = event.submitter;
|
||||
const that = this;
|
||||
|
||||
//Create a clone of the event with the same submitter, so we can redispatch it if needed
|
||||
//We need to do this that way, as we need the submitter info, just calling form.submit() would not work
|
||||
this._our_event = new SubmitEvent('submit', {
|
||||
submitter: event.submitter,
|
||||
bubbles: true, //This line is important, otherwise Turbo will not receive the event
|
||||
});
|
||||
|
||||
const confirm = bootbox.confirm({
|
||||
message: message, title: title, callback: function (result) {
|
||||
//If the dialog was confirmed, then submit the form.
|
||||
if (result) {
|
||||
//Set a flag to prevent the dialog from popping up again and allowing turbo to submit the form
|
||||
that._confirmed = true;
|
||||
form.dispatchEvent(that._our_event);
|
||||
|
||||
//Create a submit button in the form and click it to submit the form
|
||||
//Before a submit event was dispatched, but this caused weird issues on Firefox causing the delete request being posted twice (and the second time was returning 404). See https://github.com/Part-DB/Part-DB-server/issues/273
|
||||
const submit_btn = document.createElement('button');
|
||||
submit_btn.type = 'submit';
|
||||
submit_btn.style.display = 'none';
|
||||
|
||||
//If the clicked button has a value, set it on the submit button
|
||||
if (submitter.value) {
|
||||
submit_btn.value = submitter.value;
|
||||
}
|
||||
if (submitter.name) {
|
||||
submit_btn.name = submitter.name;
|
||||
}
|
||||
form.appendChild(submit_btn);
|
||||
submit_btn.click();
|
||||
} else {
|
||||
that._confirmed = false;
|
||||
}
|
||||
|
||||
40
assets/controllers/elements/json_formatter_controller.js
Normal file
40
assets/controllers/elements/json_formatter_controller.js
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
|
||||
*
|
||||
* Copyright (C) 2019 - 2023 Jan Böhmer (https://github.com/jbtronics)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published
|
||||
* by the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
import {Controller} from "@hotwired/stimulus";
|
||||
|
||||
import JSONFormatter from 'json-formatter-js';
|
||||
|
||||
/**
|
||||
* This controller implements an element that renders a JSON object as a collapsible tree.
|
||||
* The JSON object is passed as a data attribute.
|
||||
* You have to apply the controller to a div element or similar block element which can contain other elements.
|
||||
*/
|
||||
export default class extends Controller {
|
||||
connect() {
|
||||
const depth_to_open = this.element.dataset.depthToOpen ?? 0;
|
||||
const json_string = this.element.dataset.json;
|
||||
const json_object = JSON.parse(json_string);
|
||||
|
||||
const formatter = new JSONFormatter(json_object, depth_to_open);
|
||||
|
||||
this.element.appendChild(formatter.render());
|
||||
}
|
||||
}
|
||||
72
assets/controllers/elements/link_confirm_controller.js
Normal file
72
assets/controllers/elements/link_confirm_controller.js
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
|
||||
*
|
||||
* Copyright (C) 2019 - 2022 Jan Böhmer (https://github.com/jbtronics)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published
|
||||
* by the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {Controller} from "@hotwired/stimulus";
|
||||
|
||||
import * as bootbox from "bootbox";
|
||||
import "../../css/components/bootbox_extensions.css";
|
||||
|
||||
export default class extends Controller
|
||||
{
|
||||
|
||||
static values = {
|
||||
message: String,
|
||||
title: String
|
||||
}
|
||||
|
||||
|
||||
|
||||
connect()
|
||||
{
|
||||
this._confirmed = false;
|
||||
|
||||
this.element.addEventListener('click', this._onClick.bind(this));
|
||||
}
|
||||
|
||||
_onClick(event)
|
||||
{
|
||||
|
||||
//If a user has not already confirmed the deletion, just let turbo do its work
|
||||
if (this._confirmed) {
|
||||
this._confirmed = false;
|
||||
return;
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
const that = this;
|
||||
|
||||
bootbox.confirm({
|
||||
title: this.titleValue,
|
||||
message: this.messageValue,
|
||||
callback: (result) => {
|
||||
if (result) {
|
||||
//Set a flag to prevent the dialog from popping up again and allowing turbo to submit the form
|
||||
that._confirmed = true;
|
||||
|
||||
//Click the link
|
||||
that.element.click();
|
||||
} else {
|
||||
that._confirmed = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
|
||||
*
|
||||
* Copyright (C) 2019 - 2023 Jan Böhmer (https://github.com/jbtronics)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published
|
||||
* by the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
import {Controller} from "@hotwired/stimulus";
|
||||
import { zxcvbn, zxcvbnOptions } from '@zxcvbn-ts/core';
|
||||
import * as zxcvbnCommonPackage from '@zxcvbn-ts/language-common';
|
||||
import * as zxcvbnEnPackage from '@zxcvbn-ts/language-en';
|
||||
import * as zxcvbnDePackage from '@zxcvbn-ts/language-de';
|
||||
import * as zxcvbnFrPackage from '@zxcvbn-ts/language-fr';
|
||||
import * as zxcvbnJaPackage from '@zxcvbn-ts/language-ja';
|
||||
import {trans, USER_PASSWORD_STRENGTH_VERY_WEAK, USER_PASSWORD_STRENGTH_WEAK, USER_PASSWORD_STRENGTH_MEDIUM,
|
||||
USER_PASSWORD_STRENGTH_STRONG, USER_PASSWORD_STRENGTH_VERY_STRONG} from '../../translator.js';
|
||||
|
||||
/* stimulusFetch: 'lazy' */
|
||||
export default class extends Controller {
|
||||
|
||||
_passwordInput;
|
||||
|
||||
static targets = ["badge", "warning"]
|
||||
|
||||
_getTranslations() {
|
||||
//Get the current locale
|
||||
const locale = document.documentElement.lang;
|
||||
if (locale.includes('de')) {
|
||||
return zxcvbnDePackage.translations;
|
||||
} else if (locale.includes('fr')) {
|
||||
return zxcvbnFrPackage.translations;
|
||||
} else if (locale.includes('ja')) {
|
||||
return zxcvbnJaPackage.translations;
|
||||
}
|
||||
|
||||
//Fallback to english
|
||||
return zxcvbnEnPackage.translations;
|
||||
}
|
||||
|
||||
connect() {
|
||||
//Find the password input field
|
||||
this._passwordInput = this.element.querySelector('input[type="password"]');
|
||||
|
||||
//Configure zxcvbn
|
||||
const options = {
|
||||
graphs: zxcvbnCommonPackage.adjacencyGraphs,
|
||||
dictionary: {
|
||||
...zxcvbnCommonPackage.dictionary,
|
||||
// We could use the english dictionary here too, but it is very big. So we just use the common words
|
||||
//...zxcvbnEnPackage.dictionary,
|
||||
},
|
||||
translations: this._getTranslations(),
|
||||
};
|
||||
zxcvbnOptions.setOptions(options);
|
||||
|
||||
//Add event listener to the password input field
|
||||
this._passwordInput.addEventListener('input', this._onPasswordInput.bind(this));
|
||||
}
|
||||
|
||||
_onPasswordInput() {
|
||||
//Retrieve the password
|
||||
const password = this._passwordInput.value;
|
||||
|
||||
//Estimate the password strength
|
||||
const result = zxcvbn(password);
|
||||
|
||||
//Update the badge
|
||||
this.badgeTarget.parentElement.classList.remove("d-none");
|
||||
this._setBadgeToLevel(result.score);
|
||||
|
||||
this.warningTarget.innerHTML = result.feedback.warning;
|
||||
}
|
||||
|
||||
_setBadgeToLevel(level) {
|
||||
let text, classes;
|
||||
|
||||
switch (level) {
|
||||
case 0:
|
||||
text = trans(USER_PASSWORD_STRENGTH_VERY_WEAK);
|
||||
classes = "bg-danger badge-danger";
|
||||
break;
|
||||
case 1:
|
||||
text = trans(USER_PASSWORD_STRENGTH_WEAK);
|
||||
classes = "bg-warning badge-warning";
|
||||
break;
|
||||
case 2:
|
||||
text = trans(USER_PASSWORD_STRENGTH_MEDIUM)
|
||||
classes = "bg-info badge-info";
|
||||
break;
|
||||
case 3:
|
||||
text = trans(USER_PASSWORD_STRENGTH_STRONG);
|
||||
classes = "bg-primary badge-primary";
|
||||
break;
|
||||
case 4:
|
||||
text = trans(USER_PASSWORD_STRENGTH_VERY_STRONG);
|
||||
classes = "bg-success badge-success";
|
||||
break;
|
||||
default:
|
||||
text = "???";
|
||||
classes = "bg-secondary badge-secondary";
|
||||
}
|
||||
|
||||
this.badgeTarget.innerHTML = text;
|
||||
//Remove all classes
|
||||
this.badgeTarget.className = '';
|
||||
//Re-add the classes
|
||||
this.badgeTarget.classList.add("badge");
|
||||
this.badgeTarget.classList.add(...classes.split(" "));
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,8 @@ import '../../css/components/tom-select_extensions.css';
|
||||
import TomSelect from "tom-select";
|
||||
import {Controller} from "@hotwired/stimulus";
|
||||
|
||||
import {trans, ENTITY_SELECT_GROUP_NEW_NOT_ADDED_TO_DB} from '../../translator.js'
|
||||
|
||||
|
||||
export default class extends Controller {
|
||||
_tomSelect;
|
||||
@@ -40,8 +42,7 @@ export default class extends Controller {
|
||||
allowEmptyOption: true,
|
||||
selectOnTab: true,
|
||||
maxOptions: null,
|
||||
create: allowAdd,
|
||||
createFilter: /\D/, //Must contain a non-digit character, otherwise they would be recognized as DB ID
|
||||
create: allowAdd ? this.createItem.bind(this) : false,
|
||||
|
||||
searchField: [
|
||||
{field: "text", weight : 2},
|
||||
@@ -57,10 +58,38 @@ export default class extends Controller {
|
||||
'<small class="text-muted float-end">(' + addHint +')</small>' +
|
||||
'</div>';
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
//Add callbacks to update validity
|
||||
onInitialize: this.updateValidity.bind(this),
|
||||
onChange: this.updateValidity.bind(this),
|
||||
};
|
||||
|
||||
this._tomSelect = new TomSelect(this.element, settings);
|
||||
this._tomSelect.sync();
|
||||
}
|
||||
|
||||
createItem(input, callback) {
|
||||
callback({
|
||||
//$%$ is a special value prefix, that is used to identify items, that are not yet in the DB
|
||||
value: '$%$' + input,
|
||||
text: input,
|
||||
not_in_db_yet: true,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
updateValidity() {
|
||||
//Mark this input as invalid, if the selected option is disabled
|
||||
|
||||
const input = this.element;
|
||||
const selectedOption = input.options[input.selectedIndex];
|
||||
|
||||
if (selectedOption && selectedOption.disabled) {
|
||||
input.setCustomValidity("This option was disabled. Please select another option.");
|
||||
} else {
|
||||
input.setCustomValidity("");
|
||||
}
|
||||
}
|
||||
|
||||
getTomSelect() {
|
||||
@@ -78,14 +107,27 @@ export default class extends Controller {
|
||||
}
|
||||
|
||||
if (data.short) {
|
||||
return '<div><b>' + escape(data.short) + '</b></div>';
|
||||
let short = escape(data.short)
|
||||
|
||||
//Make text italic, if the item is not yet in the DB
|
||||
if (data.not_in_db_yet) {
|
||||
short = '<i>' + short + '</i>';
|
||||
}
|
||||
|
||||
return '<div><b>' + short + '</b></div>';
|
||||
}
|
||||
|
||||
let name = "";
|
||||
if (data.parent) {
|
||||
name += escape(data.parent) + " → ";
|
||||
}
|
||||
name += "<b>" + escape(data.text) + "</b>";
|
||||
|
||||
if (data.not_in_db_yet) {
|
||||
//Not yet added items are shown italic and with a badge
|
||||
name += "<i><b>" + escape(data.text) + "</b></i>" + "<span class='ms-3 badge bg-info badge-info'>" + trans(ENTITY_SELECT_GROUP_NEW_NOT_ADDED_TO_DB) + "</span>";
|
||||
} else {
|
||||
name += "<b>" + escape(data.text) + "</b>";
|
||||
}
|
||||
|
||||
return '<div>' + (data.image ? "<img class='structural-entity-select-image' style='margin-right: 5px;' ' src='" + data.image + "'/>" : "") + name + '</div>';
|
||||
}
|
||||
|
||||
@@ -81,6 +81,14 @@ export default class extends Controller {
|
||||
this._tree.remove();
|
||||
}
|
||||
|
||||
const BS53Theme = {
|
||||
getOptions() {
|
||||
return {
|
||||
onhoverColor: 'var(--bs-secondary-bg)',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
this._tree = new BSTreeView(this.treeTarget, {
|
||||
levels: 1,
|
||||
showTags: this._showTags,
|
||||
@@ -93,7 +101,7 @@ export default class extends Controller {
|
||||
}
|
||||
},
|
||||
//onNodeContextmenu: contextmenu_handler,
|
||||
}, [BS5Theme, FAIconTheme]);
|
||||
}, [BS5Theme, BS53Theme, FAIconTheme]);
|
||||
|
||||
this.treeTarget.addEventListener(EVENT_INITIALIZED, (event) => {
|
||||
/** @type {BSTreeView} */
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
|
||||
*
|
||||
* Copyright (C) 2019 - 2022 Jan Böhmer (https://github.com/jbtronics)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published
|
||||
* by the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {Controller} from "@hotwired/stimulus";
|
||||
|
||||
/**
|
||||
* This controller is used on a checkbox, which toggles the max value of all number input fields
|
||||
*/
|
||||
export default class extends Controller {
|
||||
|
||||
_checkbox;
|
||||
|
||||
getCheckbox() {
|
||||
if (this._checkbox) {
|
||||
return this._checkbox;
|
||||
}
|
||||
|
||||
//Find the checkbox inside the controller element
|
||||
this._checkbox = this.element.querySelector('input[type="checkbox"]');
|
||||
return this._checkbox;
|
||||
}
|
||||
|
||||
connect() {
|
||||
//Add event listener to the checkbox
|
||||
this.getCheckbox().addEventListener('change', this.toggleInputLimits.bind(this));
|
||||
}
|
||||
|
||||
toggleInputLimits() {
|
||||
//Find all input fields with the data-toggle-input-limits-target="max"
|
||||
const inputFields = document.querySelectorAll("input[type='number']");
|
||||
|
||||
inputFields.forEach((inputField) => {
|
||||
//Ensure that the input field has either a max or a data-max attribute
|
||||
if (!inputField.hasAttribute('max') && !inputField.hasAttribute('data-max')) {
|
||||
return;
|
||||
}
|
||||
|
||||
//If the checkbox is checked, rename the max attribute to data-max
|
||||
if (this.getCheckbox().checked) {
|
||||
inputField.setAttribute('data-max', inputField.getAttribute('max'));
|
||||
inputField.removeAttribute('max');
|
||||
} else {
|
||||
//If the checkbox is not checked, rename the data-max attribute back to max
|
||||
inputField.setAttribute('max', inputField.getAttribute('data-max'));
|
||||
inputField.removeAttribute('data-max');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -99,10 +99,25 @@ label:not(.form-check-label, .custom-control-label) {
|
||||
|
||||
form .col-form-label.required:after, form label.required:after {
|
||||
bottom: 4px;
|
||||
color: var(--bs-dark);
|
||||
color: var(--bs-secondary-color);
|
||||
content: "\2022";
|
||||
filter: opacity(75%);
|
||||
position: relative;
|
||||
right: -2px;
|
||||
z-index: 700;
|
||||
}
|
||||
|
||||
/****************************************
|
||||
* HTML diff styling
|
||||
****************************************/
|
||||
|
||||
/* Insertations are marked with green background and bold */
|
||||
ins {
|
||||
background-color: #95f095;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
del {
|
||||
background-color: #f09595;
|
||||
font-weight: bold;
|
||||
}
|
||||
@@ -67,7 +67,6 @@ ul.structural_link {
|
||||
padding-bottom: 7px;
|
||||
padding-left: 0;
|
||||
list-style: none;
|
||||
background-color: inherit;
|
||||
}
|
||||
|
||||
/* Display list items side by side */
|
||||
@@ -79,7 +78,7 @@ ul.structural_link li {
|
||||
/* Add a slash symbol (/) before/behind each list item */
|
||||
ul.structural_link li+li:before {
|
||||
padding: 2px;
|
||||
color: grey;
|
||||
color: var(--bs-tertiary-color);
|
||||
/*content: "/\00a0";*/
|
||||
font-family: "Font Awesome 5 Free";
|
||||
font-weight: 900;
|
||||
@@ -89,13 +88,13 @@ ul.structural_link li+li:before {
|
||||
|
||||
/* Add a color to all links inside the list */
|
||||
ul.structural_link li a {
|
||||
color: #0275d8;
|
||||
color: var(--bs-link-color);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* Add a color on mouse-over */
|
||||
ul.structural_link li a:hover {
|
||||
color: #01447e;
|
||||
color: var(--bs-link-hover-color);
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
|
||||
@@ -46,4 +46,19 @@
|
||||
height: 1.5em;
|
||||
max-width: 2.0em;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.part-table-image {
|
||||
max-height: 40px;
|
||||
object-fit: contain;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.part-info-image {
|
||||
max-height: 350px;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.object-fit-cover {
|
||||
object-fit: cover;
|
||||
}
|
||||
@@ -78,8 +78,6 @@ body {
|
||||
overflow: -moz-scrollbars-none;
|
||||
/* Use standard version for hiding the scrollbar */
|
||||
scrollbar-width: none;
|
||||
|
||||
background-color: var(--light);
|
||||
}
|
||||
|
||||
#sidebar-container {
|
||||
|
||||
@@ -89,8 +89,9 @@ th.select-checkbox {
|
||||
}
|
||||
|
||||
/** Fix datatables select-checkbox position */
|
||||
table.dataTable tr.selected td.select-checkbox:after, table.dataTable tr.selected th.select-checkbox:after {
|
||||
margin-top: -28px !important;
|
||||
table.dataTable tr.selected td.select-checkbox:after
|
||||
{
|
||||
margin-top: -20px !important;
|
||||
}
|
||||
|
||||
|
||||
@@ -102,4 +103,53 @@ Classes for Datatables export
|
||||
#export-messageTop,
|
||||
.export-helper{
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************
|
||||
* Styling for the select all checkbox in the parts table
|
||||
* Should match the styling of the select checkbox
|
||||
******************************************************/
|
||||
table.dataTable > thead > tr > th.select-checkbox {
|
||||
position: relative;
|
||||
}
|
||||
table.dataTable > thead > tr > th.select-checkbox:before,
|
||||
table.dataTable > thead > tr > th.select-checkbox:after {
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 0.9em;
|
||||
left: 50%;
|
||||
width: 1em !important;
|
||||
height: 1em !important;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
table.dataTable > thead > tr > th.select-checkbox:before {
|
||||
content: " ";
|
||||
margin-top: -5px;
|
||||
margin-left: -6px;
|
||||
border: 2px solid var(--bs-tertiary-color);
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
table.dataTable > tbody > tr > td.select-checkbox:before, table.dataTable > tbody > tr > th.select-checkbox:before {
|
||||
border: 2px solid var(--bs-tertiary-color) !important;
|
||||
}
|
||||
|
||||
table.dataTable > tbody > tr > td.select-checkbox:before, table.dataTable > tbody > tr > td.select-checkbox:after, table.dataTable > tbody > tr > th.select-checkbox:before, table.dataTable > tbody > tr > th.select-checkbox:after {
|
||||
width: 1em !important;
|
||||
height: 1em !important;
|
||||
}
|
||||
|
||||
table.dataTable > thead > tr.selected > th.select-checkbox:after {
|
||||
content: "✓";
|
||||
font-size: 20px;
|
||||
margin-top: -20px;
|
||||
margin-left: -6px;
|
||||
text-align: center;
|
||||
/*text-shadow: 1px 1px #B0BED9, -1px -1px #B0BED9, 1px -1px #B0BED9, -1px 1px #B0BED9; */
|
||||
}
|
||||
table.dataTable.compact > thead > tr > th.select-checkbox:before {
|
||||
margin-top: -12px;
|
||||
}
|
||||
table.dataTable.compact > thead > tr.selected > th.select-checkbox:after {
|
||||
margin-top: -16px;
|
||||
}
|
||||
|
||||
@@ -36,3 +36,42 @@
|
||||
.ck-html-label .ck-content hr {
|
||||
margin: 2px;
|
||||
}
|
||||
|
||||
/***********************************************
|
||||
* Hide CKEditor powered by message
|
||||
***********************************************/
|
||||
.ck-powered-by {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/***********************************************
|
||||
* Use Bootstrap color vars for CKEditor
|
||||
***********************************************/
|
||||
:root {
|
||||
--ck-color-base-foreground: var(--bs-secondary-bg);
|
||||
--ck-color-base-background: var(--bs-body-bg);
|
||||
--ck-color-base-border: var(--bs-border-color);
|
||||
--ck-color-base-action: var(--bs-success);
|
||||
--ck-color-base-focus: var(--bs-primary-border-subtle);
|
||||
--ck-color-base-text: var(--bs-body-color);
|
||||
--ck-color-base-active: var(--bs-primary-bg-subtle);
|
||||
--ck-color-base-active-focus: var(--bs-primary);
|
||||
--ck-color-base-error: var(--bs-danger);
|
||||
|
||||
/* Improve contrast between text and toolbar */
|
||||
--ck-color-toolbar-background: var(--bs-tertiary-bg);
|
||||
|
||||
/* Buttons */
|
||||
--ck-color-button-default-hover-background: var(--bs-secondary-bg);
|
||||
--ck-color-button-default-active-background: var(--bs-secondary-bg);
|
||||
|
||||
--ck-color-button-on-background: var(--bs-body-bg);
|
||||
--ck-color-button-on-hover-background: var(--bs-secondary-bg);
|
||||
--ck-color-button-on-active-background: var(--bs-secondary-bg);
|
||||
--ck-color-button-on-disabled-background: var(--bs-secondary-bg);
|
||||
--ck-color-button-on-color: var(--bs-primary)
|
||||
|
||||
}
|
||||
@@ -18,6 +18,29 @@
|
||||
*/
|
||||
|
||||
.tagsinput.ts-wrapper.multi .ts-control > div {
|
||||
background: var(--bs-secondary);
|
||||
color: var(--bs-white);
|
||||
}
|
||||
background: var(--bs-secondary-bg);
|
||||
color: var(--bs-body-color);
|
||||
}
|
||||
|
||||
/*********
|
||||
* BS 5.3 compatible dark mode
|
||||
***************/
|
||||
|
||||
.ts-dropdown .active {
|
||||
background-color: var(--bs-secondary-bg) !important;
|
||||
color: var(--bs-body-color) !important;
|
||||
}
|
||||
|
||||
.ts-dropdown, .ts-control, .ts-control input {
|
||||
color: var(--bs-body-color) !important;
|
||||
}
|
||||
|
||||
.ts-dropdown, .ts-dropdown.form-control, .ts-dropdown.form-select {
|
||||
background: var(--bs-body-bg);
|
||||
}
|
||||
|
||||
.ts-dropdown .optgroup-header {
|
||||
color: var(--bs-tertiary-color);
|
||||
background: var(--bs-body-bg);
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
3
assets/fonts/dompdf/.gitignore
vendored
Normal file
3
assets/fonts/dompdf/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
# Ignore font files
|
||||
*.otf
|
||||
*.ttf
|
||||
1
assets/fonts/dompdf/README.md
Normal file
1
assets/fonts/dompdf/README.md
Normal file
@@ -0,0 +1 @@
|
||||
Put your font ttf files in this folder to make them available to the label generator.
|
||||
@@ -22,7 +22,6 @@
|
||||
|
||||
import '../css/app/layout.css';
|
||||
import '../css/app/helpers.css';
|
||||
import '../css/app/darkmode.css';
|
||||
import '../css/app/tables.css';
|
||||
import '../css/app/bs-overrides.css';
|
||||
import '../css/app/treeview.css';
|
||||
|
||||
@@ -27,14 +27,67 @@ class ErrorHandlerHelper {
|
||||
constructor() {
|
||||
console.log('Error Handler registered');
|
||||
|
||||
const content = document.getElementById('content');
|
||||
content.addEventListener('turbo:before-fetch-response', (event) => this.handleError(event));
|
||||
//const content = document.getElementById('content');
|
||||
//It seems that the content element is unreliable for these events, so we use the document instead
|
||||
const content = document;
|
||||
//content.addEventListener('turbo:before-fetch-response', (event) => this.handleError(event));
|
||||
content.addEventListener('turbo:fetch-request-error', (event) => this.handleError(event));
|
||||
content.addEventListener('turbo:frame-missing', (event) => this.handleError(event));
|
||||
|
||||
$(document).ajaxError(this.handleJqueryErrror.bind(this));
|
||||
}
|
||||
|
||||
_showAlert(statusText, statusCode, location, responseHTML)
|
||||
{
|
||||
const httpStatusToText = {
|
||||
'200': 'OK',
|
||||
'201': 'Created',
|
||||
'202': 'Accepted',
|
||||
'203': 'Non-Authoritative Information',
|
||||
'204': 'No Content',
|
||||
'205': 'Reset Content',
|
||||
'206': 'Partial Content',
|
||||
'300': 'Multiple Choices',
|
||||
'301': 'Moved Permanently',
|
||||
'302': 'Found',
|
||||
'303': 'See Other',
|
||||
'304': 'Not Modified',
|
||||
'305': 'Use Proxy',
|
||||
'306': 'Unused',
|
||||
'307': 'Temporary Redirect',
|
||||
'400': 'Bad Request',
|
||||
'401': 'Unauthorized',
|
||||
'402': 'Payment Required',
|
||||
'403': 'Forbidden',
|
||||
'404': 'Not Found',
|
||||
'405': 'Method Not Allowed',
|
||||
'406': 'Not Acceptable',
|
||||
'407': 'Proxy Authentication Required',
|
||||
'408': 'Request Timeout',
|
||||
'409': 'Conflict',
|
||||
'410': 'Gone',
|
||||
'411': 'Length Required',
|
||||
'412': 'Precondition Required',
|
||||
'413': 'Request Entry Too Large',
|
||||
'414': 'Request-URI Too Long',
|
||||
'415': 'Unsupported Media Type',
|
||||
'416': 'Requested Range Not Satisfiable',
|
||||
'417': 'Expectation Failed',
|
||||
'418': 'I\'m a teapot',
|
||||
'429': 'Too Many Requests',
|
||||
'500': 'Internal Server Error',
|
||||
'501': 'Not Implemented',
|
||||
'502': 'Bad Gateway',
|
||||
'503': 'Service Unavailable',
|
||||
'504': 'Gateway Timeout',
|
||||
'505': 'HTTP Version Not Supported',
|
||||
};
|
||||
|
||||
//If the statusText is empty, we use the status code as text
|
||||
if (!statusText) {
|
||||
statusText = httpStatusToText[statusCode];
|
||||
}
|
||||
|
||||
//Create error text
|
||||
const title = statusText + ' (Status ' + statusCode + ')';
|
||||
|
||||
@@ -87,8 +140,10 @@ class ErrorHandlerHelper {
|
||||
}
|
||||
|
||||
handleError(event) {
|
||||
const fetchResponse = event.detail.fetchResponse;
|
||||
const response = fetchResponse.response;
|
||||
//Prevent default error handling
|
||||
event.preventDefault();
|
||||
|
||||
const response = event.detail.response;
|
||||
|
||||
//Ignore aborted requests.
|
||||
if (response.statusText === 'abort' || response.status == 0) {
|
||||
@@ -100,11 +155,17 @@ class ErrorHandlerHelper {
|
||||
return;
|
||||
}
|
||||
|
||||
if(fetchResponse.failed) {
|
||||
//Skip 404 errors, on admin pages (as this causes a popup on deletion in firefox)
|
||||
if (response.status == 404 && event.target.id === 'admin-content-frame') {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if(!response.ok) {
|
||||
response.text().then(responseHTML => {
|
||||
this._showAlert(response.statusText, response.status, fetchResponse.location.toString(), responseHTML);
|
||||
this._showAlert(response.statusText, response.status, response.url, responseHTML);
|
||||
}).catch(err => {
|
||||
this._showAlert(response.statusText, response.status, fetchResponse.location.toString(), '<pre>' + err + '</pre>');
|
||||
this._showAlert(response.statusText, response.status, response.url, '<pre>' + err + '</pre>');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,7 +47,8 @@
|
||||
method: config.method,
|
||||
data: {
|
||||
_dt: config.name,
|
||||
_init: true
|
||||
_init: true,
|
||||
order: config.initial_order ?? undefined,
|
||||
}
|
||||
}).done(function(data) {
|
||||
var baseState;
|
||||
@@ -72,6 +73,17 @@
|
||||
}
|
||||
} else {
|
||||
request._dt = config.name;
|
||||
|
||||
//Try to resolve the original column index when the column was reordered (using the ColReorder plugin)
|
||||
//Only do this when _ColReorder_iOrigCol is available
|
||||
if (settings.aoColumns && settings.aoColumns.length && settings.aoColumns[0]._ColReorder_iOrigCol !== undefined) {
|
||||
if (request.order && request.order.length) {
|
||||
request.order.forEach(function (order) {
|
||||
order.column = settings.aoColumns[order.column]._ColReorder_iOrigCol;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$.ajax(typeof config.url === 'function' ? config.url(dt) : config.url, {
|
||||
method: config.method,
|
||||
data: request
|
||||
|
||||
@@ -59,76 +59,239 @@ class RegisterEventHelper {
|
||||
}
|
||||
|
||||
registerTooltips() {
|
||||
this.registerLoadHandler(() => {
|
||||
const handler = () => {
|
||||
$(".tooltip").remove();
|
||||
//Exclude dropdown buttons from tooltips, otherwise we run into endless errors from bootstrap (bootstrap.esm.js:614 Bootstrap doesn't allow more than one instance per element. Bound instance: bs.dropdown.)
|
||||
$('a[title], button[title]:not([data-bs-toggle="dropdown"]), p[title], span[title], h6[title], h3[title], i.fas[title]')
|
||||
$('a[title], label[title], button[title]:not([data-bs-toggle="dropdown"]), p[title], span[title], h6[title], h3[title], i[title], small[title]')
|
||||
//@ts-ignore
|
||||
.tooltip("hide").tooltip({container: "body", placement: "auto", boundary: 'window'});
|
||||
});
|
||||
};
|
||||
|
||||
this.registerLoadHandler(handler);
|
||||
document.addEventListener('dt:loaded', handler);
|
||||
}
|
||||
|
||||
registerSpecialCharInput() {
|
||||
this.registerLoadHandler(() => {
|
||||
//@ts-ignore
|
||||
$("input[type=text], input[type=search]").unbind("keydown").keydown(function (event) {
|
||||
let greek = event.altKey;
|
||||
let use_special_char = event.altKey;
|
||||
|
||||
let greek_char = "";
|
||||
if (greek){
|
||||
if (use_special_char){
|
||||
//Use the key property to determine the greek letter (as it is independent of the keyboard layout)
|
||||
switch(event.key) {
|
||||
case "w": //Omega
|
||||
greek_char = '\u2126';
|
||||
break;
|
||||
case "u":
|
||||
case "m": //Micro
|
||||
greek_char = "\u00B5";
|
||||
break;
|
||||
case "p": //Phi
|
||||
greek_char = "\u03C6";
|
||||
break;
|
||||
case "a": //Alpha
|
||||
//Greek letters
|
||||
case "a": //Alpha (lowercase)
|
||||
greek_char = "\u03B1";
|
||||
break;
|
||||
case "b": //Beta
|
||||
case "A": //Alpha (uppercase)
|
||||
greek_char = "\u0391";
|
||||
break;
|
||||
case "b": //Beta (lowercase)
|
||||
greek_char = "\u03B2";
|
||||
break;
|
||||
case "c": //Gamma
|
||||
case "B": //Beta (uppercase)
|
||||
greek_char = "\u0392";
|
||||
break;
|
||||
case "g": //Gamma (lowercase)
|
||||
greek_char = "\u03B3";
|
||||
break;
|
||||
case "d": //Delta
|
||||
case "G": //Gamma (uppercase)
|
||||
greek_char = "\u0393";
|
||||
break;
|
||||
case "d": //Delta (lowercase)
|
||||
greek_char = "\u03B4";
|
||||
break;
|
||||
case "l": //Pound
|
||||
greek_char = "\u00A3";
|
||||
case "D": //Delta (uppercase)
|
||||
greek_char = "\u0394";
|
||||
break;
|
||||
case "y": //Yen
|
||||
greek_char = "\u00A5";
|
||||
case "e": //Epsilon (lowercase)
|
||||
greek_char = "\u03B5";
|
||||
break;
|
||||
case "o": //Yen
|
||||
greek_char = "\u00A4";
|
||||
case "E": //Epsilon (uppercase)
|
||||
greek_char = "\u0395";
|
||||
break;
|
||||
case "1": //Sum symbol
|
||||
greek_char = "\u2211";
|
||||
case "z": //Zeta (lowercase)
|
||||
greek_char = "\u03B6";
|
||||
break;
|
||||
case "2": //Integral
|
||||
greek_char = "\u222B";
|
||||
case "Z": //Zeta (uppercase)
|
||||
greek_char = "\u0396";
|
||||
break;
|
||||
case "3": //Less-than or equal
|
||||
greek_char = "\u2264";
|
||||
case "h": //Eta (lowercase)
|
||||
greek_char = "\u03B7";
|
||||
break;
|
||||
case "4": //Greater than or equal
|
||||
greek_char = "\u2265";
|
||||
case "H": //Eta (uppercase)
|
||||
greek_char = "\u0397";
|
||||
break;
|
||||
case "5": //PI
|
||||
greek_char = "\u03c0";
|
||||
case "q": //Theta (lowercase)
|
||||
greek_char = "\u03B8";
|
||||
break;
|
||||
case "q": //Copyright
|
||||
greek_char = "\u00A9";
|
||||
case "Q": //Theta (uppercase)
|
||||
greek_char = "\u0398";
|
||||
break;
|
||||
case "e": //Euro
|
||||
greek_char = "\u20AC";
|
||||
case "i": //Iota (lowercase)
|
||||
greek_char = "\u03B9";
|
||||
break;
|
||||
case "I": //Iota (uppercase)
|
||||
greek_char = "\u0399";
|
||||
break;
|
||||
case "k": //Kappa (lowercase)
|
||||
greek_char = "\u03BA";
|
||||
break;
|
||||
case "K": //Kappa (uppercase)
|
||||
greek_char = "\u039A";
|
||||
break;
|
||||
case "l": //Lambda (lowercase)
|
||||
greek_char = "\u03BB";
|
||||
break;
|
||||
case "L": //Lambda (uppercase)
|
||||
greek_char = "\u039B";
|
||||
break;
|
||||
case "m": //Mu (lowercase)
|
||||
greek_char = "\u03BC";
|
||||
break;
|
||||
case "M": //Mu (uppercase)
|
||||
greek_char = "\u039C";
|
||||
break;
|
||||
case "n": //Nu (lowercase)
|
||||
greek_char = "\u03BD";
|
||||
break;
|
||||
case "N": //Nu (uppercase)
|
||||
greek_char = "\u039D";
|
||||
break;
|
||||
case "x": //Xi (lowercase)
|
||||
greek_char = "\u03BE";
|
||||
break;
|
||||
case "X": //Xi (uppercase)
|
||||
greek_char = "\u039E";
|
||||
break;
|
||||
case "o": //Omicron (lowercase)
|
||||
greek_char = "\u03BF";
|
||||
break;
|
||||
case "O": //Omicron (uppercase)
|
||||
greek_char = "\u039F";
|
||||
break;
|
||||
case "p": //Pi (lowercase)
|
||||
greek_char = "\u03C0";
|
||||
break;
|
||||
case "P": //Pi (uppercase)
|
||||
greek_char = "\u03A0";
|
||||
break;
|
||||
case "r": //Rho (lowercase)
|
||||
greek_char = "\u03C1";
|
||||
break;
|
||||
case "R": //Rho (uppercase)
|
||||
greek_char = "\u03A1";
|
||||
break;
|
||||
case "s": //Sigma (lowercase)
|
||||
greek_char = "\u03C3";
|
||||
break;
|
||||
case "S": //Sigma (uppercase)
|
||||
greek_char = "\u03A3";
|
||||
break;
|
||||
case "t": //Tau (lowercase)
|
||||
greek_char = "\u03C4";
|
||||
break;
|
||||
case "T": //Tau (uppercase)
|
||||
greek_char = "\u03A4";
|
||||
break;
|
||||
case "u": //Upsilon (lowercase)
|
||||
greek_char = "\u03C5";
|
||||
break;
|
||||
case "U": //Upsilon (uppercase)
|
||||
greek_char = "\u03A5";
|
||||
break;
|
||||
case "f": //Phi (lowercase)
|
||||
greek_char = "\u03C6";
|
||||
break;
|
||||
case "F": //Phi (uppercase)
|
||||
greek_char = "\u03A6";
|
||||
break;
|
||||
case "c": //Chi (lowercase)
|
||||
greek_char = "\u03C7";
|
||||
break;
|
||||
case "C": //Chi (uppercase)
|
||||
greek_char = "\u03A7";
|
||||
break;
|
||||
case "y": //Psi (lowercase)
|
||||
greek_char = "\u03C8";
|
||||
break;
|
||||
case "Y": //Psi (uppercase)
|
||||
greek_char = "\u03A8";
|
||||
break;
|
||||
case "w": //Omega (lowercase)
|
||||
greek_char = "\u03C9";
|
||||
break;
|
||||
case "W": //Omega (uppercase)
|
||||
greek_char = "\u03A9";
|
||||
break;
|
||||
}
|
||||
|
||||
//Use keycodes for special characters as the shift char on the number keys are layout dependent
|
||||
switch (event.keyCode) {
|
||||
case 49: //1 key
|
||||
//Product symbol on shift, sum on no shift
|
||||
greek_char = event.shiftKey ? "\u220F" : "\u2211";
|
||||
break;
|
||||
case 50: //2 key
|
||||
//Integral on no shift, partial derivative on shift
|
||||
greek_char = event.shiftKey ? "\u2202" : "\u222B";
|
||||
break;
|
||||
case 51: //3 key
|
||||
//Less than or equal on no shift, greater than or equal on shift
|
||||
greek_char = event.shiftKey ? "\u2265" : "\u2264";
|
||||
break;
|
||||
case 52: //4 key
|
||||
//Empty set on shift, infinity on no shift
|
||||
greek_char = event.shiftKey ? "\u2205" : "\u221E";
|
||||
break;
|
||||
case 53: //5 key
|
||||
//Not equal on shift, approx equal on no shift
|
||||
greek_char = event.shiftKey ? "\u2260" : "\u2248";
|
||||
break;
|
||||
case 54: //6 key
|
||||
//Element of on no shift, not element of on shift
|
||||
greek_char = event.shiftKey ? "\u2209" : "\u2208";
|
||||
break;
|
||||
case 55: //7 key
|
||||
//And on shift, or on no shift
|
||||
greek_char = event.shiftKey ? "\u2227" : "\u2228";
|
||||
break;
|
||||
case 56: //8 key
|
||||
//Proportional to on shift, angle on no shift
|
||||
greek_char = event.shiftKey ? "\u221D" : "\u2220";
|
||||
break;
|
||||
case 57: //9 key
|
||||
//Cube root on shift, square root on no shift
|
||||
greek_char = event.shiftKey ? "\u221B" : "\u221A";
|
||||
break;
|
||||
case 48: //0 key
|
||||
//Minus-Plus on shift, plus-minus on no shift
|
||||
greek_char = event.shiftKey ? "\u2213" : "\u00B1";
|
||||
break;
|
||||
|
||||
//Special characters
|
||||
case 219: //hyphen (or ß on german layout)
|
||||
//Copyright on no shift, TM on shift
|
||||
greek_char = event.shiftKey ? "\u2122" : "\u00A9";
|
||||
break;
|
||||
case 191: //forward slash (or # on german layout)
|
||||
//Generic currency on no shift, paragraph on shift
|
||||
greek_char = event.shiftKey ? "\u00B6" : "\u00A4";
|
||||
break;
|
||||
|
||||
//Currency symbols
|
||||
case 192: //: or (ö on german layout)
|
||||
//Euro on no shift, pound on shift
|
||||
greek_char = event.shiftKey ? "\u00A3" : "\u20AC";
|
||||
break;
|
||||
case 221: //; or (ä on german layout)
|
||||
//Yen on no shift, dollar on shift
|
||||
greek_char = event.shiftKey ? "\u0024" : "\u00A5";
|
||||
break;
|
||||
|
||||
|
||||
}
|
||||
|
||||
if(greek_char=="") return;
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
import {Tab} from "bootstrap";
|
||||
import {Tab, Dropdown} from "bootstrap";
|
||||
import tab from "bootstrap/js/src/tab";
|
||||
|
||||
/**
|
||||
@@ -63,6 +63,16 @@ class TabRememberHelper {
|
||||
*/
|
||||
onInvalid(event) {
|
||||
this.revealElementOnTab(event.target);
|
||||
this.revealElementInDropdown(event.target);
|
||||
}
|
||||
|
||||
revealElementInDropdown(element) {
|
||||
let dropdown = element.closest('.dropdown-menu');
|
||||
|
||||
if(dropdown) {
|
||||
let bs_dropdown = Dropdown.getOrCreateInstance(dropdown);
|
||||
bs_dropdown.show();
|
||||
}
|
||||
}
|
||||
|
||||
revealElementOnTab(element) {
|
||||
|
||||
@@ -21,8 +21,13 @@
|
||||
|
||||
class WebauthnTFA {
|
||||
|
||||
// Decodes a Base64Url string
|
||||
_base64UrlDecode = (input) => {
|
||||
_b64UrlSafeEncode = (str) => {
|
||||
const b64 = btoa(str);
|
||||
return b64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
|
||||
}
|
||||
|
||||
// Decodes a Base64Url string
|
||||
_b64UrlSafeDecode = (input) => {
|
||||
input = input
|
||||
.replace(/-/g, '+')
|
||||
.replace(/_/g, '/');
|
||||
@@ -39,13 +44,16 @@ class WebauthnTFA {
|
||||
};
|
||||
|
||||
// Converts an array of bytes into a Base64Url string
|
||||
_arrayToBase64String = (a) => btoa(String.fromCharCode(...a));
|
||||
_arrayToBase64String = (a) => {
|
||||
const str = String.fromCharCode(...a);
|
||||
return this._b64UrlSafeEncode(str);
|
||||
}
|
||||
|
||||
// Prepares the public key options object returned by the Webauthn Framework
|
||||
_preparePublicKeyOptions = publicKey => {
|
||||
//Convert challenge from Base64Url string to Uint8Array
|
||||
publicKey.challenge = Uint8Array.from(
|
||||
this._base64UrlDecode(publicKey.challenge),
|
||||
this._b64UrlSafeDecode(publicKey.challenge),
|
||||
c => c.charCodeAt(0)
|
||||
);
|
||||
|
||||
@@ -67,7 +75,7 @@ class WebauthnTFA {
|
||||
return {
|
||||
...data,
|
||||
id: Uint8Array.from(
|
||||
this._base64UrlDecode(data.id),
|
||||
this._b64UrlSafeDecode(data.id),
|
||||
c => c.charCodeAt(0)
|
||||
),
|
||||
};
|
||||
@@ -81,7 +89,7 @@ class WebauthnTFA {
|
||||
return {
|
||||
...data,
|
||||
id: Uint8Array.from(
|
||||
this._base64UrlDecode(data.id),
|
||||
this._b64UrlSafeDecode(data.id),
|
||||
c => c.charCodeAt(0)
|
||||
),
|
||||
};
|
||||
|
||||
16
assets/translator.js
Normal file
16
assets/translator.js
Normal file
@@ -0,0 +1,16 @@
|
||||
import { localeFallbacks } from '../var/translations/configuration';
|
||||
import { trans, getLocale, setLocale, setLocaleFallbacks } from '@symfony/ux-translator';
|
||||
/*
|
||||
* This file is part of the Symfony UX Translator package.
|
||||
*
|
||||
* If folder "../var/translations" does not exist, or some translations are missing,
|
||||
* you must warmup your Symfony cache to refresh JavaScript translations.
|
||||
*
|
||||
* If you use TypeScript, you can rename this file to "translator.ts" to take advantage of types checking.
|
||||
*/
|
||||
|
||||
setLocaleFallbacks(localeFallbacks);
|
||||
|
||||
export { trans };
|
||||
|
||||
export * from '../var/translations';
|
||||
114
composer.json
114
composer.json
@@ -2,71 +2,79 @@
|
||||
"type": "project",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"require": {
|
||||
"php": "^7.4 || ^8.0",
|
||||
"php": "^8.1",
|
||||
"ext-ctype": "*",
|
||||
"ext-dom": "*",
|
||||
"ext-gd": "*",
|
||||
"ext-iconv": "*",
|
||||
"ext-intl": "*",
|
||||
"ext-json": "*",
|
||||
"ext-mbstring": "*",
|
||||
"beberlei/doctrineextensions": "^1.2",
|
||||
"brick/math": "^0.8.15",
|
||||
"composer/package-versions-deprecated": "1.11.99.4",
|
||||
"doctrine/annotations": "^1.6",
|
||||
"brick/math": "^0.11.0",
|
||||
"composer/package-versions-deprecated": "^1.11.99.5",
|
||||
"doctrine/annotations": "1.14.3",
|
||||
"doctrine/data-fixtures": "^1.6.6",
|
||||
"doctrine/dbal": "^3.4.6",
|
||||
"doctrine/doctrine-bundle": "^2.0",
|
||||
"doctrine/doctrine-migrations-bundle": "^3.0",
|
||||
"doctrine/orm": "^2.9",
|
||||
"dompdf/dompdf": "^2.0.0",
|
||||
"doctrine/orm": "^2.16",
|
||||
"dompdf/dompdf": "dev-master#87bea32efe0b0db309e1d31537201f64d5508280 as v2.0.3",
|
||||
"erusev/parsedown": "^1.7",
|
||||
"florianv/swap": "^4.0",
|
||||
"florianv/swap-bundle": "dev-master",
|
||||
"gregwar/captcha-bundle": "^2.1.0",
|
||||
"jbtronics/2fa-webauthn": "^1.0.0",
|
||||
"jbtronics/2fa-webauthn": "^v2.0.0",
|
||||
"jbtronics/dompdf-font-loader-bundle": "^1.0.0",
|
||||
"jfcherng/php-diff": "^6.14",
|
||||
"knpuniversity/oauth2-client-bundle": "^2.15",
|
||||
"league/csv": "^9.8.0",
|
||||
"league/html-to-markdown": "^5.0.1",
|
||||
"liip/imagine-bundle": "^2.2",
|
||||
"nbgrp/onelogin-saml-bundle": "^1.3",
|
||||
"nelexa/zip": "^4.0",
|
||||
"nelmio/security-bundle": "^3.0",
|
||||
"nyholm/psr7": "^1.1",
|
||||
"ocramius/proxy-manager": "2.2.*",
|
||||
"omines/datatables-bundle": "^0.5.0",
|
||||
"php-translation/symfony-bundle": "^0.12.0",
|
||||
"omines/datatables-bundle": "^0.7.2",
|
||||
"part-db/label-fonts": "^1.0",
|
||||
"php-translation/symfony-bundle": "^0.14.0",
|
||||
"phpdocumentor/reflection-docblock": "^5.2",
|
||||
"s9e/text-formatter": "^2.1",
|
||||
"scheb/2fa-backup-code": "^5.13",
|
||||
"scheb/2fa-bundle": "^5.13",
|
||||
"scheb/2fa-google-authenticator": "^5.13",
|
||||
"scheb/2fa-trusted-device": "^5.13",
|
||||
"sensio/framework-extra-bundle": "^6.1.1",
|
||||
"scheb/2fa-backup-code": "^6.8.0",
|
||||
"scheb/2fa-bundle": "^6.8.0",
|
||||
"scheb/2fa-google-authenticator": "^6.8.0",
|
||||
"scheb/2fa-trusted-device": "^6.8.0",
|
||||
"shivas/versioning-bundle": "^4.0",
|
||||
"spatie/db-dumper": "^2.21",
|
||||
"spatie/db-dumper": "^3.3.1",
|
||||
"symfony/apache-pack": "^1.0",
|
||||
"symfony/asset": "5.4.*",
|
||||
"symfony/console": "5.4.*",
|
||||
"symfony/dotenv": "5.4.*",
|
||||
"symfony/expression-language": "5.4.*",
|
||||
"symfony/flex": "^1.1",
|
||||
"symfony/form": "5.4.*",
|
||||
"symfony/framework-bundle": "5.4.*",
|
||||
"symfony/http-client": "5.4.*",
|
||||
"symfony/http-kernel": "5.4.*",
|
||||
"symfony/mailer": "5.4.*",
|
||||
"symfony/asset": "6.3.*",
|
||||
"symfony/console": "6.3.*",
|
||||
"symfony/dotenv": "6.3.*",
|
||||
"symfony/expression-language": "6.3.*",
|
||||
"symfony/flex": "^v2.3.1",
|
||||
"symfony/form": "6.3.*",
|
||||
"symfony/framework-bundle": "6.3.*",
|
||||
"symfony/http-client": "6.3.*",
|
||||
"symfony/http-kernel": "6.3.*",
|
||||
"symfony/mailer": "6.3.*",
|
||||
"symfony/monolog-bundle": "^3.1",
|
||||
"symfony/process": "5.4.*",
|
||||
"symfony/property-access": "5.4.*",
|
||||
"symfony/property-info": "5.4.*",
|
||||
"symfony/proxy-manager-bridge": "5.4.*",
|
||||
"symfony/rate-limiter": "5.4.*",
|
||||
"symfony/runtime": "5.4.*",
|
||||
"symfony/security-bundle": "5.4.*",
|
||||
"symfony/serializer": "5.4.*",
|
||||
"symfony/translation": "5.4.*",
|
||||
"symfony/twig-bundle": "5.4.*",
|
||||
"symfony/process": "6.3.*",
|
||||
"symfony/property-access": "6.3.*",
|
||||
"symfony/property-info": "6.3.*",
|
||||
"symfony/proxy-manager-bridge": "6.3.*",
|
||||
"symfony/rate-limiter": "6.3.*",
|
||||
"symfony/runtime": "6.3.*",
|
||||
"symfony/security-bundle": "6.3.*",
|
||||
"symfony/serializer": "6.3.*",
|
||||
"symfony/translation": "6.3.*",
|
||||
"symfony/twig-bundle": "6.3.*",
|
||||
"symfony/ux-translator": "^2.10",
|
||||
"symfony/ux-turbo": "^2.0",
|
||||
"symfony/validator": "5.4.*",
|
||||
"symfony/web-link": "5.4.*",
|
||||
"symfony/webpack-encore-bundle": "^1.1",
|
||||
"symfony/yaml": "5.4.*",
|
||||
"symfony/validator": "6.3.*",
|
||||
"symfony/web-link": "6.3.*",
|
||||
"symfony/webpack-encore-bundle": "^v2.0.1",
|
||||
"symfony/yaml": "6.3.*",
|
||||
"tecnickcom/tc-lib-barcode": "^1.15",
|
||||
"twig/cssinliner-extra": "^3.0",
|
||||
"twig/extra-bundle": "^3.0",
|
||||
@@ -74,7 +82,7 @@
|
||||
"twig/inky-extra": "^3.0",
|
||||
"twig/intl-extra": "^3.0",
|
||||
"twig/markdown-extra": "^3.0",
|
||||
"web-auth/webauthn-symfony-bundle": "^3.3",
|
||||
"web-auth/webauthn-symfony-bundle": "^4.0.0",
|
||||
"webmozart/assert": "^1.4"
|
||||
},
|
||||
"require-dev": {
|
||||
@@ -84,17 +92,19 @@
|
||||
"phpstan/extension-installer": "^1.0",
|
||||
"phpstan/phpstan": "^1.4.7",
|
||||
"phpstan/phpstan-doctrine": "^1.2.11",
|
||||
"phpstan/phpstan-strict-rules": "^1.5",
|
||||
"phpstan/phpstan-symfony": "^1.1.7",
|
||||
"psalm/plugin-symfony": "^v5.0.1",
|
||||
"rector/rector": "^0.18.0",
|
||||
"roave/security-advisories": "dev-latest",
|
||||
"symfony/browser-kit": "^5.2",
|
||||
"symfony/css-selector": "^5.2",
|
||||
"symfony/debug-bundle": "^5.2",
|
||||
"symfony/browser-kit": "6.3.*",
|
||||
"symfony/css-selector": "6.3.*",
|
||||
"symfony/debug-bundle": "6.3.*",
|
||||
"symfony/maker-bundle": "^1.13",
|
||||
"symfony/phpunit-bridge": "5.4.*",
|
||||
"symfony/stopwatch": "^5.2",
|
||||
"symfony/web-profiler-bundle": "^5.2",
|
||||
"symplify/easy-coding-standard": "^11.0",
|
||||
"symfony/phpunit-bridge": "6.3.*",
|
||||
"symfony/stopwatch": "6.3.*",
|
||||
"symfony/web-profiler-bundle": "6.3.*",
|
||||
"symplify/easy-coding-standard": "^12.0",
|
||||
"vimeo/psalm": "^5.6.0"
|
||||
},
|
||||
"suggest": {
|
||||
@@ -106,7 +116,7 @@
|
||||
"*": "dist"
|
||||
},
|
||||
"platform": {
|
||||
"php": "7.4.0"
|
||||
"php": "8.1.0"
|
||||
},
|
||||
"sort-packages": true,
|
||||
"allow-plugins": {
|
||||
@@ -138,7 +148,7 @@
|
||||
"post-update-cmd": [
|
||||
"@auto-scripts"
|
||||
],
|
||||
"phpstan": "vendor/bin/phpstan analyse src --level 2 --memory-limit 1G"
|
||||
"phpstan": "vendor/bin/phpstan analyse src --level 5 --memory-limit 1G"
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/symfony": "*"
|
||||
@@ -146,9 +156,7 @@
|
||||
"extra": {
|
||||
"symfony": {
|
||||
"allow-contrib": false,
|
||||
"require": "5.4.*"
|
||||
"require": "6.3.*"
|
||||
}
|
||||
},
|
||||
"repositories": [
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
7561
composer.lock
generated
7561
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -1,23 +0,0 @@
|
||||
<?php
|
||||
|
||||
use Symfony\Component\Dotenv\Dotenv;
|
||||
|
||||
require dirname(__DIR__).'/vendor/autoload.php';
|
||||
|
||||
if (!class_exists(Dotenv::class)) {
|
||||
throw new LogicException('Please run "composer require symfony/dotenv" to load the ".env" files configuring the application.');
|
||||
}
|
||||
|
||||
// Load cached env vars if the .env.local.php file exists
|
||||
// Run "composer dump-env prod" to create it (requires symfony/flex >=1.2)
|
||||
if (is_array($env = @include dirname(__DIR__).'/.env.local.php') && (!isset($env['APP_ENV']) || ($_SERVER['APP_ENV'] ?? $_ENV['APP_ENV'] ?? $env['APP_ENV']) === $env['APP_ENV'])) {
|
||||
(new Dotenv(false))->populate($env);
|
||||
} else {
|
||||
// load all the .env files
|
||||
(new Dotenv(false))->loadEnv(dirname(__DIR__).'/.env');
|
||||
}
|
||||
|
||||
$_SERVER += $_ENV;
|
||||
$_SERVER['APP_ENV'] = $_ENV['APP_ENV'] = ($_SERVER['APP_ENV'] ?? $_ENV['APP_ENV'] ?? null) ?: 'dev';
|
||||
$_SERVER['APP_DEBUG'] = $_SERVER['APP_DEBUG'] ?? $_ENV['APP_DEBUG'] ?? 'prod' !== $_SERVER['APP_ENV'];
|
||||
$_SERVER['APP_DEBUG'] = $_ENV['APP_DEBUG'] = (int) $_SERVER['APP_DEBUG'] || filter_var($_SERVER['APP_DEBUG'], FILTER_VALIDATE_BOOLEAN) ? '1' : '0';
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
return [
|
||||
Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true],
|
||||
Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle::class => ['all' => true],
|
||||
Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true],
|
||||
Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true],
|
||||
Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true],
|
||||
@@ -27,4 +26,9 @@ return [
|
||||
Scheb\TwoFactorBundle\SchebTwoFactorBundle::class => ['all' => true],
|
||||
SpomkyLabs\CborBundle\SpomkyLabsCborBundle::class => ['all' => true],
|
||||
Webauthn\Bundle\WebauthnBundle::class => ['all' => true],
|
||||
Nbgrp\OneloginSamlBundle\NbgrpOneloginSamlBundle::class => ['all' => true],
|
||||
Symfony\UX\StimulusBundle\StimulusBundle::class => ['all' => true],
|
||||
Symfony\UX\Translator\UxTranslatorBundle::class => ['all' => true],
|
||||
Jbtronics\DompdfFontLoaderBundle\DompdfFontLoaderBundle::class => ['all' => true],
|
||||
KnpU\OAuth2ClientBundle\KnpUOAuth2ClientBundle::class => ['all' => true],
|
||||
];
|
||||
|
||||
@@ -20,3 +20,6 @@ framework:
|
||||
tree.cache:
|
||||
adapter: cache.app
|
||||
tags: true
|
||||
|
||||
info_provider.cache:
|
||||
adapter: cache.app
|
||||
|
||||
@@ -9,7 +9,7 @@ datatables:
|
||||
# Set options, as documented at https://datatables.net/reference/option/
|
||||
options:
|
||||
lengthMenu : [[10, 25, 50, 100, -1], [10, 25, 50, 100, "All"]]
|
||||
pageLength: 50
|
||||
pageLength: '%partdb.table.default_page_size%' # Set to -1 to disable pagination (i.e. show all rows) by default
|
||||
#dom: "<'row' <'col-sm-12' tr>><'row' <'col-sm-6'l><'col-sm-6 text-right'pif>>"
|
||||
dom: " <'row'<'col mb-2 input-group' B l> <'col mb-2' <'pull-end' p>>>
|
||||
<'card'
|
||||
|
||||
@@ -12,6 +12,8 @@ doctrine:
|
||||
class: App\Doctrine\Types\UTCDateTimeType
|
||||
big_decimal:
|
||||
class: App\Doctrine\Types\BigDecimalType
|
||||
tinyint:
|
||||
class: App\Doctrine\Types\TinyIntType
|
||||
|
||||
schema_filter: ~^(?!internal)~
|
||||
# Only enable this when needed
|
||||
@@ -19,12 +21,15 @@ doctrine:
|
||||
|
||||
orm:
|
||||
auto_generate_proxy_classes: true
|
||||
enable_lazy_ghost_objects: true
|
||||
report_fields_where_declared: true
|
||||
validate_xml_mapping: true
|
||||
naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware
|
||||
auto_mapping: true
|
||||
mappings:
|
||||
App:
|
||||
is_bundle: false
|
||||
type: annotation
|
||||
type: attribute
|
||||
dir: '%kernel.project_dir%/src/Entity'
|
||||
prefix: 'App\Entity'
|
||||
alias: App
|
||||
@@ -33,6 +38,8 @@ doctrine:
|
||||
string_functions:
|
||||
regexp: DoctrineExtensions\Query\Mysql\Regexp
|
||||
ifnull: DoctrineExtensions\Query\Mysql\IfNull
|
||||
field: DoctrineExtensions\Query\Mysql\Field
|
||||
field2: App\Doctrine\Functions\Field2
|
||||
|
||||
when@test:
|
||||
doctrine:
|
||||
|
||||
11
config/packages/dompdf_font_loader.yaml
Normal file
11
config/packages/dompdf_font_loader.yaml
Normal file
@@ -0,0 +1,11 @@
|
||||
dompdf_font_loader:
|
||||
auto_install: true
|
||||
|
||||
fonts:
|
||||
unifont:
|
||||
normal: "%kernel.project_dir%/vendor/part-db/label-fonts/fonts/unifont.ttf"
|
||||
|
||||
# Enable autodiscovery of fonts, so that font installation is much easier
|
||||
autodiscovery:
|
||||
paths:
|
||||
- "%kernel.project_dir%/assets/fonts/dompdf"
|
||||
@@ -2,8 +2,12 @@
|
||||
framework:
|
||||
secret: '%env(APP_SECRET)%'
|
||||
csrf_protection: true
|
||||
handle_all_throwables: true
|
||||
|
||||
# Must be set to true, to enable the change of HTTP methhod via _method parameter, otherwise our delete routines does not work anymore
|
||||
# We set this header by ourself, so we can disable it here
|
||||
disallow_search_engine_index: false
|
||||
|
||||
# Must be set to true, to enable the change of HTTP method via _method parameter, otherwise our delete routines does not work anymore
|
||||
# TODO: Rework delete routines to work without _method parameter as it is not recommended anymore (see https://github.com/symfony/symfony/issues/45278)
|
||||
http_method_override: true
|
||||
|
||||
@@ -29,9 +33,6 @@ framework:
|
||||
php_errors:
|
||||
log: true
|
||||
|
||||
form:
|
||||
legacy_error_messages: false # Enable to use the new Form component validation messages
|
||||
|
||||
when@test:
|
||||
framework:
|
||||
test: true
|
||||
|
||||
5
config/packages/http_client.yaml
Normal file
5
config/packages/http_client.yaml
Normal file
@@ -0,0 +1,5 @@
|
||||
framework:
|
||||
http_client:
|
||||
default_options:
|
||||
headers:
|
||||
'User-Agent': 'Part-DB'
|
||||
10
config/packages/http_discovery.yaml
Normal file
10
config/packages/http_discovery.yaml
Normal file
@@ -0,0 +1,10 @@
|
||||
services:
|
||||
Psr\Http\Message\RequestFactoryInterface: '@http_discovery.psr17_factory'
|
||||
Psr\Http\Message\ResponseFactoryInterface: '@http_discovery.psr17_factory'
|
||||
Psr\Http\Message\ServerRequestFactoryInterface: '@http_discovery.psr17_factory'
|
||||
Psr\Http\Message\StreamFactoryInterface: '@http_discovery.psr17_factory'
|
||||
Psr\Http\Message\UploadedFileFactoryInterface: '@http_discovery.psr17_factory'
|
||||
Psr\Http\Message\UriFactoryInterface: '@http_discovery.psr17_factory'
|
||||
|
||||
http_discovery.psr17_factory:
|
||||
class: Http\Discovery\Psr17Factory
|
||||
38
config/packages/knpu_oauth2_client.yaml
Normal file
38
config/packages/knpu_oauth2_client.yaml
Normal file
@@ -0,0 +1,38 @@
|
||||
knpu_oauth2_client:
|
||||
clients:
|
||||
# configure your clients as described here: https://github.com/knpuniversity/oauth2-client-bundle#configuration
|
||||
|
||||
ip_digikey_oauth:
|
||||
type: generic
|
||||
provider_class: '\League\OAuth2\Client\Provider\GenericProvider'
|
||||
|
||||
client_id: '%env(PROVIDER_DIGIKEY_CLIENT_ID)%'
|
||||
client_secret: '%env(PROVIDER_DIGIKEY_SECRET)%'
|
||||
|
||||
redirect_route: 'oauth_client_check'
|
||||
redirect_params: {name: 'ip_digikey_oauth'}
|
||||
|
||||
provider_options:
|
||||
urlAuthorize: 'https://api.digikey.com/v1/oauth2/authorize'
|
||||
urlAccessToken: 'https://api.digikey.com/v1/oauth2/token'
|
||||
urlResourceOwnerDetails: ''
|
||||
|
||||
# Sandbox
|
||||
#urlAuthorize: 'https://sandbox-api.digikey.com/v1/oauth2/authorize'
|
||||
#urlAccessToken: 'https://sandbox-api.digikey.com/v1/oauth2/token'
|
||||
#urlResourceOwnerDetails: ''
|
||||
|
||||
ip_octopart_oauth:
|
||||
type: generic
|
||||
provider_class: '\League\OAuth2\Client\Provider\GenericProvider'
|
||||
|
||||
client_id: '%env(PROVIDER_OCTOPART_CLIENT_ID)%'
|
||||
client_secret: '%env(PROVIDER_OCTOPART_SECRET)%'
|
||||
|
||||
redirect_route: 'oauth_client_check'
|
||||
redirect_params: { name: 'ip_octopart_oauth' }
|
||||
|
||||
provider_options:
|
||||
urlAuthorize: 'https://identity.nexar.com/connect/authorize'
|
||||
urlAccessToken: 'https://identity.nexar.com/connect/token'
|
||||
urlResourceOwnerDetails: ''
|
||||
@@ -3,9 +3,15 @@ liip_imagine:
|
||||
# valid drivers options include "gd" or "gmagick" or "imagick"
|
||||
driver: "gd"
|
||||
|
||||
twig:
|
||||
mode: lazy
|
||||
|
||||
default_filter_set_settings:
|
||||
format: webp
|
||||
|
||||
filter_sets:
|
||||
thumbnail_sm:
|
||||
quality: 90
|
||||
quality: 65
|
||||
filters:
|
||||
thumbnail:
|
||||
size: [150, 150]
|
||||
@@ -20,7 +26,7 @@ liip_imagine:
|
||||
mode: inset
|
||||
|
||||
thumbnail_xs:
|
||||
quality: 90
|
||||
quality: 60
|
||||
filters:
|
||||
thumbnail:
|
||||
size: [50, 50]
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
framework:
|
||||
lock: '%env(LOCK_DSN)%'
|
||||
68
config/packages/nbgrp_onelogin_saml.yaml
Normal file
68
config/packages/nbgrp_onelogin_saml.yaml
Normal file
@@ -0,0 +1,68 @@
|
||||
# See https://github.com/SAML-Toolkits/php-saml for more information about the SAML settings
|
||||
|
||||
# Define a parameter here, so we can access it later in the default fallback
|
||||
parameters:
|
||||
saml.sp.privateKey: '%env(string:SAML_SP_PRIVATE_KEY)%'
|
||||
|
||||
nbgrp_onelogin_saml:
|
||||
onelogin_settings:
|
||||
default:
|
||||
# Basic settings
|
||||
idp:
|
||||
entityId: '%env(string:SAML_IDP_ENTITY_ID)%'
|
||||
singleSignOnService:
|
||||
url: '%env(string:SAML_IDP_SINGLE_SIGN_ON_SERVICE)%'
|
||||
binding: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect'
|
||||
singleLogoutService:
|
||||
url: '%env(string:SAML_IDP_SINGLE_LOGOUT_SERVICE)%'
|
||||
binding: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect'
|
||||
x509cert: '%env(string:SAML_IDP_X509_CERT)%'
|
||||
sp:
|
||||
entityId: '%env(string:SAML_SP_ENTITY_ID)%'
|
||||
assertionConsumerService:
|
||||
url: '%partdb.default_uri%saml/acs'
|
||||
binding: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST'
|
||||
singleLogoutService:
|
||||
url: '%partdb.default_uri%logout'
|
||||
binding: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect'
|
||||
x509cert: '%env(string:SAML_SP_X509_CERT)%'
|
||||
# Before the env variable was wrongly named "SAMLP_SP_PRIVATE_KEY".
|
||||
# For compatibility reasons we keep it and only fallback to the new name if the old one is not set. This may be removed in the future.
|
||||
privateKey: '%env(string:default:saml.sp.privateKey:string:SAMLP_SP_PRIVATE_KEY)%'
|
||||
|
||||
# Optional settings
|
||||
#baseurl: 'http://myapp.com'
|
||||
strict: true
|
||||
debug: false
|
||||
security:
|
||||
allowRepeatAttributeName: true
|
||||
# nameIdEncrypted: false
|
||||
authnRequestsSigned: true
|
||||
logoutRequestSigned: true
|
||||
logoutResponseSigned: true
|
||||
# wantMessagesSigned: false
|
||||
# wantAssertionsSigned: true
|
||||
# wantNameIdEncrypted: false
|
||||
# requestedAuthnContext: true
|
||||
# signMetadata: false
|
||||
# wantXMLValidation: true
|
||||
# relaxDestinationValidation: false
|
||||
# destinationStrictlyMatches: true
|
||||
# rejectUnsolicitedResponsesWithInResponseTo: false
|
||||
# signatureAlgorithm: 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256'
|
||||
# digestAlgorithm: 'http://www.w3.org/2001/04/xmlenc#sha256'
|
||||
#contactPerson:
|
||||
# technical:
|
||||
# givenName: 'Tech User'
|
||||
# emailAddress: 'techuser@example.com'
|
||||
# support:
|
||||
# givenName: 'Support User'
|
||||
# emailAddress: 'supportuser@example.com'
|
||||
# administrative:
|
||||
# givenName: 'Administrative User'
|
||||
# emailAddress: 'administrativeuser@example.com'
|
||||
#organization:
|
||||
# en:
|
||||
# name: 'Part-DB-name'
|
||||
# displayname: 'Displayname'
|
||||
# url: 'http://example.com'
|
||||
@@ -12,6 +12,13 @@ nelmio_security:
|
||||
external_redirects:
|
||||
abort: true
|
||||
log: true
|
||||
allow_list:
|
||||
# Whitelist the domain of the SAML IDP, so we can redirect to it during the SAML login process
|
||||
- '%env(string:key:host:url:SAML_IDP_SINGLE_SIGN_ON_SERVICE)%'
|
||||
|
||||
# Whitelist the info provider APIs (OAuth redirects)
|
||||
- 'digikey.com'
|
||||
- 'nexar.com'
|
||||
|
||||
# forces Microsoft's XSS-Protection with
|
||||
# its block mode
|
||||
|
||||
@@ -4,7 +4,7 @@ framework:
|
||||
|
||||
# Configure how to generate URLs in non-HTTP contexts, such as CLI commands.
|
||||
# See https://symfony.com/doc/current/routing.html#generating-urls-in-commands
|
||||
#default_uri: http://localhost
|
||||
default_uri: '%env(DEFAULT_URI)%'
|
||||
|
||||
when@prod:
|
||||
framework:
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# See the configuration reference at https://symfony.com/bundles/SchebTwoFactorBundle/5.x/configuration.html
|
||||
# See the configuration reference at https://symfony.com/bundles/SchebTwoFactorBundle/6.x/configuration.html
|
||||
scheb_two_factor:
|
||||
|
||||
google:
|
||||
enabled: true # If Google Authenticator should be enabled, default false
|
||||
server_name: '%partdb.title%' # Server name used in QR code
|
||||
issuer: 'Part-DB' # Issuer name used in QR code
|
||||
server_name: '$$DOMAIN$$' # This field is replaced by the domain name of the server in DecoratedGoogleAuthenticator
|
||||
issuer: '%partdb.title%' # Issuer name used in QR code
|
||||
digits: 6 # Number of digits in authentication code
|
||||
window: 1 # How many codes before/after the current one would be accepted as valid
|
||||
template: security/2fa_form.html.twig
|
||||
@@ -23,6 +23,6 @@ scheb_two_factor:
|
||||
security_tokens:
|
||||
- Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken
|
||||
# If you're using guard-based authentication, you have to use this one:
|
||||
# - Symfony\Component\Security\Guard\Token\PostAuthenticationGuardToken
|
||||
# - Symfony\Component\Security\Http\Authenticator\Token\PostAuthenticationToken
|
||||
# If you're using authenticator-based security (introduced in Symfony 5.1), you have to use this one:
|
||||
# - Symfony\Component\Security\Http\Authenticator\Token\PostAuthenticationToken
|
||||
- Symfony\Component\Security\Http\Authenticator\Token\PostAuthenticationToken
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
security:
|
||||
enable_authenticator_manager: true
|
||||
|
||||
# https://symfony.com/doc/current/security.html#registering-the-user-hashing-passwords
|
||||
password_hashers:
|
||||
Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto'
|
||||
|
||||
# https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
|
||||
providers:
|
||||
# used to reload user from session & other features (e.g. switch_user)
|
||||
app_user_provider:
|
||||
@@ -12,6 +10,7 @@ security:
|
||||
class: App\Entity\UserSystem\User
|
||||
property: name
|
||||
|
||||
|
||||
firewalls:
|
||||
dev:
|
||||
pattern: ^/(_(profiler|wdt)|css|images|js)/
|
||||
@@ -20,6 +19,10 @@ security:
|
||||
provider: app_user_provider
|
||||
lazy: true
|
||||
user_checker: App\Security\UserChecker
|
||||
entry_point: form_login
|
||||
|
||||
# Enable user impersonation
|
||||
switch_user: { role: CAN_SWITCH_USER }
|
||||
|
||||
two_factor:
|
||||
auth_form_path: 2fa_login
|
||||
@@ -29,6 +32,14 @@ security:
|
||||
login_throttling:
|
||||
max_attempts: 5 # per minute
|
||||
|
||||
saml:
|
||||
use_referer: true
|
||||
user_factory: saml_user_factory
|
||||
persist_user: true
|
||||
check_path: saml_acs
|
||||
login_path: saml_login
|
||||
failure_path: login
|
||||
|
||||
# https://symfony.com/doc/current/security/form_login_setup.html
|
||||
form_login:
|
||||
login_path: login
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
sensio_framework_extra:
|
||||
router:
|
||||
annotations: false
|
||||
@@ -1,4 +1,2 @@
|
||||
framework:
|
||||
test: true
|
||||
session:
|
||||
storage_id: session.storage.mock_file
|
||||
|
||||
@@ -19,6 +19,7 @@ twig:
|
||||
sidebar_tree_updater: '@App\Services\Trees\SidebarTreeUpdater'
|
||||
avatar_helper: '@App\Services\UserSystem\UserAvatarHelper'
|
||||
available_themes: '%partdb.available_themes%'
|
||||
saml_enabled: '%partdb.saml.enabled%'
|
||||
|
||||
when@test:
|
||||
twig:
|
||||
|
||||
4
config/packages/uid.yaml
Normal file
4
config/packages/uid.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
framework:
|
||||
uid:
|
||||
default_uuid_version: 7
|
||||
time_based_uuid_version: 7
|
||||
3
config/packages/ux_translator.yaml
Normal file
3
config/packages/ux_translator.yaml
Normal file
@@ -0,0 +1,3 @@
|
||||
ux_translator:
|
||||
# The directory where the JavaScript translations are dumped
|
||||
dump_directory: '%kernel.project_dir%/var/translations'
|
||||
@@ -4,7 +4,9 @@ when@dev:
|
||||
intercept_redirects: false
|
||||
|
||||
framework:
|
||||
profiler: { only_exceptions: false }
|
||||
profiler:
|
||||
only_exceptions: false
|
||||
collect_serializer_data: true
|
||||
|
||||
when@test:
|
||||
web_profiler:
|
||||
|
||||
@@ -11,15 +11,20 @@ parameters:
|
||||
partdb.banner: '%env(trim:string:BANNER)%' # The info text shown in the homepage, if empty config/banner.md is used
|
||||
partdb.default_currency: '%env(string:BASE_CURRENCY)%' # The currency that is used inside the DB (and is assumed when no currency is set). This can not be changed later, so be sure to set it the currency used in your country
|
||||
partdb.global_theme: '' # The theme to use globally (see public/build/themes/ for choices, use name without .css). Set to '' for default bootstrap theme
|
||||
partdb.locale_menu: ['en', 'de', 'fr', 'ru', 'ja'] # The languages that are shown in user drop down menu
|
||||
partdb.locale_menu: ['en', 'de', 'it', 'fr', 'ru', 'ja'] # The languages that are shown in user drop down menu
|
||||
partdb.enforce_change_comments_for: '%env(csv:ENFORCE_CHANGE_COMMENTS_FOR)%' # The actions for which a change comment is required (e.g. "part_edit", "part_create", etc.). If this is empty, change comments are not required at all.
|
||||
|
||||
partdb.default_uri: '%env(string:DEFAULT_URI)%' # The default URI to use for the Part-DB instance (e.g. https://part-db.example.com/). This is used for generating links in emails
|
||||
|
||||
######################################################################################################################
|
||||
# Users and Privacy
|
||||
######################################################################################################################
|
||||
partdb.gpdr_compliance: true # If this option is activated, IP addresses are anonymized to be GPDR compliant
|
||||
partdb.gdpr_compliance: true # If this option is activated, IP addresses are anonymized to be GDPR compliant
|
||||
partdb.users.use_gravatar: '%env(bool:USE_GRAVATAR)%' # Set to false, if no Gravatar images should be used for user profiles.
|
||||
partdb.users.email_pw_reset: '%env(bool:ALLOW_EMAIL_PW_RESET)%' # Config if users are able, to reset their password by email. By default this enabled, when a mail server is configured.
|
||||
|
||||
partdb.check_for_updates: '%env(bool:CHECK_FOR_UPDATES)' # Set to false, if Part-DB should not contact the GitHub API to check for updates
|
||||
|
||||
######################################################################################################################
|
||||
# Mail settings
|
||||
######################################################################################################################
|
||||
@@ -29,9 +34,10 @@ parameters:
|
||||
######################################################################################################################
|
||||
# Attachments and files
|
||||
######################################################################################################################
|
||||
partdb.attachments.allow_downloads: '%env(bool:ALLOW_ATTACHMENT_DOWNLOADS)%' # Allow users to download attachments to server. Warning: This can be dangerous, because via that feature attackers maybe can access ressources on your intranet!
|
||||
partdb.attachments.dir.media: 'public/media/' # The folder where uploaded attachment files are saved (must be in public folder)
|
||||
partdb.attachments.dir.secure: 'uploads/' # The folder where secured attachment files are saved (must not be in public/)
|
||||
partdb.attachments.allow_downloads: '%env(bool:ALLOW_ATTACHMENT_DOWNLOADS)%' # Allow users to download attachments to server. Warning: This can be dangerous, because via that feature attackers maybe can access ressources on your intranet!
|
||||
partdb.attachments.dir.media: 'public/media/' # The folder where uploaded attachment files are saved (must be in public folder)
|
||||
partdb.attachments.dir.secure: 'uploads/' # The folder where secured attachment files are saved (must not be in public/)
|
||||
partdb.attachments.max_file_size: '%env(string:MAX_ATTACHMENT_FILE_SIZE)%' # The maximum size of an attachment file (in bytes, you can use M for megabytes and G for gigabytes)
|
||||
|
||||
######################################################################################################################
|
||||
# Error pages
|
||||
@@ -39,6 +45,16 @@ parameters:
|
||||
partdb.error_pages.admin_email: '%env(trim:string:ERROR_PAGE_ADMIN_EMAIL)%' # You can set an email address here, which is shown on an error page, how to contact an administrator
|
||||
partdb.error_pages.show_help: '%env(trim:string:ERROR_PAGE_SHOW_HELP)%' # If this is set to true, solutions to common problems are shown on error pages. Disable this, if you do not want your users to see them...
|
||||
|
||||
######################################################################################################################
|
||||
# SAML
|
||||
######################################################################################################################
|
||||
partdb.saml.enabled: '%env(bool:SAML_ENABLED)%' # If this is set to true, SAML authentication is enabled
|
||||
|
||||
######################################################################################################################
|
||||
# Table settings
|
||||
######################################################################################################################
|
||||
partdb.table.default_page_size: '%env(int:TABLE_DEFAULT_PAGE_SIZE)%' # The default number of entries shown per page in tables
|
||||
|
||||
######################################################################################################################
|
||||
# Sidebar
|
||||
######################################################################################################################
|
||||
@@ -95,7 +111,9 @@ parameters:
|
||||
env(INSTANCE_NAME): 'Part-DB'
|
||||
env(BASE_CURRENCY): 'EUR'
|
||||
env(USE_GRAVATAR): '0'
|
||||
env(ALLOW_ATTACHMENT_DOWNLOADS): 0
|
||||
env(MAX_ATTACHMENT_FILE_SIZE): '100M'
|
||||
|
||||
env(ENFORCE_CHANGE_COMMENTS_FOR): ''
|
||||
|
||||
env(ERROR_PAGE_ADMIN_EMAIL): ''
|
||||
env(ERROR_PAGE_SHOW_HELP): 1
|
||||
@@ -108,5 +126,17 @@ parameters:
|
||||
env(EMAIL_SENDER_NAME): 'Part-DB Mailer'
|
||||
env(ALLOW_EMAIL_PW_RESET): 0
|
||||
|
||||
env(TABLE_DEFAULT_PAGE_SIZE): 50
|
||||
|
||||
env(TRUSTED_PROXIES): '127.0.0.1' #By default trust only our own server
|
||||
env(TRUSTED_HOSTS): '' # Trust all host names by default
|
||||
|
||||
env(DEFAULT_URI): 'https://partdb.changeme.invalid/'
|
||||
|
||||
env(SAML_ROLE_MAPPING): '{}'
|
||||
|
||||
env(HISTORY_SAVE_CHANGED_DATA): 1
|
||||
env(HISTORY_SAVE_CHANGED_FIELDS): 1
|
||||
env(HISTORY_SAVE_REMOVED_DATA): 1
|
||||
env(HISTORY_SAVE_NEW_DATA): 1
|
||||
|
||||
|
||||
@@ -43,6 +43,9 @@ perms: # Here comes a list with all Permission names (they have a perm_[name] co
|
||||
revert_element:
|
||||
label: "perm.revert_elements"
|
||||
alsoSet: ["read", "edit", "create", "delete", "show_history"]
|
||||
import:
|
||||
label: "perm.import"
|
||||
alsoSet: ["read", "edit", "create"]
|
||||
|
||||
parts_stock:
|
||||
group: "data"
|
||||
@@ -76,6 +79,9 @@ perms: # Here comes a list with all Permission names (they have a perm_[name] co
|
||||
revert_element:
|
||||
label: "perm.revert_elements"
|
||||
alsoSet: ["read", "edit", "create", "delete", "show_history"]
|
||||
import:
|
||||
label: "perm.import"
|
||||
alsoSet: [ "read", "edit", "create" ]
|
||||
|
||||
footprints:
|
||||
<<: *PART_CONTAINING
|
||||
@@ -133,6 +139,13 @@ perms: # Here comes a list with all Permission names (they have a perm_[name] co
|
||||
ic_logos:
|
||||
label: "perm.tools.ic_logos"
|
||||
|
||||
info_providers:
|
||||
label: "perm.part.info_providers"
|
||||
operations:
|
||||
create_parts:
|
||||
label: "perm.part.info_providers.create_parts"
|
||||
alsoSet: ['parts.create']
|
||||
|
||||
groups:
|
||||
label: "perm.groups"
|
||||
group: "system"
|
||||
@@ -156,6 +169,9 @@ perms: # Here comes a list with all Permission names (they have a perm_[name] co
|
||||
revert_element:
|
||||
label: "perm.revert_elements"
|
||||
alsoSet: ["read", "edit", "create", "delete", "edit_permissions", "show_history"]
|
||||
import:
|
||||
label: "perm.import"
|
||||
alsoSet: [ "read", "edit", "create" ]
|
||||
|
||||
users:
|
||||
label: "perm.users"
|
||||
@@ -181,6 +197,9 @@ perms: # Here comes a list with all Permission names (they have a perm_[name] co
|
||||
set_password:
|
||||
label: "perm.users.set_password"
|
||||
alsoSet: 'read'
|
||||
impersonate:
|
||||
label: "perm.users.impersonate"
|
||||
alsoSet: ['set_password']
|
||||
change_user_settings:
|
||||
label: "perm.users.change_user_settings"
|
||||
show_history:
|
||||
@@ -188,6 +207,9 @@ perms: # Here comes a list with all Permission names (they have a perm_[name] co
|
||||
revert_element:
|
||||
label: "perm.revert_elements"
|
||||
alsoSet: ["read", "create", "delete", "edit_permissions", "show_history", "edit_infos", "edit_username"]
|
||||
import:
|
||||
label: "perm.import"
|
||||
alsoSet: [ "read", "create" ]
|
||||
|
||||
#database:
|
||||
# label: "perm.database"
|
||||
@@ -227,6 +249,10 @@ perms: # Here comes a list with all Permission names (they have a perm_[name] co
|
||||
alsoSet: 'show_logs'
|
||||
server_infos:
|
||||
label: "perm.server_infos"
|
||||
manage_oauth_tokens:
|
||||
label: "Manage OAuth tokens"
|
||||
show_updates:
|
||||
label: "perm.system.show_available_updates"
|
||||
|
||||
attachments:
|
||||
label: "perm.part.attachments"
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
#index:
|
||||
# path: /
|
||||
# controller: App\Controller\DefaultController::index
|
||||
|
||||
# Redirect every url without an locale to the locale of the user/the global base locale
|
||||
|
||||
scan_qr:
|
||||
path: /scan/{type}/{id}
|
||||
controller: App\Controller\ScanController:scanQRCode
|
||||
controller: App\Controller\ScanController::scanQRCode
|
||||
|
||||
csp_report:
|
||||
path: /csp/report
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
controllers:
|
||||
resource: ../../src/Controller/
|
||||
type: annotation
|
||||
resource:
|
||||
path: ../../src/Controller/
|
||||
namespace: App\Controller
|
||||
type: attribute
|
||||
prefix: '{_locale}'
|
||||
|
||||
defaults:
|
||||
@@ -11,4 +13,4 @@ controllers:
|
||||
|
||||
kernel:
|
||||
resource: ../../src/Kernel.php
|
||||
type: annotation
|
||||
type: attribute
|
||||
4
config/routes/nbgrp_saml.yaml
Normal file
4
config/routes/nbgrp_saml.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
nbgrp_saml:
|
||||
resource: "@NbgrpOneloginSamlBundle/Resources/config/routes.php"
|
||||
# Only load the SAML routes if SAML is enabled
|
||||
condition: "env('SAML_ENABLED') == '1' or env('SAML_ENABLED') == 'true'"
|
||||
@@ -14,16 +14,19 @@ services:
|
||||
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
|
||||
bind:
|
||||
bool $demo_mode: '%partdb.demo_mode%'
|
||||
bool $gpdr_compliance : '%partdb.gpdr_compliance%'
|
||||
bool $kernel_debug: '%kernel.debug%'
|
||||
bool $gdpr_compliance: '%partdb.gdpr_compliance%'
|
||||
bool $kernel_debug_enabled: '%kernel.debug%'
|
||||
string $kernel_cache_dir: '%kernel.cache_dir%'
|
||||
string $partdb_title: '%partdb.title%'
|
||||
string $default_currency: '%partdb.default_currency%'
|
||||
string $base_currency: '%partdb.default_currency%'
|
||||
|
||||
_instanceof:
|
||||
App\Services\LabelSystem\PlaceholderProviders\PlaceholderProviderInterface:
|
||||
tags: ['app.label_placeholder_provider']
|
||||
|
||||
App\Services\InfoProviderSystem\Providers\InfoProviderInterface:
|
||||
tags: ['app.info_provider']
|
||||
|
||||
# makes classes in src/ available to be used as services
|
||||
# this creates a service per class whose id is the fully-qualified class name
|
||||
App\:
|
||||
@@ -78,6 +81,7 @@ services:
|
||||
$save_changed_fields: '%env(bool:HISTORY_SAVE_CHANGED_FIELDS)%'
|
||||
$save_changed_data: '%env(bool:HISTORY_SAVE_CHANGED_DATA)%'
|
||||
$save_removed_data: '%env(bool:HISTORY_SAVE_REMOVED_DATA)%'
|
||||
$save_new_data: '%env(bool:HISTORY_SAVE_NEW_DATA)%'
|
||||
tags:
|
||||
- { name: 'doctrine.event_subscriber' }
|
||||
|
||||
@@ -87,18 +91,18 @@ services:
|
||||
|
||||
App\Form\AttachmentFormType:
|
||||
arguments:
|
||||
$allow_attachments_downloads: '%partdb.attachments.allow_downloads%'
|
||||
$allow_attachments_download: '%partdb.attachments.allow_downloads%'
|
||||
$max_file_size: '%partdb.attachments.max_file_size%'
|
||||
|
||||
App\Services\Attachments\AttachmentSubmitHandler:
|
||||
arguments:
|
||||
$allow_attachments_downloads: '%partdb.attachments.allow_downloads%'
|
||||
$mimeTypes: '@mime_types'
|
||||
$max_upload_size: '%partdb.attachments.max_file_size%'
|
||||
|
||||
App\EventSubscriber\LogSystem\LogoutLoggerListener:
|
||||
tags:
|
||||
- name: 'kernel.event_listener'
|
||||
event: 'Symfony\Component\Security\Http\Event\LogoutEvent'
|
||||
dispatcher: security.event_dispatcher.main
|
||||
App\Services\LogSystem\EventCommentNeededHelper:
|
||||
arguments:
|
||||
$enforce_change_comments_for: '%partdb.enforce_change_comments_for%'
|
||||
|
||||
####################################################################################################################
|
||||
# Attachment system
|
||||
@@ -127,6 +131,15 @@ services:
|
||||
# Security
|
||||
####################################################################################################################
|
||||
|
||||
saml_user_factory:
|
||||
alias: App\Security\SamlUserFactory
|
||||
public: true
|
||||
|
||||
App\Security\SamlUserFactory:
|
||||
arguments:
|
||||
$saml_role_mapping: '%env(json:SAML_ROLE_MAPPING)%'
|
||||
$update_group_on_login: '%env(bool:SAML_UPDATE_GROUP_ON_LOGIN)%'
|
||||
|
||||
####################################################################################################################
|
||||
# Cache
|
||||
####################################################################################################################
|
||||
@@ -167,7 +180,7 @@ services:
|
||||
|
||||
App\EventSubscriber\UserSystem\SetUserTimezoneSubscriber:
|
||||
arguments:
|
||||
$timezone: '%partdb.timezone%'
|
||||
$default_timezone: '%partdb.timezone%'
|
||||
|
||||
App\Controller\SecurityController:
|
||||
arguments:
|
||||
@@ -194,6 +207,10 @@ services:
|
||||
arguments:
|
||||
$available_themes: '%partdb.available_themes%'
|
||||
|
||||
App\Command\User\ConvertToSAMLUserCommand:
|
||||
arguments:
|
||||
$saml_enabled: '%partdb.saml.enabled%'
|
||||
|
||||
|
||||
####################################################################################################################
|
||||
# Label system
|
||||
@@ -207,6 +224,11 @@ services:
|
||||
tags:
|
||||
- { name: 'app.label_placeholder_provider', priority: 10}
|
||||
|
||||
App\Services\LabelSystem\DompdfFactory:
|
||||
arguments:
|
||||
$fontDirectory: '%kernel.project_dir%/var/dompdf/fonts/'
|
||||
$tmpDirectory: '%kernel.project_dir%/var/dompdf/tmp/'
|
||||
|
||||
####################################################################################################################
|
||||
# Trees
|
||||
####################################################################################################################
|
||||
@@ -215,6 +237,46 @@ services:
|
||||
$rootNodeExpandedByDefault: '%partdb.sidebar.root_expanded%'
|
||||
$rootNodeEnabled: '%partdb.sidebar.root_node_enable%'
|
||||
|
||||
####################################################################################################################
|
||||
# Part info provider system
|
||||
####################################################################################################################
|
||||
App\Services\InfoProviderSystem\ProviderRegistry:
|
||||
arguments:
|
||||
$providers: !tagged_iterator 'app.info_provider'
|
||||
|
||||
App\Services\InfoProviderSystem\Providers\Element14Provider:
|
||||
arguments:
|
||||
$api_key: '%env(string:PROVIDER_ELEMENT14_KEY)%'
|
||||
$store_id: '%env(string:PROVIDER_ELEMENT14_STORE_ID)%'
|
||||
|
||||
App\Services\InfoProviderSystem\Providers\DigikeyProvider:
|
||||
arguments:
|
||||
$clientId: '%env(string:PROVIDER_DIGIKEY_CLIENT_ID)%'
|
||||
$currency: '%env(string:PROVIDER_DIGIKEY_CURRENCY)%'
|
||||
$language: '%env(string:PROVIDER_DIGIKEY_LANGUAGE)%'
|
||||
$country: '%env(string:PROVIDER_DIGIKEY_COUNTRY)%'
|
||||
|
||||
App\Services\InfoProviderSystem\Providers\TMEClient:
|
||||
arguments:
|
||||
$secret: '%env(string:PROVIDER_TME_SECRET)%'
|
||||
$token: '%env(string:PROVIDER_TME_KEY)%'
|
||||
|
||||
App\Services\InfoProviderSystem\Providers\TMEProvider:
|
||||
arguments:
|
||||
$currency: '%env(string:PROVIDER_TME_CURRENCY)%'
|
||||
$country: '%env(string:PROVIDER_TME_COUNTRY)%'
|
||||
$language: '%env(string:PROVIDER_TME_LANGUAGE)%'
|
||||
$get_gross_prices: '%env(bool:PROVIDER_TME_GET_GROSS_PRICES)%'
|
||||
|
||||
App\Services\InfoProviderSystem\Providers\OctopartProvider:
|
||||
arguments:
|
||||
$clientId: '&env(string:PROVIDER_OCTOPART_CLIENT_ID)%'
|
||||
$secret: '%env(string:PROVIDER_OCTOPART_SECRET)%'
|
||||
$country: '%env(string:PROVIDER_OCTOPART_COUNTRY)%'
|
||||
$currency: '%env(string:PROVIDER_OCTOPART_CURRENCY)%'
|
||||
$search_limit: '%env(int:PROVIDER_OCTOPART_SEARCH_LIMIT)%'
|
||||
$onlyAuthorizedSellers: '%env(bool:PROVIDER_OCTOPART_ONLY_AUTHORIZED_SELLERS)%'
|
||||
|
||||
####################################################################################################################
|
||||
# Symfony overrides
|
||||
####################################################################################################################
|
||||
@@ -225,6 +287,13 @@ services:
|
||||
tags:
|
||||
- {name: serializer.normalizer, priority: -9000}
|
||||
|
||||
# Disable igbinary serialization for cache even when igbinary is available, as it causes issues with the doctrine
|
||||
# proxy objects (see https://github.com/igbinary/igbinary/issues/377 and https://github.com/igbinary/igbinary/issues/273)
|
||||
cache.default_marshaller:
|
||||
class: Symfony\Component\Cache\Marshaller\DefaultMarshaller
|
||||
arguments:
|
||||
$useIgbinarySerialize: false
|
||||
|
||||
|
||||
####################################################################################################################
|
||||
# Miscellaneous
|
||||
@@ -238,7 +307,7 @@ services:
|
||||
tags:
|
||||
- { name: 'doctrine.fixtures.purger_factory', alias: 'reset_autoincrement_purger' }
|
||||
|
||||
# We are needing this service inside of a migration, where only the container is injected. So we need to define it as public, to access it from the container.
|
||||
# We are needing this service inside a migration, where only the container is injected. So we need to define it as public, to access it from the container.
|
||||
App\Services\UserSystem\PermissionPresetsHelper:
|
||||
public: true
|
||||
|
||||
@@ -246,6 +315,10 @@ services:
|
||||
arguments:
|
||||
$project_dir: '%kernel.project_dir%'
|
||||
|
||||
App\Services\System\UpdateAvailableManager:
|
||||
arguments:
|
||||
$check_for_updates: '%partdb.check_for_updates%'
|
||||
|
||||
####################################################################################################################
|
||||
# Monolog
|
||||
####################################################################################################################
|
||||
@@ -262,3 +335,14 @@ services:
|
||||
autowire: true
|
||||
tags:
|
||||
- { name: monolog.processor }
|
||||
|
||||
when@test:
|
||||
services:
|
||||
# Decorate the doctrine fixtures load command to use our custom purger by default
|
||||
doctrine.fixtures_load_command.custom:
|
||||
decorates: doctrine.fixtures_load_command
|
||||
class: Doctrine\Bundle\FixturesBundle\Command\LoadDataFixturesDoctrineCommand
|
||||
arguments:
|
||||
- '@doctrine.fixtures.loader'
|
||||
- '@doctrine'
|
||||
- { default: '@App\Doctrine\Purger\ResetAutoIncrementPurgerFactory' }
|
||||
4
docs/assets/usage/import_export/part_import_example.csv
Normal file
4
docs/assets/usage/import_export/part_import_example.csv
Normal file
@@ -0,0 +1,4 @@
|
||||
name;description;category;notes;footprint;tags;quantity;storage_location;mass;ipn;mpn;manufacturing_status;manufacturer;supplier;spn;price;favorite;needs_review;minamount;partUnit;manufacturing_status
|
||||
BC547;NPN transistor;Transistors -> NPN;very important notes;TO -> TO-92;NPN,Transistor;5;Room 1 -> Shelf 1 -> Box 2;10;;;Manufacturer;;You need to fill this line, to use spn and price;BC547C;2,3;0;;;;
|
||||
BC557;PNP transistor;<b>HTML</b>;;TO -> TO-92;PNP,Transistor;10;Room 2-> Box 3;;Internal1234;;;;;;;;1;;;active
|
||||
Copper Wire;;Wire;;;;;;;;;;;;;;;;;Meter;
|
||||
|
BIN
docs/assets/usage/information_provider_system/animation.gif
Normal file
BIN
docs/assets/usage/information_provider_system/animation.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 358 KiB |
@@ -26,7 +26,17 @@ The following configuration options can only be changed by the server administra
|
||||
* `INSTANCE_NAME`: The name of your installation. It will be shown as a title in the navbar and other places. By default `Part-DB`, but you can customize it to something likes `ExampleCorp. Inventory`.
|
||||
* `ALLOW_ATTACHMENT_DOWNLOADS` (allowed values `0` or `1`): By setting this option to 1, users can make Part-DB directly download a file specified as an URL and create it as local file. Please not that this allows users access to all ressources publicly available to the server (so full access to other servers in the same local network), which could be a security risk.
|
||||
* `USE_GRAVATAR`: Set to `1` to use [gravatar.com](gravatar.com) images for user avatars (as long as they have not set their own picture). The users browsers have to download the pictures from a third-party (gravatars) server, so this might be a privacy risk.
|
||||
|
||||
* `MAX_ATTACHMENT_FILE_SIZE`: The maximum file size (in bytes) for attachments. You can use the suffix `K`, `M` or `G` to specify the size in kilobytes, megabytes or gigabytes. By default `100M` (100 megabytes). Please note that this only the limit of Part-DB. You still need to configure the php.ini `upload_max_filesize` and `post_max_size` to allow bigger files to be uploaded.
|
||||
* `DEFAULT_URI`: The default URI base to use for the Part-DB, when no URL can be determined from the browser request. This should be the primary URL/Domain, which is used to access Part-DB. This value is used to create correct links in emails and other places, where the URL is needed. It is also used, when SAML is enabled.s If you are using a reverse proxy, you should set this to the URL of the reverse proxy (e.g. `https://part-db.example.com`). **This value must end with a slash**.
|
||||
* `ENFORCE_CHANGE_COMMENTS_FOR`: With this option you can configure, where users are enforced to give a change reason, which will be written to the log. This is a comma separated list of values (e.g. `part_edit,part_delete`). Leave empty to make change comments optional everywhere. Possible values are:
|
||||
* `part_edit`: Edit operation of a existing part
|
||||
* `part_delete`: Delete operation of a existing part
|
||||
* `part_create`: Creation of a new part
|
||||
* `part_stock_operation`: Stock operation on a part (therefore withdraw, add or move stock)
|
||||
* `datastructure_edit`: Edit operation of a existing datastructure (e.g. category, manufacturer, ...)
|
||||
* `datastructure_delete`: Delete operation of a existing datastructure (e.g. category, manufacturer, ...)
|
||||
* `datastructure_create`: Creation of a new datastructure (e.g. category, manufacturer, ...)
|
||||
* `CHECK_FOR_UPDATES` (default `1`): Set this to 0, if you do not want Part-DB to connect to GitHub to check for new versions, or if your server can not connect to the internet.
|
||||
|
||||
### E-Mail settings
|
||||
* `MAILER_DSN`: You can configure the mail provider which should be used for email delivery (see https://symfony.com/doc/current/components/mailer.html for full documentation). If you just want to use an SMTP mail account, you can use the following syntax `MAILER_DSN=smtp://user:password@smtp.mailserver.invalid:587`
|
||||
@@ -34,11 +44,15 @@ The following configuration options can only be changed by the server administra
|
||||
* `EMAIL_SENDER_NAME`: Similar to `EMAIL_SENDER_EMAIL` but this allows you to specify the name from which the mails are sent from.
|
||||
* `ALLOW_EMAIL_PW_RESET`: Set this value to true, if you wan to allow users to reset their password via an email notification. You have to configure the mailprovider first before via the MAILER_DSN setting.
|
||||
|
||||
### Table related settings
|
||||
* `TABLE_DEFAULT_PAGE_SIZE`: The default page size for tables. This is the number of rows which are shown per page. Set to `-1` to disable pagination and show all rows at once.
|
||||
|
||||
### History/Eventlog related settings
|
||||
The following options are used to configure, which (and how much) data is written to the system log:
|
||||
* `HISTORY_SAVE_CHANGED_FIELDS`: When this option is set to true, the name of the fields which are changed, are saved to the DB (so for example it is logged that a user has changed, that the user has changed the name and description of the field, but not the data/content of these changes)
|
||||
* `HISTORY_SAVE_CHANGED_DATA`: When this option is set to true, the changed data is saved to log (so it is logged, that a user has changed the name of a part and what the name was before). This can increase database size, when you have a lot of changes to enties.
|
||||
* `HISTORY_SAVE_CHANGED_DATA`: When this option is set to true, the changed data is saved to log (so it is logged, that a user has changed the name of a part and what the name was before). This can increase database size, when you have a lot of changes to entities.
|
||||
* `HISTORY_SAVE_REMOVED_DATA`: When this option is set to true, removed data is saved to log, meaning that you can easily undelete an entity, when it was removed accidentally.
|
||||
* `HISTORY_SAVE_NEW_DATA`: When this option is set to true, the new data (the data after a change) is saved to element changed log entries. This allows you to easily see the changes between two revisions of an entity. This can increase database size, when you have a lot of changes to entities.
|
||||
|
||||
If you wanna use want to revert changes or view older revisions of entities, then `HISTORY_SAVE_CHANGED_FIELDS`, `HISTORY_SAVE_CHANGED_DATA` and `HISTORY_SAVE_REMOVED_DATA` all have to be true.
|
||||
|
||||
@@ -46,6 +60,25 @@ If you wanna use want to revert changes or view older revisions of entities, the
|
||||
* `ERROR_PAGE_ADMIN_EMAIL`: You can set an email-address here, which is shown on the error page, who should be contacted about the issue (e.g. an IT support email of your company)
|
||||
* `ERROR_PAGE_SHOW_HELP`: Set this 0, to disable the solution hints shown on an error page. These hints should not contain senstive informations, but could confuse end-users.
|
||||
|
||||
### SAML SSO settings
|
||||
The following settings can be used to enable and configure Single-Sign on via SAML. This allows users to login to Part-DB without entering a username and password, but instead they are redirected to a SAML Identity Provider (IdP) and are logged in automatically. This is especially useful, when you want to use Part-DB in a company, where all users have a SAML account (e.g. via Active Directory or LDAP).
|
||||
You can find more advanced settings in the `config/packages/hslavich_onelogin_saml.yaml` file. Please note that this file is not backuped by the backup script, so you have to backup it manually, if you want to keep your changes. If you want to edit it on docker, you have to map the file to a volume.
|
||||
|
||||
* `SAML_ENABLED`: When this is set to 1, SAML SSO is enabled and the SSO Login button is shown in the login form. You have to configure the SAML settings below, before you can use this feature.
|
||||
* `SAML_ROLE_MAPPING`: A [JSON](https://en.wikipedia.org/wiki/JSON) encoded map which specifies how Part-DB should convert the user roles given by SAML attribute `group` should be converted to a Part-DB group (specified by ID). You can use a wildcard `*` to map all otherwise unmapped roles to a certain group. Example: `{"*": 1, "admin": 2, "editor": 3}`. This would map all roles to the group with ID 1, except the role `admin`, which is mapped to the group with ID 2 and the role `editor`, which is mapped to the group with ID 3.
|
||||
* `SAML_UPDATE_GROUP_ON_LOGIN`: When this is enabled the group of the user is updated on every login of the user based on the SAML role attributes. When this is disabled, the group is only assigned on the first login of the user, and a Part-DB administrator can change the group afterwards by editing the user.
|
||||
* `SAML_IDP_ENTITY_ID`: The entity ID of your SAML Identity Provider (IdP). You can find this value in the metadata XML file or configuration UI of your IdP.
|
||||
* `SAML_IDP_SINGLE_SIGN_ON_SERVICE`: The URL of the SAML IdP Single Sign-On Service (SSO). You can find this value in the metadata XML file or configuration UI of your IdP.
|
||||
* `SAML_IDP_SINGLE_LOGOUT_SERVICE`: The URL of the SAML IdP Single Logout Service (SLO). You can find this value in the metadata XML file or configuration UI of your IdP.
|
||||
* `SAML_IDP_X509_CERT`: The base64 encoded X.509 public certificate of your SAML IdP. You can find this value in the metadata XML file or configuration UI of your IdP. It should start with `MIIC` and end with `=`.
|
||||
* `SAML_SP_ENTITY_ID`: The entity ID of your SAML Service Provider (SP). This is the value you have configured for the Part-DB client in your IdP.
|
||||
* `SAML_SP_X509_CERT`: The public X.509 certificate of your SAML SP (here Part-DB). This is the value you have configured for the Part-DB client in your IdP. It should start with `MIIC` and end with `=`. IdPs like keycloak allows you to generate a public/private key pair for the client which you can setup here and in the `SAML_SP_PRIVATE_KEY` setting.
|
||||
* `SAML_SP_PRIVATE_KEY`: The private key of your SAML SP (here Part-DB), corresponding the public key specified in `SAML_SP_X509_CERT`. This is the value you have configured for the Part-DB client in your IdP. It should start with `MIIE` and end with `=`. IdPs like keycloak allows you to generate a public/private key pair for the client which you can setup here and in the `SAML_SP_X509_CERT` setting.
|
||||
|
||||
### Information provider settings
|
||||
The settings prefixes with `PROVIDER_*` are used to configure the information providers.
|
||||
See the [information providers]({% link usage/information_provider_system.md %}) page for more information.
|
||||
|
||||
### Other / less used options
|
||||
* `TRUSTED_PROXIES`: Set the IP addresses (or IP blocks) of trusted reverse proxies here. This is needed to get correct IP informations (see [here](https://symfony.com/doc/current/deployment/proxies.html) for more info).
|
||||
* `TRUSTED_HOSTS`: To prevent `HTTP Host header attacks` you can set a regex containing all host names via which Part-DB should be accessible. If accessed via the wrong hostname, an error will be shown.
|
||||
@@ -72,7 +105,7 @@ The following options are available:
|
||||
|
||||
* `partdb.global_theme`: The default theme to use, when no user specific theme is set. Should be one of the themes from the `partdb.available_themes` config option.
|
||||
* `partdb.locale_menu`: The codes of the languages, which should be shown in the language chooser menu (the one with the user icon in the navbar). The first language in the list will be the default language.
|
||||
* `partdb.gpdr_compliance`: When set to true (default value), IP addresses which are saved in the database will be anonymized, by removing the last byte of the IP. This is required by the GDPR (General Data Protection Regulation) in the EU.
|
||||
* `partdb.gdpr_compliance`: When set to true (default value), IP addresses which are saved in the database will be anonymized, by removing the last byte of the IP. This is required by the GDPR (General Data Protection Regulation) in the EU.
|
||||
* `partdb.sidebar.items`: The panel contents which should be shown in the sidebar by default. You can also change the number of sidebar panels by changing the number of items in this list.
|
||||
* `partdb.sidebar.root_node_enable`: Show a root node in the sidebar trees, of which all nodes are children of
|
||||
* `partdb.sidebar.root_expanded`: Expand the root node in the sidebar trees by default
|
||||
|
||||
@@ -27,7 +27,8 @@ It is installed on a web server and so can be accessed with any browser without
|
||||
* Barcodes/Labels generator for parts and storage locations, scan barcodes via webcam using the builtin barcode scanner
|
||||
* User system with groups and detailed (fine granular) permissions.
|
||||
Two-factor authentication is supported (Google Authenticator and Webauthn/U2F keys) and can be enforced for groups. Password reset via email can be setuped.
|
||||
* Import/Export system (partial working)
|
||||
* Optional support for single sign-on (SSO) via SAML (using an intermediate service like [Keycloak](https://www.keycloak.org/) you can connect Part-DB to an existing LDAP or Active Directory server)
|
||||
* Import/Export system
|
||||
* Project management: Create projects and assign parts to the bill of material (BOM), to show how often you could build this project and directly withdraw all components needed from DB
|
||||
* Event log: Track what changes happens to your inventory, track which user does what. Revert your parts to older versions.
|
||||
* Responsive design: You can use Part-DB on your PC, your tablet and your smartphone using the same interface.
|
||||
@@ -35,7 +36,8 @@ It is installed on a web server and so can be accessed with any browser without
|
||||
* Support for rich text descriptions and comments in parts
|
||||
* Support for multiple currencies and automatic update of exchange rates supported
|
||||
* Powerful search and filter function, including parametric search (search for parts according to some specifications)
|
||||
|
||||
* Easy migration from an existing PartKeepr instance (see [here]({%link partkeepr_migration.md %}))
|
||||
* Use cloud providers (like Octopart, Digikey, farnell or TME) to automatically get part information, datasheets and prices for parts (see [here]({% link usage/information_provider_system.md %}))
|
||||
|
||||
With these features Part-DB is useful to hobbyists, who want to keep track of their private electronic parts inventory,
|
||||
or makerspaces, where many users have should have (controlled) access to the shared inventory.
|
||||
|
||||
@@ -22,9 +22,9 @@ sudo apt install git curl zip ca-certificates software-properties-common apt-tra
|
||||
```
|
||||
|
||||
### Install PHP and apache2
|
||||
Part-DB is written in [PHP](https://php.net) and therefore needs an PHP interpreter to run. Part-DB needs PHP 7.3 or higher, however it is recommended to use the most recent version of PHP for performance reasons and future compatibility.
|
||||
Part-DB is written in [PHP](https://php.net) and therefore needs an PHP interpreter to run. Part-DB needs PHP 8.1 or higher, however it is recommended to use the most recent version of PHP for performance reasons and future compatibility.
|
||||
|
||||
As Debian 11 does not ship PHP 8.1 in it's default repositories, we have to add a repository for it. You can skip this step if your distribution is shipping a recent version of PHP or you want to use the built-in PHP version.
|
||||
As Debian 11 does not ship PHP 8.1 in it's default repositories, we have to add a repository for it. You can skip this step if your distribution is shipping a recent version of PHP or you want to use the built-in PHP version. If you are using Debian 12, you can skip this step, as PHP 8.1 is already included in the default repositories.
|
||||
```bash
|
||||
# Add sury repository for PHP 8.1
|
||||
sudo curl -sSL https://packages.sury.org/php/README.txt | sudo bash -x
|
||||
@@ -74,6 +74,17 @@ We now have all prerequisites installed and can start to install Part-DB. We wil
|
||||
git clone https://github.com/Part-DB/Part-DB-symfony.git /var/www/partdb
|
||||
```
|
||||
|
||||
By default you are now on the latest development version. In most cases you want to use the latest stable version. You can switch to the latest stable version (tagged) by running the following command:
|
||||
```bash
|
||||
# This finds the latest release/tag and checks it out
|
||||
git checkout $(git describe --tags $(git rev-list --tags --max-count=1))
|
||||
```
|
||||
Alternatively you can checkout a specific version by running (see [GitHub Relases page](https://github.com/Part-DB/Part-DB-server/releases) for a list of available versions):
|
||||
```bash
|
||||
# This checks out the version 1.5.2
|
||||
git checkout v1.5.2
|
||||
```
|
||||
|
||||
Change ownership of the files to the apache user:
|
||||
```bash
|
||||
chown -R www-data:www-data /var/www/partdb
|
||||
@@ -90,7 +101,7 @@ The basic configuration of Part-DB is done by a `.env.local` file in the main di
|
||||
cp .env .env.local
|
||||
```
|
||||
|
||||
In your `.env.local` you can configure Part-DB according to your wishes. A full list of configuration options can be found [here]({% link configuration.md %}.
|
||||
In your `.env.local` you can configure Part-DB according to your wishes. A full list of configuration options can be found [here](../configuration.md).
|
||||
Other configuration options like the default language or default currency can be found in `config/parameters.yaml`.
|
||||
|
||||
Please check that the `partdb.default_currency` value in `config/parameters.yaml` matches your mainly used currency, as this can not be changed after creating price informations.
|
||||
@@ -184,6 +195,10 @@ If you want to update your existing Part-DB installation, you just have to run t
|
||||
cd /var/www/partdb
|
||||
# Pull latest Part-DB version from GitHub
|
||||
git pull
|
||||
|
||||
# Checkout the latest version (or use a specific version, like described above)
|
||||
git checkout $(git describe --tags $(git rev-list --tags --max-count=1))
|
||||
|
||||
# Apply correct permission
|
||||
chown -R www-data:www-data .
|
||||
# Install new composer dependencies
|
||||
@@ -199,7 +214,7 @@ sudo nano config/parameters.yaml
|
||||
sudo -u www-data php bin/console doctrine:migrations:migrate
|
||||
|
||||
# Clear Part-DB cache
|
||||
sudo u www-data php bin/console cache:clear
|
||||
sudo -u www-data php bin/console cache:clear
|
||||
```
|
||||
|
||||
## MySQL/MariaDB database
|
||||
|
||||
@@ -17,3 +17,5 @@ For example, if your reverse proxy has the IP address `192.168.2.10`, your value
|
||||
```
|
||||
TRUSTED_PROXIES=192.168.2.10
|
||||
```
|
||||
|
||||
Set the `DEFAULT_URI` environment variable to the URL of your Part-DB installation, available from the outside (so via the reverse proxy).
|
||||
150
docs/installation/saml_sso.md
Normal file
150
docs/installation/saml_sso.md
Normal file
@@ -0,0 +1,150 @@
|
||||
---
|
||||
title: Single Sign-On via SAML
|
||||
layout: default
|
||||
parent: Installation
|
||||
nav_order: 12
|
||||
---
|
||||
|
||||
# Single Sign-On via SAML
|
||||
|
||||
Part-DB supports Single Sign-On via SAML. This means that you can use your existing SAML identity provider to log in to Part-DB.
|
||||
Using an intermediate SAML server like [Keycloak](https://www.keycloak.org/), also allows you to connect Part-DB to a LDAP or Active Directory server.
|
||||
|
||||
{: .important }
|
||||
> This feature is for advanced users only. Single Sign-On is useful for large organizations with many users, which are already using SAML for other services.
|
||||
> If you have only one or a few users, you should use the built-in authentication system of Part-DB.
|
||||
> This guide assumes that you already have an SAML identity provider set up and working, and have a basic understanding of how SAML works.
|
||||
|
||||
{: .warning }
|
||||
> This feature is currently in beta. Please report any bugs you find.
|
||||
> So far it has only tested with Keycloak, but it should work with any SAML 2.0 compatible identity provider.
|
||||
|
||||
This guide will show you how to configure Part-DB with [Keycloak](https://www.keycloak.org/) as the SAML identity provider,
|
||||
but it should work with any SAML 2.0 compatible identity provider.
|
||||
|
||||
This guide assumes that you have a working Keycloak installation with some users. If you don't, you can follow the [Keycloak Getting Started Guide](https://www.keycloak.org/docs/latest/getting_started/index.html).
|
||||
|
||||
{: .important }
|
||||
> Part-DB associates local users with SAML users by their username. That means if the username of a SAML user changes, a new local user will be created (and the old account can not be accessed).
|
||||
> You should make sure that the username of a SAML user does not change. If you use Keycloak make sure that the possibility to change the username is disabled (which is by default).
|
||||
> If you really have to rename a SAML user, a Part-DB admin can rename the local user in the Part-DB in the admin panel, to match the new username of the SAML user.
|
||||
|
||||
## Configure basic SAML connection
|
||||
|
||||
### Create a new SAML client
|
||||
1. First, you need to configure a new SAML client in Keycloak. Login in to your Keycloak admin console and go to the `Clients` page.
|
||||
2. Click on `Create client` and select `SAML` as type from the dropdown menu. For the client ID, you can use anything you want, but it should be unique.
|
||||
*It is recommended to set this value to the domain name of your Part-DB installation, with an attached `/sp` (e.g. `https://partdb.yourdomain.invalid/sp`)*.
|
||||
The name field should be set to something human-readable, like `Part-DB`.
|
||||
3. Click on `Save` to create the new client.
|
||||
|
||||
### Configure the SAML client
|
||||
|
||||
1. Now you need to configure the SAML client. Go to the `Settings` tab and set the following values:
|
||||
* Set `Home URL` to the homepage of your Part-DB installation (e.g. `https://partdb.yourdomain.invalid/`).
|
||||
* Set `Valid redirect URIs` to your homepage with a wildcard at the end (e.g. `https://partdb.yourdomain.invalid/*`).
|
||||
* Set `Valid post logout redirect URIs` to `+` to allow all urls from the `Valid redirect URIs`.
|
||||
* Set `Name ID format` to `username`
|
||||
* Ensure `Force POST binding` is enabled.
|
||||
* Ensure `Sign documents` is enabled.
|
||||
* Ensure `Front channel logout` is enabled.
|
||||
* Ensure `Signature Algorithm` is set to `RSA_SHA256`.
|
||||
|
||||
Click on `Save` to save the changes.
|
||||
2. Go to the `Advanced` tab and set the following values:
|
||||
* Assertion Consumer Service POST Binding URL to your homepage with `/saml/acs` at the end (e.g. `https://partdb.yourdomain.invalid/saml/acs`).
|
||||
* Logout Service POST Binding URL to your homepage with `/logout` at the end (e.g. `https://partdb.yourdomain.invalid/logout`).
|
||||
3. Go to Keys tab and ensure `Client Signature Required` is enabled.
|
||||
4. In the Keys tab click on `Generate new keys`. This will generate a new key pair for the SAML client. The private key will be downloaded to your computer.
|
||||
|
||||
### Configure Part-DB to use SAML
|
||||
1. Open the `.env.local` file of Part-DB (or the docker-compose.yaml) for edit
|
||||
2. Set the `SAMLP_SP_PRIVATE_KEY` environment variable to the content of the private key file you downloaded in the previous step. It should start with `MIEE` and end with `=`.
|
||||
3. Set the `SAML_SP_X509_CERT` environment variable to the content of the Certificate field shown in the `Keys` tab of the SAML client in Keycloak. It should start with `MIIC` and end with `=`.
|
||||
4. Set the `SAML_SP_ENTITY_ID` environment variable to the entityID of the SAML client in Keycloak (e.g. `https://partdb.yourdomain.invalid/sp`).
|
||||
5. In Keycloak navigate to `Realm Settings` -> `SAML 2.0 Identity Provider` (by default something like `https://idp.yourdomain.invalid/realms/master/protocol/saml/descriptor) to show the SAML metadata.
|
||||
6. Copy the `entityID` value from the metadata to the `SAML_IDP_ENTITY_ID` configuration variable of Part-DB (by default something like `https://idp.yourdomain.invalid/realms/master`).
|
||||
7. Copy the `Single Sign-On Service` value from the metadata to the `SAML_IDP_SINGLE_SIGN_ON_SERVICE` configuration variable of Part-DB (by default something like `https://idp.yourdomain.invalid/realms/master/protocol/saml`).
|
||||
8. Copy the `Single Logout Service` value from the metadata to the `SAML_IDP_SINGLE_LOGOUT_SERVICE` configuration variable of Part-DB (by default something like `https://idp.yourdomain.invalid/realms/master/protocol/saml/logout`).
|
||||
9. Copy the `X.509 Certificate` value from the metadata to the `SAML_IDP_X509_CERT` configuration variable of Part-DB (it should start with `MIIC` and should be pretty long).
|
||||
10. Set the `DEFAULT_URI` to the homepage (on the publicly available domain) of your Part-DB installation (e.g. `https://partdb.yourdomain.invalid/`). It must end with a slash.
|
||||
11. Set the `SAML_ENABLED` configuration in Part-DB to 1 to enable SAML authentication.
|
||||
|
||||
When you access the Part-DB login form now, you should see a new button to log in via SSO. Click on it to be redirected to the SAML identity provider and log in.
|
||||
|
||||
In the following sections, you will learn how to configure that Part-DB uses the data provided by the SAML identity provider to fill out user informations.
|
||||
|
||||
### Set user information based on SAML attributes
|
||||
Part-DB can set basic user information like the username, the real name and the email address based on the SAML attributes provided by the SAML identity provider.
|
||||
To do this, you need to configure your SAML identity provider to provide the following attributes:
|
||||
|
||||
* `email` or `urn:oid:1.2.840.113549.1.9.1` for the email address
|
||||
* `firstName` or `urn:oid:2.5.4.42` for the first name
|
||||
* `lastName` or `urn:oid:2.5.4.4` for the last name
|
||||
* `department` for the department field of the user
|
||||
|
||||
You can omit any of these attributes, but then the corresponding field will be empty (but can be overriden by an administrator).
|
||||
These values are written to Part-DB database, whenever the user logs in via SAML (the user is created on the first login, and updated on every login).
|
||||
|
||||
To configure Keycloak to provide these attributes, you need to go to the `Client scopes` page and select the `sp-dedicatd` client scope (or create a new one).
|
||||
In the scope configuration page, click on `Add mappers` and `From predefined mappers`. Select the following mappers:
|
||||
* `X500 email`
|
||||
* `X500 givenName`
|
||||
* `X500 surname`
|
||||
|
||||
and click `Add`. Now Part-DB will be provided with the email, first name and last name of the user based on the Keycloak user database.
|
||||
|
||||
### Configure permissions for SAML users
|
||||
On the first login of a SAML user, Part-DB will create a new user in the database. This user will have the same username as the SAML user, but no password set. The user will be marked as a SAML user, so he can only login via SAML in the future. However in other aspects the user is a normal user, so Part-DB admins can set permissions for SAML users like for any other user and override permissions assigned via groups.
|
||||
|
||||
However for large organizations you maybe want to automatically assign permissions to SAML users based on the roles or groups configured in the identity provider. For this purpose Part-DB allows you to map SAML roles or groups to Part-DB groups. See the next section for details.
|
||||
|
||||
### Map SAML roles to Part-DB groups
|
||||
Part-DB allows you to configure a mapping between SAML roles or groups and Part-DB groups. This allows you to automatically assign permissions to SAML users based on the roles or groups configured in the identity provider. For example if a user at your SAML provider has the role `admin`, you can configure Part-DB to assign the `admin` group to this user. This will give the user all permissions of the `admin` group.
|
||||
|
||||
For this you need first have to create the groups in Part-DB, to which you want to assign the users and configure their permissions. You will need the IDs of the groups, which you can find in the `System->Group` page of Part-DB in the Info tab.
|
||||
|
||||
The map is provided as [JSON](https://en.wikipedia.org/wiki/JSON) encoded map between the SAML role and the group ID, which has the form `{"saml_role": group_id, "*": group_id, ...}`. You can use the `*` key to assign a group to all users, which are not in any other group. The map is configured via the `SAML_ROLE_MAPPING` environment variable, which you can configure via the `.env.local` or `docker-compose.yml` file. Please note that you have to enclose the JSON string in single quotes here, as JSON itself uses double quotes (e.g. `SAML_ROLE_MAPPING='{ "*": 2, "editor": 3, "admin": 1 }`).
|
||||
|
||||
For example if you want to assign the group with ID 1 (by default admin) to every SAML user which has the role `admin`, the role with ID 3 (by default editor) to every SAML user with the role `editor` and everybody else to the group with ID 2 (by default readonly), you can configure the following map:
|
||||
|
||||
```
|
||||
SAML_ROLE_MAPPING='{"admin": 1, "editor": 3, "*": 2}'
|
||||
```
|
||||
|
||||
Please not that the order of the mapping is important. The first matching role will be assigned to the user. So if you have a user with the roles `admin` and `editor`, he will be assigned to the group with ID 1 (admin) and not to the group with ID 3 (editor), as the `admin` role comes first in the JSON map.
|
||||
This mean that you should always put the most specific roles (e.g. admins) first of the map and the most general roles (e.g. normal users) later.
|
||||
|
||||
If you want to assign users with a certain role to a empty group, provide the group ID -1 as the value. This is not a valid group ID, so the user will not be assigned to any group.
|
||||
|
||||
The SAML roles (or groups depending on your configuration), have to be supplied via a SAML attribute `group`. You have to configure your SAML identity provider to provide this attribute. For example in Keycloak you can configure this attribute in the `Client scopes` page. Select the `sp-dedicated` client scope (or create a new one) and click on `Add mappers`. Select `Role mapping` or `Group membership`, change the field name and click `Add`. Now Part-DB will be provided with the groups of the user based on the Keycloak user database.
|
||||
|
||||
By default, the group is assigned to the user on the first login and updated on every login based on the SAML attributes. This allows you to configure the groups in the SAML identity provider and the users will automatically stay up to date with their permissions. However, if you want to disable this behavior (and let the Part-DB admins configure the groups manually, after the first login), you can set the `SAML_UPDATE_GROUP_ON_LOGIN` environment variable to `false`. If you want to disable the automatic group assignment completly (so not even on the first login of a user), set the `SAML_ROLE_MAPPING` to `{}` (empty JSON object).
|
||||
|
||||
## Overview of possible SAML attributes used by Part-DB
|
||||
The following table shows all SAML attributes, which can be usedby Part-DB. If your identity provider is configured to provide these attributes, you can use to automatically fill the corresponding fields of the user in Part-DB.
|
||||
|
||||
| SAML attribute | Part-DB user field | Description |
|
||||
|-------------------------------------------|-------------------|-------------------------------------------------------------------|
|
||||
| `urn:oid:1.2.840.113549.1.9.1` or `email` | email | The email address of the user. |
|
||||
| `urn:oid:2.5.4.42` or `firstName` | firstName | The first name of the user. |
|
||||
| `urn:oid:2.5.4.4` or `lastName` | lastName | The last name of the user. |
|
||||
| `department` | department | The department of the user. |
|
||||
| `group` | group | The group of the user (determined by `SAML_ROLE_MAPPING` option). |
|
||||
|
||||
## Use SAML Login for existing users
|
||||
Part-DB distinguishes between local users and SAML users. Local users are users, which can login via Part-DB login form and which use the password (hash) saved in the Part-DB database. SAML users are stored in the database too (they are created on the first login of the user via SAML), but they use the SAML identity provider to authenticate the user and have no password stored in the database. When you try you will get an error message.
|
||||
|
||||
For security reasons it is not possible to authenticate via SAML as a local user (and vice versa). So if you have existing users in your Part-DB database and want them to be able to login via SAML in the future, you can use the `php bin/console partdb:user:convert-to-saml-user username` command to convert them to SAML users. This will remove the password hash from the database and mark them as SAML users, so they can login via SAML in the future.
|
||||
|
||||
The reverse is also possible: If you have existing SAML users and want them to be able to login via the Part-DB login form, you can use the `php bin/console partdb:user:convert-to-saml-user --to-local username` command to convert them to local users. You have to set an password for the user afterwards.
|
||||
|
||||
{: .important }
|
||||
> It is recommended that you let the original admin user (ID: 2) be a local user, so you can still login to Part-DB if the SAML identity provider is not available.
|
||||
|
||||
## Advanced SAML configuration
|
||||
You can find some more advanced SAML configuration options in the `config/packages/nbgrp_onelogin_saml.yaml` file. Refer to the file for more information.
|
||||
Normally you don't have to change anything here.
|
||||
|
||||
Please note that this file is not saved by the Part-DB backup tool, so you have to save it manually if you want to keep your changes. On docker containers you have to configure a volume mapping for it.
|
||||
|
||||
51
docs/partkeepr_migration.md
Normal file
51
docs/partkeepr_migration.md
Normal file
@@ -0,0 +1,51 @@
|
||||
---
|
||||
layout: default
|
||||
title: Migrate from PartKeepr to Part-DB
|
||||
nav_order: 101
|
||||
---
|
||||
|
||||
# Migrate from PartKeepr to Part-DB
|
||||
|
||||
{: .warning }
|
||||
> This feature is currently in beta. Please report any bugs you find.
|
||||
|
||||
This guide describes how to migrate from [PartKeepr](https://partkeepr.org/) to Part-DB.
|
||||
|
||||
Part-DB has a built-in migration tool, which can be used to migrate the data from an existing PartKeepr instance to
|
||||
a new Part-DB instance. Most of the data can be migrated, however there are some limitations, you can find below.
|
||||
|
||||
## What can be imported
|
||||
* Datastructures (Categories, Footprints, Storage Locations, Manufacturers, Distributors, Part Measurement Units)
|
||||
* Basic part informations (Name, Description, Comment, etc.)
|
||||
* Attachments and images of parts, projects, footprints, manufacturers and storage locations
|
||||
* Part prices (distributor infos)
|
||||
* Part parameters
|
||||
* Projects (including parts and attachments)
|
||||
* Users (optional): Passwords however will be not migrated, and need to be reset later
|
||||
|
||||
## What can't be imported
|
||||
* Metaparts (A dummy version of the metapart will be created in Part-DB, however it will not function as metapart)
|
||||
* Multiple manufacturers per part (only the last manufacturer of a part will be migrated)
|
||||
* Overage information for project parts (the overage info will be set as comment in the project BOM, but will have no effect)
|
||||
* Batch Jobs
|
||||
* Parameter Units (the units will be written into the parameters)
|
||||
* Project Reports and Project Runs
|
||||
* Stock history
|
||||
* Any kind of PartKeepr preferences
|
||||
|
||||
## How to migrate
|
||||
1. Install Part-DB like described in the installation guide. You can use any database backend you want (mysql or sqlite). Run the database migration, but do not create any new data yet.
|
||||
2. Export your PartKeepr database as XML file using [mysqldump](https://dev.mysql.com/doc/refman/8.0/en/mysqldump.html):
|
||||
When the MySQL database is running on the local computer and you are root you can just run the command `mysqldump --xml PARTKEEPR_DATABASE --result-file pk.xml`.
|
||||
If your server is remote or your MySQL authentication is different, you need to run `mysqldump --xml -h PARTKEEPR_HOST -u PARTKEEPR_USER -p PARTKEEPR_DATABASE`, where you replace `PARTKEEPR_HOST`
|
||||
with the hostname of your MySQL database and `PARTKEEPR_USER` with the username of MySQL user which has access to the PartKeepr database. You will be asked for the MySQL user password.
|
||||
3. Go the Part-DB main folder and run the command `php bin/console partdb:migrations:import-partkeepr path/to/pk.xml`. This step will delete all existing data in the Part-DB database and import the contents of PartKeepr.
|
||||
4. Copy the contents of `data/files/` from your PartKeepr installation to the `uploads/` folder of your Part-DB installation and the contents of `data/images` from PartKeepr to `public/media/` of Part-DB.
|
||||
5. Clear the cache of Part-DB by running: `php bin/console cache:clear`
|
||||
6. Go to the Part-DB web interface. You can login with the username `admin` and the password, which is shown during the installation process of Part-DB (step 1). You should be able to see all the data from PartKeepr.
|
||||
|
||||
## Import users
|
||||
If you want to import the users (mostly the username and email address) from PartKeepr, you can add the `--import-users` option on the database import command (step 3): `php bin/console partdb:migrations:import-partkeepr --import-users path/to/pk.xml`.
|
||||
|
||||
All imported users of PartKeepr will be assigned to a new group "PartKeepr Users", which has normal user permissions (so editing data, but no administrative tasks). You can change the group and permissions later in Part-DB users managment.
|
||||
Passwords can not be imported from PartKeepr and all imported users get marked as disabled user. So to allow users to login, you need to enable them in the user management and assign a password.
|
||||
@@ -22,6 +22,11 @@ php bin/console doctrine:migrations:migrate
|
||||
|
||||
If this does not help, please [open an issue on GitHub](https://github.com/Part-DB/Part-DB-symfony).
|
||||
|
||||
## Search for user and reset password:
|
||||
You can list all users with the following command: `php bin/console partdb:users:list`
|
||||
To reset the password of a user you can use the following command: `php bin/console partdb:users:set-password [username]`
|
||||
|
||||
|
||||
## Error logs
|
||||
Detailed error logs can be found in the `var/log` directory.
|
||||
When Part-DB is installed directly, the errors are written to the `var/log/prod.log` file.
|
||||
@@ -35,4 +40,4 @@ docker-compose logs -f
|
||||
Please include the error logs in your issue on GitHub, if you open an issue.
|
||||
|
||||
## Report Issue
|
||||
If an error occurs, or you found a bug, please [open an issue on GitHub](https://github.com/Part-DB/Part-DB-symfony).
|
||||
If an error occurs, or you found a bug, please [open an issue on GitHub](https://github.com/Part-DB/Part-DB-symfony).
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
layout: default
|
||||
title: Upgrade from legacy Part-DB version (<1.0)
|
||||
nav_order: 100
|
||||
---
|
||||
|
||||
# Upgrade from legacy Part-DB version
|
||||
@@ -23,13 +24,14 @@ Some things changed however to the old version and some features are still missi
|
||||
* Configuration is now done via configuration files / environment variables instead of the WebUI (this maybe change in the future).
|
||||
* Database updated are now done via console instead of the WebUI
|
||||
* Permission system changed: **You will have to newly set the permissions of all users and groups!**
|
||||
* Import / Export file format changed. Fields must be english now (unlike in legacy Part-DB versions, where german fields in CSV were possible)
|
||||
and you maybe have to change the header line/field names of your CSV files.
|
||||
|
||||
## Missing features
|
||||
* No possibility to mark parts for ordering (yet)
|
||||
* No import / export possibility for parts (yet), however you can import/export other datastructures like Categories, Footprints, etc. (yet)
|
||||
* No support for 3D models of footprints (yet)
|
||||
* No possibility to disable footprints, manufacturers globally (or per category). This should not have a big impact, when you forbid users to edit/create them.
|
||||
|
||||
* No resistor calculator or SMD labels tools
|
||||
|
||||
## Upgrade process
|
||||
|
||||
|
||||
29
docs/usage/bom_import.md
Normal file
29
docs/usage/bom_import.md
Normal file
@@ -0,0 +1,29 @@
|
||||
---
|
||||
layout: default
|
||||
title: Import Bill of Material (BOM) for Projects
|
||||
nav_order: 5
|
||||
parent: Usage
|
||||
---
|
||||
|
||||
# Import Bill of Material (BOM) for Projects
|
||||
|
||||
Part-DB supports the import of Bill of Material (BOM) files for projects. This allows you to directly import a BOM file from your ECAD software into your Part-DB project.
|
||||
|
||||
|
||||
The import process is currently semi-automatic. This means Part-DB will take the BOM file and create entries for all parts in the BOM file in your project and assign fields like
|
||||
mountnames (e.g. 'C1, C2, C3'), quantity and more.
|
||||
However, you still have to assign the parts from Part-DB database to the entries (if applicable) after the import by hand,
|
||||
as Part-DB can not know which part you had in mind when you designed your schematic.
|
||||
|
||||
## Usage
|
||||
In the project view or edit click on the "Import BOM" button, below the BOM table. This will open a dialog where you can
|
||||
select the BOM file you want to import and some options for the import process:
|
||||
|
||||
* **Type**: The format/type of the BOM file. See below for explanations of the different types.
|
||||
* **Clear existing BOM entries before import**: If this is checked, all existing BOM entries, which are currently associated with the project, will be deleted before the import.
|
||||
|
||||
### Supported BOM file formats
|
||||
|
||||
* **KiCAD Pcbnew BOM (CSV file)**: A CSV file of the Bill of Material (BOM) generated by [KiCAD Pcbnew](https://www.kicad.org/).
|
||||
Please note that you have to export the BOM from the PCB editor, the BOM generated by the schematic editor (Eeschema) has a different format and does not work with this type.
|
||||
You can generate this BOM file by going to "File" -> "Fabrication Outputs" -> "Bill of Materials" in Pcbnew and save the file to your desired location.
|
||||
@@ -19,6 +19,7 @@ You can get help for every command with the parameter `--help`. See `php bin/con
|
||||
* `php bin/console partdb:users:permissions`: View/Change the permissions of the user with the given username
|
||||
* `php bin/console partdb:users:upgrade-permissions-schema`: Upgrade the permissions schema of users to the latest version (this is normally automatically done when the user visits a page)
|
||||
* `php bin/console partdb:logs:show`: Show the most recent entries of the Part-DB event log / recent activity
|
||||
* `php bin/console partdb:user:convert-to-saml-user`: Convert a local user to a SAML/SSO user. This is needed, if you want to use SAML/SSO authentication for a user, which was created before you enabled SAML/SSO authentication.
|
||||
|
||||
## Currency commands
|
||||
* `php bin/console partdb:currencies:update-exchange-rates`: Update the exchange rates of all currencies from the internet)
|
||||
@@ -30,6 +31,7 @@ You can get help for every command with the parameter `--help`. See `php bin/con
|
||||
* `partdb:migrations:convert-bbcode`: Migrate the old BBCode markup codes used in legacy Part-DB versions (< 1.0.0) to the new markdown syntax
|
||||
* `partdb:attachments:clean-unused`: Remove all attachments which are not used by any database entry (e.g. orphaned attachments)
|
||||
* `partdb:cache:clear`: Clears all caches, so the next page load will be slower, but the cache will be rebuild. This can maybe fix some issues, when the cache were corrupted. This command is also needed after changing things in the `parameters.yaml` file or upgrading Part-DB.
|
||||
* `partdb:migrations:import-partkeepr`: Imports an mysqldump XML dump of a PartKeepr database into Part-DB. This is only needed for users, which want to migrate from PartKeepr to Part-DB. *All existing data in the Part-DB database is deleted!*
|
||||
|
||||
## Database commands
|
||||
* `php bin/console doctrine:migrations:migrate`: Migrate the database to the latest version
|
||||
|
||||
103
docs/usage/import_export.md
Normal file
103
docs/usage/import_export.md
Normal file
@@ -0,0 +1,103 @@
|
||||
---
|
||||
layout: default
|
||||
title: Import & Export data
|
||||
nav_order: 4
|
||||
parent: Usage
|
||||
---
|
||||
|
||||
# Import & Export data
|
||||
|
||||
Part-DB offers the possibility to import existing data (parts, datastructures, etc.) from existing datasources into Part-DB. Data can also be exported from Part-DB into various formats.
|
||||
|
||||
## Import
|
||||
|
||||
{: .note }
|
||||
> As data import is a very powerful feature and can easily fill up your database with lots of data, import is by default only available for
|
||||
> administrators. If you want to allow other users to import data, or can not import data, check the permissions of the user. You can enable import for each data structure
|
||||
> individually in the permissions settings.
|
||||
|
||||
If you want to import data from PartKeepr you might want to look into the [PartKeepr migration guide]({% link upgrade_legacy.md %}).
|
||||
|
||||
### Import parts
|
||||
|
||||
Part-DB supports the import of parts from CSV files and other formats. This can be used to import existing parts from other databases or datasources into Part-DB. The import can be done via the "Tools -> Import parts" page, which you can find in the "Tools" sidebar panel.
|
||||
|
||||
{: .important }
|
||||
> When importing data, the data is immediatley written to database during the import process, when the data is formally valid.
|
||||
> You will not be able to check the data before it is written to the database, so you should review the data before using the import tool.
|
||||
|
||||
You can upload the file which should be imported here and choose various options on how the data should be treated:
|
||||
* **Format**: By default "auto" is selected here and Part-DB will try to detect the format of the file automatically based on its file extension. If you want to force a specific format or Part-DB can not auto-detect the format, you can select it here.
|
||||
* **CSV delimiter**: If you upload an CSV file, you can select the delimiter character which is used to separate the columns in the CSV file. Depending on the CSV file, this might be a comma (`,`), semicolon (`;`).
|
||||
* **Category override**: You can select (or create) a category here, to which all imported parts should be assigned, no matter what was specified in the import file. This can be useful if you want to assign all imports to a certain category or if no category is specified in the data. If you leave this field empty, the category will be determined by the import file (or the export will error, if no category is specified).
|
||||
* **Mark all imported parts as "Needs review"**: If this is selected, all imported parts will be marked as "Needs review" after the import. This can be useful if you want to review all imported parts before using them.
|
||||
* **Create unknown datastructures**: If this is selected Part-DB will create new datastructures (like categories, manufacturers, etc.) if no datastructure(s) with the same name and path already exists. If this is not selected, only existing datastructures will be used and if no matching datastrucure is found, the imported parts field will be empty.
|
||||
* **Path delimiter**: Part-DB allows you to create/select nested datastructures (like categories, manufacturers, etc.) by using a path (e.g. `Category 1->Category 1.1`, which will select/create the `Category 1.1` whose parent is `Category 1`). This path is separated by the path delimiter. If you want to use a different path delimiter than the default one (which is `>`), you can select it here.
|
||||
* **Abort on validation error**: If this is selected, the import will be aborted if a validation error occurs (e.g. if a required field is empty) for any of the imported parts and validation errors will be shown on top of the page. If this is not selected, the import will continue for the other parts and only the invalid parts will be skipped.
|
||||
|
||||
After you have selected the options, you can start the import by clicking the "Import" button. When the import is finished, you will see the results of the import in the lower half of the page. You find a table with the imported parts (including links to them) there.
|
||||
|
||||
#### Fields description
|
||||
|
||||
For the importing of parts, you can use the following fields which will be imported into each part. Please note that the field names are case sensitive (so `name` is not the same as `Name`). All fields (besides name) are optional, so you can leave them empty or do not include the column in your file.
|
||||
|
||||
* **`name`** (required): The name of the part. This is the only required field, all other fields are optional.
|
||||
* **`description`**: The description of the part, you can use markdown/HTML syntax here for rich text formatting.
|
||||
* **`notes`** or **`comment`**: The notes of the part, you can use markdown/HTML syntax here for rich text formatting.
|
||||
* **`category`**: The category of the part. This can be a path (e.g. `Category 1->Category 1.1`), which will select/create the `Category 1.1` whose parent is `Category 1`. If you want to use a different path delimiter than the default one (which is `->`), you can select it in the import options. If the category does not exist and the option "Create unknown datastructures" is selected, it will be created.
|
||||
* **`footprint`**: The footprint of the part. Can be a path similar to the category field.
|
||||
* **`favorite`**: If this is set to `1`, the part will be marked as favorite.
|
||||
* **`manufacturer`**: The manufacturer of the part. Can be a path similar to the category field.
|
||||
* **`manufacturer_product_number`** or **`mpn`**: The manufacturer product number of the part.
|
||||
* **`manufacturer_product_url`: The URL to the product page of the manufacturer of the part.
|
||||
* **`manufacturing_status`**: The manufacturing status of the part, must be one of the following values: `announced`, `active`, `nrfnd`, `eol`, `discontinued` or left empty.
|
||||
* **`needs_review`** or **`needs_review`**: If this is set to `1`, the part will be marked as "needs review".
|
||||
* **`tags`**: A comma separated list of tags for the part.
|
||||
* **`mass`**: The mass of the part in grams.
|
||||
* **`ipn`**: The IPN (Item Part Number) of the part.
|
||||
* **`minamount`**: The minimum amount of the part which should be in stock.
|
||||
* **`partUnit`**: The measurement unit of the part to use. Can be a path similar to the category field.
|
||||
|
||||
With the following fields you can specify storage locations and amount / quantiy in stock of the part. An PartLot will be created automatically from the data and assigned to the part. The following fields are helpers for an easy import for parts at one storage location. If you need to create a Part with multiple PartLots you have to use JSON format (or CSV) with nested objects:
|
||||
|
||||
**`storage_location`** or **`storelocation`**: The storage location of the part. Can be a path similar to the category field.
|
||||
**`amount`**, **`quantity`** or **`instock`**: The amount of the part in stock. If this value is not set, the part lot will be marked with "unknown amount"
|
||||
|
||||
The following fields can be used to specify the supplier/distributor, supplier product number and the price of the part. This is only possible for a single supplier/distributor and price with this fields. If you need to specify multiple suppliers/distributors or prices, you have to use JSON format (or CSV) with nested objects.
|
||||
**Please note that the supplier fields is required, if you want to import prices or supplier product numbers.**. If the supplier is not specified, the price and supplier product number fields will be ignored:
|
||||
|
||||
* **`supplier`**: The supplier of the part. Can be a path similar to the category field.
|
||||
* **`supplier_product_number`** or **`supplier_part_number`** or * **`spn`**: The supplier product number of the part.
|
||||
* **`price`**: The price of the part in the base currency of the database (by default euro).
|
||||
|
||||
#### Example data
|
||||
Here you can find some example data for the import of parts, you can use it as a template for your own import (especially the CSV file).
|
||||
|
||||
* [Part import CSV example]({% link assets/usage/import_export/part_import_example.csv %}) with all possible fields
|
||||
|
||||
## Export
|
||||
|
||||
By default every user, who can read the datastructure, can also export the data of this datastructure, as this does not give the user any additional information.
|
||||
|
||||
### Exporting data structures (categories, manufacturers, etc.)
|
||||
You can export data structures (like categories, manufacturers, etc.) in the respective edit page (e.g. Tools Panel -> Edit -> Category).
|
||||
If you select a certain datastructure from your list, you can export it (and optionally all sub-datastructures) in the "Export" tab.
|
||||
If you want to export all datastructures of a certain type (e.g. all categories in your database), you can select the "Export all" function in the "Import / Export" tab of the "new element" page.
|
||||
|
||||
You can select between the following export formats:
|
||||
* **CSV** (Comma Separated Values): A semicolon separated list of values, where every line represents an element. This format can be imported into Excel or LibreOffice Calc and is easy to work with. However it does not support nested datastructures or sub data (like parameters, attachments, etc.), very well (many columns are generated, as every possible sub data is exported as a separate column).
|
||||
* **JSON** (JavaScript Object Notation): A text-based format, which is easy to work with programming laguages. It supports nested datastructures and sub data (like parameters, attachments, etc.) very well. However it is not easy to work with in Excel or LibreOffice Calc and you maybe need to write some code to work with the exported data efficiently.
|
||||
* **YAML** (Yet another Markup Language): Very similar to JSON
|
||||
* **XML** (Extensible Markup Language): Good support with nested datastructures. Similar usecase as JSON and YAML.
|
||||
|
||||
Also you can select between the following export levels:
|
||||
* **Simple**: This will only export very basic information about the name (like the name, or description for parts)
|
||||
* **Extended**: This will export all commonly used information about this datastructure (like notes, options, etc)
|
||||
* **Full**: This will export all available information about this datastructure (like all parameters, attachments)
|
||||
|
||||
Please note that the level will also be applied to all sub data or children elements. So if you select "Full" for a part, all the associated categories, manufacturers, footprints, etc. will also be exported with all available information, this can lead to very large export files.
|
||||
|
||||
### Exporting parts
|
||||
You can export parts in all part tables. Select the parts you want via the checkbox in the table line and select the export format and level in the appearing menu.
|
||||
|
||||
See the section about exporting datastructures for more information about the export formats and levels.
|
||||
142
docs/usage/information_provider_system.md
Normal file
142
docs/usage/information_provider_system.md
Normal file
@@ -0,0 +1,142 @@
|
||||
---
|
||||
title: Information provider system
|
||||
layout: default
|
||||
parent: Usage
|
||||
---
|
||||
|
||||
# Information provider system
|
||||
|
||||
Part-DB can create parts based on information from external sources: For example with the right setup you can just search for a part number
|
||||
and Part-DB will query selected distributors and manufacturers for the part and create a part with the information it found.
|
||||
This way your Part-DB parts automatically get datasheet links, prices, parameters and more, with just a few clicks.
|
||||
|
||||
## Usage
|
||||
|
||||
Before you can use the information provider system, you have to configure at least one information provider, which act as data source.
|
||||
See below for a list of available information providers and available configuration options.
|
||||
For many providers it is enough, to setup the API keys in the env configuration, some require an additional OAuth connection.
|
||||
You can list all enabled information providers in the browser at `https://your-partdb-instance.tld/tools/info_providers/providers` (you need the right permission for it, see below).
|
||||
|
||||
To use the information provider system, your user need to have the right permissions. Go to the permission management page of
|
||||
a user or a group and assign the permissions of the "Info providers" group in the "Miscellaneous" tab.
|
||||
|
||||
If you have the required permission you will find in the sidebar in the "Tools" section the entry "Create part from info provider".
|
||||
Click this and you will land on a search page. Enter the part number you want to search for and select the information providers you want to use.
|
||||
|
||||
After you click Search, you will be presented with the results and can select the result that fits best.
|
||||
With a click on the blue plus button, you will be redirected to the part creation page with the information already filled in.
|
||||
|
||||

|
||||
|
||||
## Alternative names
|
||||
|
||||
Part-DB tries to automatically find existing elements from your database for the information it got from the providers for fields like manufacturer, footprint, etc.
|
||||
For this it searches for a element with the same name (case-insensitive) as the information it got from the provider. So e.g. if the provider returns "EXAMPLE CORP" as manufacturer,
|
||||
Part-DB will automatically select the element with the name "Example Corp" from your database.
|
||||
|
||||
As the names of these fields differ from provider to provider (and maybe not even normalized for the same provider), you
|
||||
can define multiple alternative names for an element (on their editing page).
|
||||
For example if define a manufacturer "Example Corp" with the alternative names "Example Corp.", "Example Corp", "Example Corp. Inc." and "Example Corporation",
|
||||
then the provider can return any of these names and Part-DB will still automatically select the right element.
|
||||
|
||||
If Part-DB finds no matching element, it will automatically create a new one, when you do not change the value before saving.
|
||||
|
||||
## Attachment types
|
||||
|
||||
The information provider system uses attachment types to differentiate between datasheets and image attachments.
|
||||
For this it will create a "Datasheet" and "Image" attachment type on the first run. You can change the names of these
|
||||
types in the attachment type settings (as long as you keep the "Datasheet"/"Image" in the alternative names field).
|
||||
|
||||
If you already have attachment types for images and datasheets and want the information provider system to use them, you can
|
||||
add the alternative names "Datasheet" and "Image" to the alternative names field of the attachment types.
|
||||
|
||||
## Data providers
|
||||
|
||||
The system tries to be as flexible as possible, so many different information sources can be used.
|
||||
Each information source is called am "info provider" and handles the communication with the external source.
|
||||
The providers are just a driver which handles the communication with the different external sources and converts them into a common format Part-DB understands.
|
||||
That way it is pretty easy to create new providers as they just need to do very little work.
|
||||
|
||||
Normally the providers utilize an API of a service, and you need to create a account at the provider and get an API key.
|
||||
Also there are limits on how many requests you can do per day or months, depending on the provider and your contract with them.
|
||||
|
||||
The following providers are currently available and shipped with Part-DB:
|
||||
|
||||
(All trademarks are property of their respective owners. Part-DB is not affiliated with any of the companies.)
|
||||
|
||||
### Ocotpart
|
||||
The Octopart provider uses the [Octopart / Nexar API](https://nexar.com/api) to search for parts and getting informations.
|
||||
To use it you have to create an account at Nexar and create a new application on the [Nexar Portal](https://portal.nexar.com/).
|
||||
The name does not matter, but it is important that the application has access to the "Supply" scope.
|
||||
In the Authorization tab, you will find the client ID and client secret, which you have to enter in the Part-DB env configuration (see below).
|
||||
|
||||
Please note that the Nexar API in the free plan is limited to 1000 results per month.
|
||||
That means if you search for a keyword and results in 10 parts, then 10 will be substracted from your monthly limit. You can see your current usage on the Nexar portal.
|
||||
Part-DB caches the search results internally, so if you have searched for a part before, it will not count against your monthly limit again, when you create it from the search results.
|
||||
|
||||
Following env configuration options are available:
|
||||
|
||||
* `PROVIDER_OCTOPART_CLIENT_ID`: The client ID you got from Nexar (mandatory)
|
||||
* `PROVIDER_OCTOPART_SECRET`: The client secret you got from Nexar (mandatory)
|
||||
* `PROVIDER_OCTOPART_CURRENCY`: The currency you want to get prices in if available (optional, 3 letter ISO-code, default: `EUR`). If an offer is only available in a certain currency,
|
||||
Part-DB will save the prices in their native currency, and you can use Part-DB currency conversion feature to convert it to your preferred currency.
|
||||
* `PROVIDER_OCOTPART_COUNTRY`: The country you want to get prices in if available (optional, 2 letter ISO-code, default: `DE`). To get correct prices, you have to set this and the currency setting to the correct value.
|
||||
* `PROVIDER_OCTOPART_SEARCH_LIMIT`: The maximum number of results to return per search (optional, default: `10`). This affects how quickly your monthly limit is used up.
|
||||
* `PROVIDER_OCTOPART_ONLY_AUTHORIZED_SELLERS`: If set to `true`, only offers from [authorized sellers](https://octopart.com/authorized) will be returned (optional, default: `false`).
|
||||
|
||||
**Attention**: If you change the octopart clientID after you have already used the provider, you have to remove the OAuth token in the Part-DB database. Remove the entry in the table `oauth_tokens` with the name `ip_octopart_oauth`.
|
||||
|
||||
### Digi-Key
|
||||
The Digi-Key provider uses the [Digi-Key API](https://developer.digikey.com/) to search for parts and getting shopping information from [Digi-Key](https://www.digikey.com/).
|
||||
To use it you have to create an account at Digi-Key and get an API key on the [Digi-Key API page](https://developer.digikey.com/).
|
||||
You must create an organization there and create a "Production app". Most settings are not important, you just have to grant access to the "Product Information" API.
|
||||
You will get an Client ID and a Client Secret, which you have to enter in the Part-DB env configuration (see below).
|
||||
|
||||
Following env configuration options are available:
|
||||
* `PROVIDER_DIGIKEY_CLIENT_ID`: The client ID you got from Digi-Key (mandatory)
|
||||
* `PROVIDER_DIGIKEY_SECRET`: The client secret you got from Digi-Key (mandatory)
|
||||
* `PROVIDER_DIGIKEY_CURRENCY`: The currency you want to get prices in (optional, default: `EUR`)
|
||||
* `PROVIDER_DIGIKEY_LANGUAGE`: The language you want to get the descriptions in (optional, default: `en`)
|
||||
* `PROVIDER_DIGIKEY_COUNTRY`: The country you want to get the prices for (optional, default: `DE`)
|
||||
|
||||
The Digi-Key provider needs an additional OAuth connection. To do this, go to the information provider list (`https://your-partdb-instance.tld/tools/info_providers/providers`),
|
||||
go the Digi-Key provider (in the disabled page) and click on the "Connect OAuth" button. You will be redirected to Digi-Key, where you have to login and grant access to the app.
|
||||
To do this your user needs the "Manage OAuth tokens" permission from the "System" section in the "System" tab.
|
||||
The OAuth connection should only be needed once, but if you have any problems with the provider, just click the button again, to establish a new connection.
|
||||
|
||||
### TME
|
||||
The TME provider use the API of [TME](https://www.tme.eu/) to search for parts and getting shopping information from them.
|
||||
To use it you have to create an account at TME and get an API key on the [TME API page](https://developers.tme.eu/en/).
|
||||
You have to generate a new anonymous key there and enter the key and secret in the Part-DB env configuration (see below).
|
||||
|
||||
Following env configuration options are available:
|
||||
* `PROVIDER_TME_KEY`: The API key you got from TME (mandatory)
|
||||
* `PROVIDER_TME_SECRET`: The API secret you got from TME (mandatory)
|
||||
* `PROVIDER_TME_CURRENCY`: The currency you want to get prices in (optional, default: `EUR`)
|
||||
* `PROVIDER_TME_LANGUAGE`: The language you want to get the descriptions in (`en`, `de` and `pl`) (optional, default: `en`)
|
||||
* `PROVIDER_TME_COUNTRY`: The country you want to get the prices for (optional, default: `DE`)
|
||||
* `PROVIDER_TME_GET_GROSS_PRICES`: If this is set to `1` the prices will be gross prices (including tax), otherwise net prices (optional, default: `0`)
|
||||
|
||||
### Farnell / Element14 / Newark
|
||||
The Farnell provider uses the [Farnell API](https://partner.element14.com/) to search for parts and getting shopping information from [Farnell](https://www.farnell.com/).
|
||||
You have to create an account at Farnell and get an API key on the [Farnell API page](https://partner.element14.com/).
|
||||
Register a new application there (settings does not matter, as long as you select the "Product Search API") and you will get an API key.
|
||||
|
||||
Following env configuration options are available:
|
||||
* `PROVIDER_ELEMENT14_KEY`: The API key you got from Farnell (mandatory)
|
||||
* `PROVIDER_ELEMENT14_STORE_ID`: The store ID you want to use. This decides the language of results, currency and country of prices (optional, default: `de.farnell.com`, see [here](https://partner.element14.com/docs/Product_Search_API_REST__Description) for availailable values)
|
||||
|
||||
|
||||
### Custom provider
|
||||
To create a custom provider, you have to create a new class implementing the `InfoProviderInterface` interface. As long as it is a valid Symfony service, it will be automatically loaded and can be used.
|
||||
Besides some metadata functions, you have to implement the `searchByKeyword()` and `getDetails()` functions, which do the actual API requests and return the information to Part-DB.
|
||||
See the existing providers for examples.
|
||||
If you created a new provider, feel free to create a pull request to add it to the Part-DB core.
|
||||
|
||||
## Result caching
|
||||
To reduce the number of API calls against the providers, the results are cached:
|
||||
* The search results (exact search term) are cached for 7 days
|
||||
* The product details are cached for 4 days
|
||||
|
||||
If you need a fresh result, you can clear the cache by running `php .\bin\console cache:pool:clear info_provider.cache` on the command line.
|
||||
The default `php bin/console cache:clear` also clears the result cache, as it clears all caches.
|
||||
119
docs/usage/keybindings.md
Normal file
119
docs/usage/keybindings.md
Normal file
@@ -0,0 +1,119 @@
|
||||
---
|
||||
title: Keybindings
|
||||
layout: default
|
||||
parent: Usage
|
||||
---
|
||||
|
||||
# Keybindings
|
||||
|
||||
This page lists all the keybindings of Part-DB. Currently, there are only the special character keybindings.
|
||||
|
||||
## Special characters
|
||||
Using the keybindings below (Alt + key) you can insert special characters into the text fields of Part-DB. This works on all text and search fields in Part-DB.
|
||||
|
||||
### Greek letters
|
||||
|
||||
| Key | Character |
|
||||
|---------------------|---------------------|
|
||||
| **Alt + a** | α (Alpha) |
|
||||
| **Alt + Shift + A** | Α (Alpha uppercase) |
|
||||
| **Alt + b** | β (Beta) |
|
||||
| **Alt + Shift + B** | Β (Beta uppercase) |
|
||||
| **Alt + g** | γ (Gamma) |
|
||||
| **Alt + Shift + G** | Γ (Gamma uppercase) |
|
||||
| **Alt + d** | δ (Delta) |
|
||||
| **Alt + Shift + D** | Δ (Delta uppercase) |
|
||||
| **Alt + e** | ε (Epsilon) |
|
||||
| **Alt + Shift + E** | Ε (Epsilon uppercase) |
|
||||
| **Alt + z** | ζ (Zeta) |
|
||||
| **Alt + Shift + Z** | Ζ (Zeta uppercase) |
|
||||
| **Alt + h** | η (Eta) |
|
||||
| **Alt + Shift + H** | Η (Eta uppercase) |
|
||||
| **Alt + q** | θ (Theta) |
|
||||
| **Alt + Shift + Q** | Θ (Theta uppercase) |
|
||||
| **Alt + i** | ι (Iota) |
|
||||
| **Alt + Shift + I** | Ι (Iota uppercase) |
|
||||
| **Alt + k** | κ (Kappa) |
|
||||
| **Alt + Shift + K** | Κ (Kappa uppercase) |
|
||||
| **Alt + l** | λ (Lambda) |
|
||||
| **Alt + Shift + L** | Λ (Lambda uppercase) |
|
||||
| **Alt + m** | μ (Mu) |
|
||||
| **Alt + Shift + M** | Μ (Mu uppercase) |
|
||||
| **Alt + n** | ν (Nu) |
|
||||
| **Alt + Shift + N** | Ν (Nu uppercase) |
|
||||
| **Alt + x** | ξ (Xi) |
|
||||
| **Alt + Shift + x** | Ξ (Xi uppercase) |
|
||||
| **Alt + o** | ο (Omicron) |
|
||||
| **Alt + Shift + O** | Ο (Omicron uppercase) |
|
||||
| **Alt + p** | π (Pi) |
|
||||
| **Alt + Shift + P** | Π (Pi uppercase) |
|
||||
| **Alt + r** | ρ (Rho) |
|
||||
| **Alt + Shift + R** | Ρ (Rho uppercase) |
|
||||
| **Alt + s** | σ (Sigma) |
|
||||
| **Alt + Shift + S** | Σ (Sigma uppercase) |
|
||||
| **Alt + t** | τ (Tau) |
|
||||
| **Alt + Shift + T** | Τ (Tau uppercase) |
|
||||
| **Alt + u** | υ (Upsilon) |
|
||||
| **Alt + Shift + U** | Υ (Upsilon uppercase) |
|
||||
| **Alt + f** | φ (Phi) |
|
||||
| **Alt + Shift + F** | Φ (Phi uppercase) |
|
||||
| **Alt + y** | ψ (Psi) |
|
||||
| **Alt + Shift + Y** | Ψ (Psi uppercase) |
|
||||
| **Alt + c** | χ (Chi) |
|
||||
| **Alt + Shift + C** | Χ (Chi uppercase) |
|
||||
| **Alt + w** | ω (Omega) |
|
||||
| **Alt + Shift + W** | Ω (Omega uppercase) |
|
||||
|
||||
### Mathematical symbols
|
||||
|
||||
| Key | Character |
|
||||
|----------------------|-------------------------------------------|
|
||||
| **Alt + 1** | ∑ (Sum symbol) |
|
||||
| **Alt + Shift + 1** | ∏ (Product symbol) |
|
||||
| **Alt + 2** | ∫ (Integral symbol) |
|
||||
| **Alt + Shift + 2** | ∂ (Partial derivation) |
|
||||
| **Alt + 3** | ≤ (Less or equal symbol) |
|
||||
| **Alt + Shift + 3** | ≥ (Greater or equal symbol) |
|
||||
| **Alt + 4** | ∞ (Infinity symbol) |
|
||||
| **Alt + Shift + 4** | ∅ (Empty set symbol) |
|
||||
| **Alt + 5** | ≈ (Approximatley) |
|
||||
| **Alt + Shift + 5** | ≠ (Not equal symbol) |
|
||||
| **Alt + 6** | ∈ (Element of) |
|
||||
| **Alt + Shift + 6** | ∉ (Not element of) |
|
||||
| **Alt + 7** | ∨ (Logical or) |
|
||||
| **Alt + Shift + 7** | ∧ (Logical and) |
|
||||
| **Alt + 8** | ∠ (Angle symbol) |
|
||||
| **Alt + Shift + 8** | ∝ (Proportional to) |
|
||||
| **Alt + 9** | √ (Square root) |
|
||||
| **Alt + Shift + 9** | ∛ (Cube root) |
|
||||
| **Alt + 0** | ± (Plus minus) |
|
||||
| **Alt + Shift + 0** | ∓ (Minus plus) |
|
||||
|
||||
### Currency symbols
|
||||
|
||||
Please not the following keybindings are bound to a specific keycode. The key character is not the same on all keyboards.
|
||||
It is given here for a US keyboard layout.
|
||||
|
||||
For a German keyboard layout, replace ; with ö, and ' with ä.
|
||||
|
||||
| Key | Character |
|
||||
|---------------------------------|---------------------------|
|
||||
| **Alt + ;** (code 192) | € (Euro currency symbol) |
|
||||
| **Alt + Shift + ;** (code 192) | £ (Pound currency symbol) |
|
||||
| **Alt + '** (code 222) | ¥ (Yen currency symbol) |
|
||||
| **Alt + Shift + '** (code 222) | $ (Dollar currency symbol) |
|
||||
|
||||
|
||||
### Others
|
||||
|
||||
Please not the following keybindings are bound to a specific keycode. The key character is not the same on all keyboards.
|
||||
It is given here for a US keyboard layout.
|
||||
|
||||
For a German keyboard layout, replace `[` with `0`, and `]` with `´`.
|
||||
|
||||
| Key | Character |
|
||||
|--------------------------------|--------------------|
|
||||
| **Alt + [** (code 219) | © (Copyright char) |
|
||||
| **Alt + Shift + [** (code 219) | (Registered char) |
|
||||
| **Alt + ]** (code 221) | ™ (Trademark char) |
|
||||
| **Alt + Shift + ]** (code 221) | (Degree char) |
|
||||
@@ -92,4 +92,27 @@ The following variables are in injected into Twig and can be accessed using `{%
|
||||
| `{% raw %}{{ element }}{% endraw %}` | The target element, selected in label dialog |
|
||||
| `{% raw %}{{ user }}{% endraw %}` | The current logged in user. Null if you are not logged in |
|
||||
| `{% raw %}{{ install_title }}{% endraw %}` | The name of the current Part-DB instance (similar to [[INSTALL_NAME]] placeholder). |
|
||||
| `{% raw %}{{ page }}{% endraw %}` | The page number (the nth-element for which the label is generated |
|
||||
| `{% raw %}{{ page }}{% endraw %}` | The page number (the nth-element for which the label is generated |
|
||||
|
||||
|
||||
## Use custom fonts for PDF labels
|
||||
You can use your own fonts for label generation. To do this, put the TTF files of the fonts you want to use into the `assets/fonts/dompdf` folder.
|
||||
The filename will be used as name for the font family and you can use a `_bold` (or `_b`), `_italic` (or `_i`) or `_bold_italic` (or `_bi`) suffix to define
|
||||
different styles of the font. So for example, if you copy the file `myfont.ttf` and `myfont_bold.ttf` into the `assets/fonts/dompdf` folder, you can use the font family `myfont` with regular and bold style.
|
||||
Afterwards regenerate cache with `php bin/console cache:clear`, so the new fonts will be available for label generation.
|
||||
|
||||
The fonts will not be availble from the UI directly, you have to use it in the HTML directly either by defining a `style="font-family: 'myfont';"` attribute on the HTML element or by using a CSS class.
|
||||
You can define the font globally for the label, by adding following statement to the "Additional styles (CSS)" option in the label generator settings:
|
||||
```css
|
||||
* {
|
||||
font-family: 'myfont';
|
||||
}
|
||||
```
|
||||
|
||||
## Non-latin characters in PDF labels
|
||||
The default used font (DejaVu) does not support all characters. Especially characters from non-latin languages like Chinese, Japanese, Korean, Arabic, Hebrew, Cyrillic, etc. are not supported.
|
||||
For this we use [Unifont](http://unifoundry.com/unifont.html) as fallback font. This font supports all (or most) unicode characters, but is not as beautiful as DejaVu.
|
||||
|
||||
If you want to use a different (more beautiful) font, you can use the [custom fonts](#use-custom-fonts-for-pdf-labels) feature.
|
||||
There is the [Noto](https://www.google.com/get/noto/) font family from Google, which supports a lot of languages and is available in different styles (regular, bold, italic, bold-italic).
|
||||
For example you can use [Noto CJK](https://github.com/notofonts/noto-cjk) for more beautful Chinese, Japanese and Korean characters.
|
||||
@@ -62,4 +62,21 @@ by calling the `php bin/console partdb:currencies:update-exchange-rates`.
|
||||
If you call this command regularly (e.g. with a cronjob), you can keep the exchange rates up-to-date.
|
||||
|
||||
Please note that if you use a base currency, which is not the Euro, you have to configure an exchange rate API, as the
|
||||
free API used by default only supports the Euro as base currency.
|
||||
free API used by default only supports the Euro as base currency.
|
||||
|
||||
## Enforce log comments
|
||||
On almost any editing operation it is possible to add a comment describing, what or why you changed something.
|
||||
This comment will be written to change log and can be viewed later.
|
||||
If you want to enforce your users to add comments to certain operations, you can do this by setting the `ENFORCE_CHANGE_COMMENTS_FOR` option.
|
||||
See the configuration reference for more information.
|
||||
|
||||
## Personal stocks and stock locations
|
||||
For makerspaces and universities with a lot of users, where each user can have his own stock, which only he should be able to access, you can assign
|
||||
the user as "owner" of a part lot. This way, only him is allowed to add or remove parts from this lot.
|
||||
|
||||
## Update notfications
|
||||
Part-DB can show you a notification that there is a newer version than currently installed available. The notification will be shown on the homepage and the server info page.
|
||||
It is only be shown to users which has the `Show available Part-DB updates` permission.
|
||||
|
||||
For the notification to work, Part-DB queries the GitHub API every 2 days to check for new releases. No data is sent to GitHub besides the metadata required for the connection (so the public IP address of your computer running Part-DB).
|
||||
If you don't want Part-DB to query the GitHub API, or if your server can not reach the internet, you can disable the update notifications by setting the `CHECK_FOR_UPDATES` option to `false`.
|
||||
@@ -69,6 +69,12 @@ final class Version20190902140506 extends AbstractMultiPlatformMigration
|
||||
//For attachments
|
||||
$this->addSql('DELETE FROM `attachements` WHERE attachements.class_name = "Part" AND (SELECT COUNT(parts.id) FROM parts WHERE parts.id = attachements.element_id) = 0;');
|
||||
|
||||
//Add perms_labels column to groups table if not existing (it was not created in certain legacy versions)
|
||||
//This prevents the migration failing (see https://github.com/Part-DB/Part-DB-server/issues/366 and https://github.com/Part-DB/Part-DB-server/issues/67)
|
||||
if (!$this->doesColumnExist('groups', 'perms_labels')) {
|
||||
$this->addSql('ALTER TABLE `groups` ADD `perms_labels` SMALLINT NOT NULL AFTER `perms_tools`');
|
||||
}
|
||||
|
||||
/**************************************************************************************************************
|
||||
* Doctrine generated SQL
|
||||
**************************************************************************************************************/
|
||||
@@ -100,11 +106,17 @@ final class Version20190902140506 extends AbstractMultiPlatformMigration
|
||||
$this->addSql('ALTER TABLE part_lots ADD CONSTRAINT FK_EBC8F9435D8F4B37 FOREIGN KEY (id_store_location) REFERENCES `storelocations` (id)');
|
||||
$this->addSql('ALTER TABLE part_lots ADD CONSTRAINT FK_EBC8F943C22F6CC4 FOREIGN KEY (id_part) REFERENCES `parts` (id) ON DELETE CASCADE');
|
||||
$this->addSql('ALTER TABLE parts DROP INDEX parts_order_orderdetails_id_k, ADD UNIQUE INDEX UNIQ_6940A7FE81081E9B (order_orderdetails_id)');
|
||||
$this->addSql('ALTER TABLE parts DROP FOREIGN KEY parts_id_storelocation_fk');
|
||||
if ($this->doesFKExists('parts', 'parts_id_storelocation_fk')) {
|
||||
$this->addSql('ALTER TABLE parts DROP FOREIGN KEY parts_id_storelocation_fk');
|
||||
}
|
||||
$this->addSql('DROP INDEX favorite ON parts');
|
||||
$this->addSql('DROP INDEX parts_id_storelocation_k ON parts');
|
||||
$this->addSql('ALTER TABLE parts DROP FOREIGN KEY parts_id_footprint_fk');
|
||||
$this->addSql('ALTER TABLE parts DROP FOREIGN KEY parts_id_manufacturer_fk');
|
||||
if ($this->doesFKExists('parts', 'parts_id_footprint_fk')) {
|
||||
$this->addSql('ALTER TABLE parts DROP FOREIGN KEY parts_id_footprint_fk');
|
||||
}
|
||||
if ($this->doesFKExists('parts', 'parts_id_manufacturer_fk')) {
|
||||
$this->addSql('ALTER TABLE parts DROP FOREIGN KEY parts_id_manufacturer_fk');
|
||||
}
|
||||
$this->addSql('ALTER TABLE parts CHANGE mininstock minamount DOUBLE PRECISION NOT NULL, ADD id_part_unit INT DEFAULT NULL, ADD manufacturer_product_number VARCHAR(255) NOT NULL, ADD manufacturing_status VARCHAR(255) DEFAULT NULL, ADD needs_review TINYINT(1) NOT NULL, ADD tags LONGTEXT NOT NULL, ADD mass DOUBLE PRECISION DEFAULT NULL, DROP instock, CHANGE id_category id_category INT NOT NULL, CHANGE name name VARCHAR(255) NOT NULL, CHANGE order_quantity order_quantity INT NOT NULL, CHANGE manual_order manual_order TINYINT(1) NOT NULL, CHANGE manufacturer_product_url manufacturer_product_url VARCHAR(255) NOT NULL, CHANGE last_modified last_modified DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, CHANGE favorite favorite TINYINT(1) NOT NULL, DROP id_storelocation');
|
||||
$this->addSql('ALTER TABLE parts ADD CONSTRAINT FK_6940A7FE5697F554 FOREIGN KEY (id_category) REFERENCES `categories` (id)');
|
||||
$this->addSql('ALTER TABLE parts ADD CONSTRAINT FK_6940A7FEEBBCC786 FOREIGN KEY (id_master_picture_attachement) REFERENCES `attachments` (id)');
|
||||
@@ -119,39 +131,54 @@ final class Version20190902140506 extends AbstractMultiPlatformMigration
|
||||
$this->addSql('CREATE INDEX IDX_6940A7FE1ECB93AE ON parts (id_manufacturer)');
|
||||
$this->addSql('ALTER TABLE parts ADD CONSTRAINT parts_id_footprint_fk FOREIGN KEY (id_footprint) REFERENCES footprints (id)');
|
||||
$this->addSql('ALTER TABLE parts ADD CONSTRAINT parts_id_manufacturer_fk FOREIGN KEY (id_manufacturer) REFERENCES manufacturers (id)');
|
||||
$this->addSql('ALTER TABLE attachment_types DROP FOREIGN KEY attachement_types_parent_id_fk');
|
||||
//We have to use the old table name here, because the if is executed before any sql command added by addSQL is executed (and thus the table name is not changed yet)
|
||||
if ($this->doesFKExists('attachement_types', 'attachement_types_parent_id_fk')) {
|
||||
$this->addSql('ALTER TABLE attachment_types DROP FOREIGN KEY attachement_types_parent_id_fk');
|
||||
}
|
||||
$this->addSql('ALTER TABLE attachment_types ADD filetype_filter LONGTEXT NOT NULL, ADD not_selectable TINYINT(1) NOT NULL, CHANGE name name VARCHAR(255) NOT NULL, CHANGE comment comment LONGTEXT NOT NULL, CHANGE last_modified last_modified DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL');
|
||||
$this->addSql('DROP INDEX attachement_types_parent_id_k ON attachment_types');
|
||||
$this->addSql('CREATE INDEX IDX_EFAED719727ACA70 ON attachment_types (parent_id)');
|
||||
$this->addSql('ALTER TABLE attachment_types ADD CONSTRAINT attachement_types_parent_id_fk FOREIGN KEY (parent_id) REFERENCES attachment_types (id)');
|
||||
$this->addSql('ALTER TABLE categories DROP FOREIGN KEY categories_parent_id_fk');
|
||||
if ($this->doesFKExists('categories', 'categories_parent_id_fk')) {
|
||||
$this->addSql('ALTER TABLE categories DROP FOREIGN KEY categories_parent_id_fk');
|
||||
}
|
||||
$this->addSql('ALTER TABLE categories ADD not_selectable TINYINT(1) NOT NULL, CHANGE name name VARCHAR(255) NOT NULL, CHANGE disable_footprints disable_footprints TINYINT(1) NOT NULL, CHANGE disable_manufacturers disable_manufacturers TINYINT(1) NOT NULL, CHANGE disable_autodatasheets disable_autodatasheets TINYINT(1) NOT NULL, CHANGE disable_properties disable_properties TINYINT(1) NOT NULL, CHANGE comment comment LONGTEXT NOT NULL, CHANGE last_modified last_modified DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL');
|
||||
$this->addSql('DROP INDEX categories_parent_id_k ON categories');
|
||||
$this->addSql('CREATE INDEX IDX_3AF34668727ACA70 ON categories (parent_id)');
|
||||
$this->addSql('ALTER TABLE categories ADD CONSTRAINT categories_parent_id_fk FOREIGN KEY (parent_id) REFERENCES categories (id)');
|
||||
$this->addSql('ALTER TABLE devices DROP FOREIGN KEY devices_parent_id_fk');
|
||||
if ($this->doesFKExists('devices', 'devices_parent_id_fk')) {
|
||||
$this->addSql('ALTER TABLE devices DROP FOREIGN KEY devices_parent_id_fk');
|
||||
}
|
||||
$this->addSql('ALTER TABLE devices ADD not_selectable TINYINT(1) NOT NULL, CHANGE name name VARCHAR(255) NOT NULL, CHANGE order_quantity order_quantity INT NOT NULL, CHANGE order_only_missing_parts order_only_missing_parts TINYINT(1) NOT NULL, CHANGE last_modified last_modified DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, CHANGE comment comment LONGTEXT NOT NULL');
|
||||
$this->addSql('DROP INDEX devices_parent_id_k ON devices');
|
||||
$this->addSql('CREATE INDEX IDX_11074E9A727ACA70 ON devices (parent_id)');
|
||||
$this->addSql('ALTER TABLE devices ADD CONSTRAINT devices_parent_id_fk FOREIGN KEY (parent_id) REFERENCES devices (id)');
|
||||
$this->addSql('ALTER TABLE footprints DROP FOREIGN KEY footprints_parent_id_fk');
|
||||
if ($this->doesFKExists('footprints', 'footprints_parent_id_fk')) {
|
||||
$this->addSql('ALTER TABLE footprints DROP FOREIGN KEY footprints_parent_id_fk');
|
||||
}
|
||||
$this->addSql('ALTER TABLE footprints ADD not_selectable TINYINT(1) NOT NULL, CHANGE name name VARCHAR(255) NOT NULL, CHANGE comment comment LONGTEXT NOT NULL, CHANGE last_modified last_modified DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL');
|
||||
$this->addSql('DROP INDEX footprints_parent_id_k ON footprints');
|
||||
$this->addSql('CREATE INDEX IDX_A34D68A2727ACA70 ON footprints (parent_id)');
|
||||
$this->addSql('ALTER TABLE footprints ADD CONSTRAINT footprints_parent_id_fk FOREIGN KEY (parent_id) REFERENCES footprints (id)');
|
||||
$this->addSql('ALTER TABLE manufacturers DROP FOREIGN KEY manufacturers_parent_id_fk');
|
||||
if ($this->doesFKExists('manufacturers', 'manufacturers_parent_id_fk')) {
|
||||
$this->addSql('ALTER TABLE manufacturers DROP FOREIGN KEY manufacturers_parent_id_fk');
|
||||
}
|
||||
$this->addSql('ALTER TABLE manufacturers ADD not_selectable TINYINT(1) NOT NULL, CHANGE name name VARCHAR(255) NOT NULL, CHANGE address address VARCHAR(255) NOT NULL, CHANGE phone_number phone_number VARCHAR(255) NOT NULL, CHANGE fax_number fax_number VARCHAR(255) NOT NULL, CHANGE email_address email_address VARCHAR(255) NOT NULL, CHANGE website website VARCHAR(255) NOT NULL, CHANGE auto_product_url auto_product_url VARCHAR(255) NOT NULL, CHANGE comment comment LONGTEXT NOT NULL, CHANGE last_modified last_modified DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL');
|
||||
$this->addSql('DROP INDEX manufacturers_parent_id_k ON manufacturers');
|
||||
$this->addSql('CREATE INDEX IDX_94565B12727ACA70 ON manufacturers (parent_id)');
|
||||
$this->addSql('ALTER TABLE manufacturers ADD CONSTRAINT manufacturers_parent_id_fk FOREIGN KEY (parent_id) REFERENCES manufacturers (id)');
|
||||
$this->addSql('ALTER TABLE storelocations DROP FOREIGN KEY storelocations_parent_id_fk');
|
||||
if ($this->doesFKExists('storelocations', 'storelocations_parent_id_fk')) {
|
||||
$this->addSql('ALTER TABLE storelocations DROP FOREIGN KEY storelocations_parent_id_fk');
|
||||
}
|
||||
$this->addSql('ALTER TABLE storelocations ADD storage_type_id INT DEFAULT NULL, ADD only_single_part TINYINT(1) NOT NULL, ADD limit_to_existing_parts TINYINT(1) NOT NULL, ADD not_selectable TINYINT(1) NOT NULL, CHANGE name name VARCHAR(255) NOT NULL, CHANGE is_full is_full TINYINT(1) NOT NULL, CHANGE comment comment LONGTEXT NOT NULL, CHANGE last_modified last_modified DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL');
|
||||
$this->addSql('ALTER TABLE storelocations ADD CONSTRAINT FK_7517020B270BFF1 FOREIGN KEY (storage_type_id) REFERENCES `measurement_units` (id)');
|
||||
$this->addSql('CREATE INDEX IDX_7517020B270BFF1 ON storelocations (storage_type_id)');
|
||||
$this->addSql('DROP INDEX storelocations_parent_id_k ON storelocations');
|
||||
$this->addSql('CREATE INDEX IDX_7517020727ACA70 ON storelocations (parent_id)');
|
||||
$this->addSql('ALTER TABLE storelocations ADD CONSTRAINT storelocations_parent_id_fk FOREIGN KEY (parent_id) REFERENCES storelocations (id)');
|
||||
$this->addSql('ALTER TABLE suppliers DROP FOREIGN KEY suppliers_parent_id_fk');
|
||||
if ($this->doesFKExists('suppliers', 'suppliers_parent_id_fk')) {
|
||||
$this->addSql('ALTER TABLE suppliers DROP FOREIGN KEY suppliers_parent_id_fk');
|
||||
}
|
||||
$this->addSql('ALTER TABLE suppliers ADD default_currency_id INT DEFAULT NULL, ADD shipping_costs NUMERIC(11, 5) DEFAULT NULL, ADD not_selectable TINYINT(1) NOT NULL, CHANGE name name VARCHAR(255) NOT NULL, CHANGE address address VARCHAR(255) NOT NULL, CHANGE phone_number phone_number VARCHAR(255) NOT NULL, CHANGE fax_number fax_number VARCHAR(255) NOT NULL, CHANGE email_address email_address VARCHAR(255) NOT NULL, CHANGE website website VARCHAR(255) NOT NULL, CHANGE auto_product_url auto_product_url VARCHAR(255) NOT NULL, CHANGE comment comment LONGTEXT NOT NULL, CHANGE last_modified last_modified DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL');
|
||||
$this->addSql('ALTER TABLE suppliers ADD CONSTRAINT FK_AC28B95CECD792C0 FOREIGN KEY (default_currency_id) REFERENCES currencies (id)');
|
||||
$this->addSql('CREATE INDEX IDX_AC28B95CECD792C0 ON suppliers (default_currency_id)');
|
||||
@@ -159,7 +186,10 @@ final class Version20190902140506 extends AbstractMultiPlatformMigration
|
||||
$this->addSql('CREATE INDEX IDX_AC28B95C727ACA70 ON suppliers (parent_id)');
|
||||
$this->addSql('ALTER TABLE suppliers ADD CONSTRAINT suppliers_parent_id_fk FOREIGN KEY (parent_id) REFERENCES suppliers (id)');
|
||||
$this->addSql('DROP INDEX attachements_class_name_k ON attachments');
|
||||
$this->addSql('ALTER TABLE attachments DROP FOREIGN KEY attachements_type_id_fk');
|
||||
//We have to use the old table name here, because the if is executed before any sql command added by addSQL is executed (and thus the table name is not changed yet)
|
||||
if ($this->doesFKExists('attachements', 'attachements_type_id_fk')) {
|
||||
$this->addSql('ALTER TABLE attachments DROP FOREIGN KEY attachements_type_id_fk');
|
||||
}
|
||||
$this->addSql('ALTER TABLE attachments ADD datetime_added DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, CHANGE type_id type_id INT DEFAULT NULL, CHANGE name name VARCHAR(255) NOT NULL, CHANGE filename filename VARCHAR(255) NOT NULL, CHANGE show_in_table show_in_table TINYINT(1) NOT NULL, CHANGE last_modified last_modified DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL');
|
||||
$this->addSql('ALTER TABLE attachments ADD CONSTRAINT FK_47C4FAD61F1F2A24 FOREIGN KEY (element_id) REFERENCES `parts` (id) ON DELETE CASCADE');
|
||||
$this->addSql('DROP INDEX attachements_type_id_fk ON attachments');
|
||||
@@ -194,10 +224,10 @@ final class Version20190902140506 extends AbstractMultiPlatformMigration
|
||||
$this->addSql('CREATE INDEX IDX_C68C4459398D64AA ON pricedetails (id_currency)');
|
||||
$this->addSql('CREATE INDEX IDX_C68C44594A01DDC7 ON pricedetails (orderdetails_id)');
|
||||
$this->addSql('DROP INDEX pricedetails_orderdetails_id_k ON pricedetails');
|
||||
$this->addSql('DROP INDEX name ON groups');
|
||||
$this->addSql('ALTER TABLE groups ADD not_selectable TINYINT(1) NOT NULL, CHANGE name name VARCHAR(255) NOT NULL, CHANGE comment comment LONGTEXT NOT NULL, CHANGE perms_labels perms_labels INT NOT NULL, CHANGE last_modified last_modified DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL');
|
||||
$this->addSql('ALTER TABLE groups ADD CONSTRAINT FK_F06D3970727ACA70 FOREIGN KEY (parent_id) REFERENCES `groups` (id)');
|
||||
$this->addSql('CREATE INDEX IDX_F06D3970727ACA70 ON groups (parent_id)');
|
||||
$this->addSql('DROP INDEX name ON `groups`');
|
||||
$this->addSql('ALTER TABLE `groups` ADD not_selectable TINYINT(1) NOT NULL, CHANGE name name VARCHAR(255) NOT NULL, CHANGE comment comment LONGTEXT NOT NULL, CHANGE perms_labels perms_labels INT NOT NULL, CHANGE last_modified last_modified DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL');
|
||||
$this->addSql('ALTER TABLE `groups` ADD CONSTRAINT FK_F06D3970727ACA70 FOREIGN KEY (parent_id) REFERENCES `groups` (id)');
|
||||
$this->addSql('CREATE INDEX IDX_F06D3970727ACA70 ON `groups` (parent_id)');
|
||||
|
||||
//Fill empty timestamps with current date
|
||||
$tables = ['attachments', 'attachment_types', 'categories', 'devices', 'footprints', 'manufacturers',
|
||||
@@ -210,6 +240,10 @@ final class Version20190902140506 extends AbstractMultiPlatformMigration
|
||||
|
||||
//Set the dbVersion to a high value, to prevent the old Part-DB versions to upgrade DB!
|
||||
$this->addSql("UPDATE `internal` SET `keyValue` = '99' WHERE `internal`.`keyName` = 'dbVersion'");
|
||||
|
||||
//Migrate theme config to new format
|
||||
$this->addSql('UPDATE users SET users.config_theme = REPLACE(users.config_theme ,".min.css", "") WHERE users.config_theme LIKE "%.min.css"');
|
||||
$this->addSql('UPDATE users SET users.config_theme = REPLACE(users.config_theme ,".css", "") WHERE users.config_theme LIKE "%.css"');
|
||||
}
|
||||
|
||||
public function mySQLDown(Schema $schema): void
|
||||
@@ -335,10 +369,6 @@ final class Version20190902140506 extends AbstractMultiPlatformMigration
|
||||
$this->addSql('ALTER TABLE `users` CHANGE name name VARCHAR(32) NOT NULL COLLATE utf8_general_ci, CHANGE need_pw_change need_pw_change TINYINT(1) DEFAULT \'0\' NOT NULL, CHANGE first_name first_name TINYTEXT DEFAULT NULL COLLATE utf8_general_ci, CHANGE last_name last_name TINYTEXT DEFAULT NULL COLLATE utf8_general_ci, CHANGE department department TINYTEXT DEFAULT NULL COLLATE utf8_general_ci, CHANGE email email TINYTEXT DEFAULT NULL COLLATE utf8_general_ci, CHANGE config_language config_language TINYTEXT DEFAULT NULL COLLATE utf8_general_ci, CHANGE config_timezone config_timezone TINYTEXT DEFAULT NULL COLLATE utf8_general_ci, CHANGE config_theme config_theme TINYTEXT DEFAULT NULL COLLATE utf8_general_ci, CHANGE config_currency config_currency TINYTEXT DEFAULT NULL COLLATE utf8_general_ci, CHANGE last_modified last_modified DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, CHANGE perms_labels perms_labels SMALLINT NOT NULL');
|
||||
$this->addSql('DROP INDEX uniq_1483a5e95e237e06 ON `users`');
|
||||
$this->addSql('CREATE UNIQUE INDEX name ON `users` (name)');
|
||||
|
||||
//Migrate theme config to new format
|
||||
$this->addSql('UPDATE users SET users.config_theme = REPLACE(users.config_theme ,".min.css", "") WHERE users.config_theme LIKE "%.min.css"');
|
||||
$this->addSql('UPDATE users SET users.config_theme = REPLACE(users.config_theme ,".css", "") WHERE users.config_theme LIKE "%.css"');
|
||||
}
|
||||
|
||||
public function sqLiteUp(Schema $schema): void
|
||||
|
||||
@@ -66,8 +66,6 @@ final class Version20190913141126 extends AbstractMultiPlatformMigration
|
||||
';
|
||||
|
||||
$this->addSql($sql);
|
||||
|
||||
$this->printPermissionUpdateMessage();
|
||||
}
|
||||
|
||||
public function mySQLDown(Schema $schema): void
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user