mirror of
https://github.com/Part-DB/Part-DB-server.git
synced 2025-06-21 01:25:55 +02:00
Compare commits
640 commits
Author | SHA1 | Date | |
---|---|---|---|
|
c44535990b | ||
|
b8d5b83eee | ||
|
00da2dedc3 | ||
|
4ce1de079e | ||
|
6b9c125de4 | ||
|
2c4f44e808 | ||
|
2b694731ad | ||
|
7e34535e62 | ||
|
0bb831fe88 | ||
|
42a32ce142 | ||
|
23f58b7bf4 | ||
|
4e9101fded | ||
|
9c700c77a8 | ||
|
cb1f674332 | ||
|
6823d94ffb | ||
|
60ab992360 | ||
|
f9e769a6e3 | ||
|
f802c6c176 | ||
|
dedadf0c10 | ||
|
c8375def1a | ||
|
62ebcde2de | ||
|
594a5779dc | ||
|
c0ef64fb64 | ||
|
48c70c3bb4 | ||
|
68124a340b | ||
|
0b5003fcf6 | ||
|
956ece60af | ||
|
53da45d7d7 | ||
|
57f0432a87 | ||
|
fb535ec6f7 | ||
|
4e1b1a4ffa | ||
|
5b111d80f1 | ||
|
03e1105a8e | ||
|
059a9683db | ||
|
1daf6f01f4 | ||
|
d3b225771c | ||
|
7275db27e7 | ||
|
49ee9131d0 | ||
|
e75e0c4c0b | ||
|
e94d4a7752 | ||
|
95206f427d | ||
|
2d7f88522a | ||
|
f5c17bc7c8 | ||
|
63e222ed40 | ||
|
6963ee3b8d | ||
|
bb5e42bf63 | ||
|
c48f778648 | ||
|
616aad6403 | ||
|
bcc7547d6f | ||
|
5a1a6e9217 | ||
|
eae1fcecab | ||
|
b53989bb9d | ||
|
467d50bd31 | ||
|
1935258978 | ||
|
2b5030c69f | ||
|
6537502696 | ||
|
0ba352ab0b | ||
|
5d3f861728 | ||
|
319b69f6c7 | ||
|
c4ba28e3a0 | ||
|
b38ef8ecea | ||
|
cb0817666d | ||
|
a54c2db9b9 | ||
|
17caf476bf | ||
|
42cb590c75 | ||
|
6fd05e1456 | ||
|
bec45d60e5 | ||
|
019e67a676 | ||
|
f146d88aa5 | ||
|
48be9a8098 | ||
|
29f92d9bd3 | ||
|
ebb977e99f | ||
|
94bcd3d2d3 | ||
|
a9bd4c5606 | ||
|
8d9dde0032 | ||
|
b2d4333fff | ||
|
afd5e2b95b | ||
|
085adf8d71 | ||
|
9b35b60d61 | ||
|
742e57cc5c | ||
|
a5961668fe | ||
|
e7394c165a | ||
|
7be966122f | ||
|
d176b68fd2 | ||
|
1e80be1376 | ||
|
3585b08d4b | ||
|
c51e0eb68f | ||
|
d05c0579a2 | ||
|
5e40519bc5 | ||
|
d13752114c | ||
|
90e1b809fe | ||
|
32b4e6812d | ||
|
a798aa9c24 | ||
|
f1c28b9f46 | ||
|
39bc400376 | ||
|
e287918121 | ||
|
e0bf8e5fbc | ||
|
376c7e7a6f | ||
|
5612a790fb | ||
|
80527e35c3 | ||
|
f592ab6395 | ||
|
d7c741c652 | ||
|
9502f30e1b | ||
|
7286c4bbef | ||
|
a976f97dbb | ||
|
2c9b8c7dea | ||
|
787decf4e2 | ||
|
2fc70b8bdd | ||
|
64491a9772 | ||
|
b724b05de6 | ||
|
d94c4af1be | ||
|
8f0f5a5eb4 | ||
|
edf50a71d1 | ||
|
d0937218b9 | ||
|
3247a97217 | ||
|
edd254ee06 | ||
|
42ecb83155 | ||
|
56f801c058 | ||
|
2d3d05e956 | ||
|
4321e51bf5 | ||
|
be04730906 | ||
|
aa06e1df04 | ||
|
fd7a0156bc | ||
|
1e19ff24ba | ||
|
0f4238291f | ||
|
03a2a10efd | ||
|
04310aa2f8 | ||
|
e8ca11a5cf | ||
|
24137b30a5 | ||
|
4421917333 | ||
|
25c8660c2e | ||
|
190e87390d | ||
|
c9aefdd862 | ||
|
3ad088663f | ||
|
a29e87e5ac | ||
|
de0832bece | ||
|
614697ba84 | ||
|
6bdf3d891a | ||
|
f75704f77c | ||
|
9d09543eb9 | ||
|
a6116398a8 | ||
|
39763b84d5 | ||
|
8502df08fa | ||
|
bf2a776403 | ||
|
052190c69b | ||
|
8826ba6729 | ||
|
39b5240934 | ||
|
ddc1c286d9 | ||
|
22fba37d28 | ||
|
0c627a5636 | ||
|
53dcd24216 | ||
|
4b09a321ad | ||
|
9e85b70c17 | ||
|
9c99217dee | ||
|
afc1dbdd4b | ||
|
20f58fc07d | ||
|
e6b78dd213 | ||
|
63893ffabe | ||
|
c9e519d0b5 | ||
|
273bde90f2 | ||
|
92e4976396 | ||
|
e9efbff912 | ||
|
41089c08f8 | ||
|
9e23e606f8 | ||
|
b3f0fd368a | ||
|
12bd5472e2 | ||
|
ef64779759 | ||
|
b3d8076ddf | ||
|
f775203608 | ||
|
a6083688e4 | ||
|
50689cd4e6 | ||
|
255fcbac1c | ||
|
7f8ffa56e5 | ||
|
9a2a5f30a3 | ||
|
a9f444cbb4 | ||
|
164efb0551 | ||
|
a37b8cbb15 | ||
|
946032a101 | ||
|
a273acbecd | ||
|
0ceee1582e | ||
|
04a0369d56 | ||
|
31a288b44d | ||
|
502dc3aa1c | ||
|
6874d7ca55 | ||
|
da8f669aed | ||
|
0f92a69b03 | ||
|
8faa3251c4 | ||
|
56fc14003c | ||
|
b3499e4ea5 | ||
|
07b1ff9bf5 | ||
|
5bbf24c92e | ||
|
eea8b3e679 | ||
|
e223078af9 | ||
|
b554d0d851 | ||
|
b1ba26e0b9 | ||
|
ca8ad760d7 | ||
|
80129c0a88 | ||
|
7530e62dfa | ||
|
baf8977578 | ||
|
c7bf843312 | ||
|
ce6fee1682 | ||
|
2653fad488 | ||
|
dd54c46a29 | ||
|
724a0e21d3 | ||
|
578277d11f | ||
|
22258e3183 | ||
|
0234463b68 | ||
|
ef412eef92 | ||
|
76ebd22eab | ||
|
5b0ca8e346 | ||
|
0b6b10c27b | ||
|
6225d2c9b3 | ||
|
01fc6524a4 | ||
|
2575e6a160 | ||
|
484ba5ebd7 | ||
|
b42d98e9f8 | ||
|
65b2f045ac | ||
|
5e76451d46 | ||
|
a873ad3316 | ||
|
b1e03f49ee | ||
|
011e23f8e6 | ||
|
646cd8cf22 | ||
|
52ac8a70d5 | ||
|
e020334b73 | ||
|
7698e83f0b | ||
|
dd56f5e0c8 | ||
|
92c32eef74 | ||
|
08770c7dc5 | ||
|
808a94e4df | ||
|
490086d531 | ||
|
2ef3fbb81b | ||
|
7d834ac8d7 | ||
|
15ad0ec9c0 | ||
|
f0b78e8b2c | ||
|
e616faa76f | ||
|
8159f4d8ee | ||
|
021c576468 | ||
|
1b2339a82c | ||
|
2b6bb3f773 | ||
|
abc5c61a06 | ||
|
7145bce605 | ||
|
bb92e5e9ee | ||
|
0c47aa226c | ||
|
76e945bbbd | ||
|
4a6ec2581d | ||
|
3d75bf5f9f | ||
|
c27648b89b | ||
|
ccf67c0662 | ||
|
ca116cae91 | ||
|
a29d933f99 | ||
|
49acf3e0cf | ||
|
234b5abb96 | ||
|
839bcf91d6 | ||
|
58ed57fab7 | ||
|
fa42997733 | ||
|
ac416141d0 | ||
|
c629a85b14 | ||
|
7ccfea208f | ||
|
f3c802bcff | ||
|
574583bd6a | ||
|
84c54d0b25 | ||
|
86d3f87694 | ||
|
ddd7252051 | ||
|
b4e8136618 | ||
|
c2638991f2 | ||
|
8554be9abd | ||
|
87a518703f | ||
|
dd03ca943d | ||
|
6997861811 | ||
|
1cc1530b20 | ||
|
98597fb3aa | ||
|
283a445198 | ||
|
7db44f0ec5 | ||
|
abb5395cae | ||
|
8c8b44baef | ||
|
7366a33fe5 | ||
|
ad02d7e525 | ||
|
b5a0189f29 | ||
|
756152dd68 | ||
|
173a8ee680 | ||
|
b99777cde1 | ||
|
8193e7a68e | ||
|
f18c024daa | ||
|
f6577a8f33 | ||
|
7fc3153dde | ||
|
5231dbd6e7 | ||
|
77671550a7 | ||
|
e231404128 | ||
|
6650e2da3d | ||
|
fd521acaa4 | ||
|
a169623866 | ||
|
21c3c45150 | ||
|
1aee0a91c0 | ||
|
27a28d4adc | ||
|
d6ff22fc44 | ||
|
5ede61118c | ||
|
228549ff51 | ||
|
1ec5cbc301 | ||
|
3011cb8fae | ||
|
ff78c3c9a7 | ||
|
d5980b7620 | ||
|
a8e1171108 | ||
|
19e5d302f4 | ||
|
22e2480feb | ||
|
88ef1788ac | ||
|
a54ce939ca | ||
|
528d0c7a26 | ||
|
c68a647e75 | ||
|
e0e4b74b6f | ||
|
204178740c | ||
|
8fdf37261d | ||
|
06c8e584a4 | ||
|
bbf7222a6a | ||
|
f6e955b487 | ||
|
32a72bfd23 | ||
|
25e0c22de9 | ||
|
2dd1843aac | ||
|
f3bf4ca838 | ||
|
b88e5e27d8 | ||
|
6f91ff1f28 | ||
|
b7b941e3a1 | ||
|
64414fe105 | ||
|
701713e298 | ||
|
445229976f | ||
|
eb02404d49 | ||
|
c780c0bd92 | ||
|
8f631cae63 | ||
|
07afff8db5 | ||
|
a4f440656a | ||
|
235d572f8c | ||
|
eebc373734 | ||
|
002d29a53e | ||
|
5074e2beac | ||
|
d898ca736c | ||
|
af325612aa | ||
|
590c2c3b0a | ||
|
20f32c7f12 | ||
|
4106bcef5f | ||
|
0e3b8a2a28 | ||
|
272608b4ec | ||
|
7a389469b9 | ||
|
9650969c94 | ||
|
6821e668e4 | ||
|
43a68b96ae | ||
|
1f6e3db09e | ||
|
2fabcabcc0 | ||
|
22855b077d | ||
|
2cad7a67ea | ||
|
8ce93a028a | ||
|
028307b63c | ||
|
7bd6cd7cec | ||
|
8c45a40f9e | ||
|
70c62dab77 | ||
|
b4d8d31c2d | ||
|
bc15135f6b | ||
|
16baccc2cb | ||
|
bb2559edc1 | ||
|
f6f736a91f | ||
|
9f477676e2 | ||
|
6cba6ba52e | ||
|
d29dbc9385 | ||
|
cb01302ada | ||
|
e3dfbf0e95 | ||
|
3f471d0c73 | ||
|
4a706ab707 | ||
|
4946a9ab0d | ||
|
123372d93f | ||
|
272fe0516b | ||
|
289c9126d0 | ||
|
0a482da93e | ||
|
8bb8118d9f | ||
|
9db822eabd | ||
|
8a42dfa154 | ||
|
d7a7e22e5a | ||
|
4f75e2641b | ||
|
d3dcefb645 | ||
|
6d1553e8d8 | ||
|
740985d68f | ||
|
7ad2fab53d | ||
|
6e9b337b49 | ||
|
c58ff5861d | ||
|
33a5e70b70 | ||
|
07f1ce5822 | ||
|
d41996b365 | ||
|
d3c9b7eae1 | ||
|
373a1ab0f4 | ||
|
58dd56a89f | ||
|
d7eadd9294 | ||
|
853e29dd83 | ||
|
0c1c46c045 | ||
|
be97ea08a2 | ||
|
1c8b81ca2c | ||
|
8266f230d7 | ||
|
0b53542716 | ||
|
eab1c7096c | ||
|
8ee3aaf4f4 | ||
|
427b8659c9 | ||
|
3c3af824cf | ||
|
d40ce470d3 | ||
|
07c7f07c35 | ||
|
fe732ecf45 | ||
|
971bb92a8c | ||
|
777f6ba738 | ||
|
4d927c5870 | ||
|
1830e9da3d | ||
|
5eb29746af | ||
|
afb816cc41 | ||
|
bd640c19a4 | ||
|
0d445b6a21 | ||
|
78671b0bfe | ||
|
60325e797d | ||
|
7d9be5ae76 | ||
|
777bfed813 | ||
|
43ca543651 | ||
|
205d5f8f58 | ||
|
ee37852a72 | ||
|
dc14b58d73 | ||
|
a88a2e04cf | ||
|
c620beb965 | ||
|
92cb9f70a1 | ||
|
b2059b6910 | ||
|
0b21effb13 | ||
|
02acafc348 | ||
|
d202ecf06f | ||
|
5402d7bedb | ||
|
39247f1ece | ||
|
55b824d777 | ||
|
4eb223c401 | ||
|
4a99a5e68f | ||
|
a96c10a13e | ||
|
b3b2782f45 | ||
|
1bf9f25ded | ||
|
75df0198fc | ||
|
b70d74ae4b | ||
|
dfe4568991 | ||
|
3fff354833 | ||
|
db72dac243 | ||
|
b886c0aeae | ||
|
91b7f2752f | ||
|
f4a67c0224 | ||
|
c6ac0302ed | ||
|
39f1960135 | ||
|
ffb659b228 | ||
|
e93148304e | ||
|
34940dd950 | ||
|
eda0e2fe26 | ||
|
4aecfaf4e0 | ||
|
767de1dd65 | ||
|
7a6b045030 | ||
|
fdf64f9e9a | ||
|
835b954140 | ||
|
9770ffa46b | ||
|
da75cca97c | ||
|
d767e7472d | ||
|
9b8d4c518a | ||
|
96f5b2beab | ||
|
b9dc349d9a | ||
|
07d6e5c1d6 | ||
|
488c8c5526 | ||
|
fb0abf3c1a | ||
|
a954712197 | ||
|
7c258d231b | ||
|
c4bc1a4c51 | ||
|
0d9c86fcd3 | ||
|
5454bb5b07 | ||
|
04d5cd741b | ||
|
3191028f74 | ||
|
49f82127aa | ||
|
28d86c8885 | ||
|
1548b9f8c8 | ||
|
7271c8c6f1 | ||
|
aa0ec15e67 | ||
|
7f78822a12 | ||
|
f8e92f98d0 | ||
|
8d816ab1ee | ||
|
19967bd42e | ||
|
d3a819613f | ||
|
e33f6a20bb | ||
|
02b736c92f | ||
|
e339c79c5a | ||
|
945fb9384e | ||
|
a792a140f7 | ||
|
ed4728fdb1 | ||
|
92a8107b9d | ||
|
1af8558cf4 | ||
|
b781150ee9 | ||
|
59c4248efe | ||
|
a5b101a0ea | ||
|
03854aa207 | ||
|
c989be2719 | ||
|
d22e3ddcd7 | ||
|
040168b3d4 | ||
|
ac5c5555d5 | ||
|
1e6065f732 | ||
|
cb7be460d7 | ||
|
206bcebdb7 | ||
|
18c697f472 | ||
|
4adb9a5266 | ||
|
a72a7ed1fc | ||
|
838997b959 | ||
|
5736816b2b | ||
|
38b5a84c4f | ||
|
dff1ef04bf | ||
|
757201cafa | ||
|
1da3225e1d | ||
|
a2cd5652d2 | ||
|
dc7c13479c | ||
|
113e5b3bcd | ||
|
925f5c0ce0 | ||
|
0c53f5e186 | ||
|
2bcbe1d0be | ||
|
0e68f0783f | ||
|
91e8711fdf | ||
|
cf39e1f259 | ||
|
0cd631774b | ||
|
df53cf2540 | ||
|
b734fc09f3 | ||
|
1fe5c56d02 | ||
|
af98842090 | ||
|
3d67ad870a | ||
|
7b5ae70de3 | ||
|
18c80f6b64 | ||
|
d49bb1f4b5 | ||
|
87533b6031 | ||
|
33e36f3d2b | ||
|
42e604245c | ||
|
33475dca66 | ||
|
7a90d3f281 | ||
|
e53da5ad06 | ||
|
f5bbb8bdd6 | ||
|
d5b07bbaa3 | ||
|
3585b8a56a | ||
|
0c33059c4e | ||
|
0824e11570 | ||
|
0c4f5bcb3a | ||
|
aad8dcbadf | ||
|
193d5c8663 | ||
|
3734541743 | ||
|
f3bea68011 | ||
|
e843286ea7 | ||
|
e3d2012809 | ||
|
ce768764cc | ||
|
16b3d58242 | ||
|
fad8f26eaa | ||
|
04d1e84596 | ||
|
934acca934 | ||
|
639c98237a | ||
|
a6db67ab33 | ||
|
b92553f480 | ||
|
f5d53dc305 | ||
|
b7ce91e2d8 | ||
|
4295141fb6 | ||
|
973709c2f4 | ||
|
a72a61091a | ||
|
c635637c00 | ||
|
77a5cadf51 | ||
|
e0ef376cf0 | ||
|
04aeab7ea6 | ||
|
0dea26f67d | ||
|
1815162907 | ||
|
e00988047c | ||
|
faadd8e9a4 | ||
|
409dcce3c7 | ||
|
746ba398a9 | ||
|
faa3bea3ab | ||
|
f70f6c39ce | ||
|
25a8642749 | ||
|
41e45599d4 | ||
|
293afc3998 | ||
|
c662dcfcd9 | ||
|
e16aa31ddf | ||
|
c87f809d12 | ||
|
a3dcd1a0a8 | ||
|
4398b8698c | ||
|
18eb0467ee | ||
|
60942c8254 | ||
|
c7fac06b65 | ||
|
2e5b2c8b7d | ||
|
fbd095ab50 | ||
|
b176cb1ae1 | ||
|
2b65926865 | ||
|
a5d184baef | ||
|
12e9497ccf | ||
|
4b7d200aa2 | ||
|
e937432d1e | ||
|
e1f1d10833 | ||
|
05ec7ab665 | ||
|
dbd841a723 | ||
|
e8bc93f67a | ||
|
0d6ab793ce | ||
|
eab4d6f600 | ||
|
861c0174df | ||
|
5d68922f2e | ||
|
20ee16e3c0 | ||
|
20be83c345 | ||
|
015b69e601 | ||
|
95ef97fcc2 | ||
|
d600cb4b9a | ||
|
0bbfaf9893 | ||
|
e3e562a154 | ||
|
49034fabf2 | ||
|
e9d03a0c95 | ||
|
d7e68605c9 | ||
|
51900b4b62 | ||
|
67a1d06f37 | ||
|
395af17d96 | ||
|
88f4feaa81 | ||
|
b6b2e44231 | ||
|
4d4570701b | ||
|
178a825e93 | ||
|
f67ce2b0a3 | ||
|
10918ccb0d | ||
|
698fadc00c | ||
|
b16760988d | ||
|
7e3e1e2705 | ||
|
e5e039a1ca | ||
|
43d8c3c208 | ||
|
3cc1fb40f0 | ||
|
fea8109789 | ||
|
ff2aafabbd | ||
|
e27b15691a | ||
|
47ddcca065 | ||
|
0a7a7c979c | ||
|
b37ae97673 | ||
|
fa9e571b41 | ||
|
f0fd3d8c1d | ||
|
a1bdfab80f | ||
|
0d5b7a0711 | ||
|
852107f7f6 | ||
|
77b017381a | ||
|
75ce9c4370 | ||
|
a8d12c9c4c | ||
|
3294ba5964 | ||
|
2bd3a6a745 | ||
|
0d3c670f9d | ||
|
998b3ed075 | ||
|
a390b1e2a0 | ||
|
fb493cc837 | ||
|
2f17d5f3f5 | ||
|
3a2f3ce1cc |
692 changed files with 73210 additions and 18932 deletions
55
.docker/frankenphp/Caddyfile
Normal file
55
.docker/frankenphp/Caddyfile
Normal file
|
@ -0,0 +1,55 @@
|
|||
{
|
||||
{$CADDY_GLOBAL_OPTIONS}
|
||||
|
||||
frankenphp {
|
||||
{$FRANKENPHP_CONFIG}
|
||||
}
|
||||
|
||||
# https://caddyserver.com/docs/caddyfile/directives#sorting-algorithm
|
||||
order mercure after encode
|
||||
order vulcain after reverse_proxy
|
||||
order php_server before file_server
|
||||
}
|
||||
|
||||
{$CADDY_EXTRA_CONFIG}
|
||||
|
||||
{$SERVER_NAME:localhost} {
|
||||
log {
|
||||
# Redact the authorization query parameter that can be set by Mercure
|
||||
format filter {
|
||||
wrap console
|
||||
fields {
|
||||
uri query {
|
||||
replace authorization REDACTED
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
root * /app/public
|
||||
encode zstd br gzip
|
||||
|
||||
mercure {
|
||||
# Transport to use (default to Bolt)
|
||||
transport_url {$MERCURE_TRANSPORT_URL:bolt:///data/mercure.db}
|
||||
# Publisher JWT key
|
||||
publisher_jwt {env.MERCURE_PUBLISHER_JWT_KEY} {env.MERCURE_PUBLISHER_JWT_ALG}
|
||||
# Subscriber JWT key
|
||||
subscriber_jwt {env.MERCURE_SUBSCRIBER_JWT_KEY} {env.MERCURE_SUBSCRIBER_JWT_ALG}
|
||||
# Allow anonymous subscribers (double-check that it's what you want)
|
||||
anonymous
|
||||
# Enable the subscription API (double-check that it's what you want)
|
||||
subscriptions
|
||||
# Extra directives
|
||||
{$MERCURE_EXTRA_DIRECTIVES}
|
||||
}
|
||||
|
||||
vulcain
|
||||
|
||||
{$CADDY_SERVER_EXTRA_DIRECTIVES}
|
||||
|
||||
# Disable Topics tracking if not enabled explicitly: https://github.com/jkarlin/topics
|
||||
header ?Permissions-Policy "browsing-topics=()"
|
||||
|
||||
php_server
|
||||
}
|
5
.docker/frankenphp/conf.d/app.dev.ini
Normal file
5
.docker/frankenphp/conf.d/app.dev.ini
Normal file
|
@ -0,0 +1,5 @@
|
|||
; See https://docs.docker.com/desktop/networking/#i-want-to-connect-from-a-container-to-a-service-on-the-host
|
||||
; See https://github.com/docker/for-linux/issues/264
|
||||
; The `client_host` below may optionally be replaced with `discover_client_host=yes`
|
||||
; Add `start_with_request=yes` to start debug session on each request
|
||||
xdebug.client_host = host.docker.internal
|
18
.docker/frankenphp/conf.d/app.ini
Normal file
18
.docker/frankenphp/conf.d/app.ini
Normal file
|
@ -0,0 +1,18 @@
|
|||
expose_php = 0
|
||||
date.timezone = UTC
|
||||
apc.enable_cli = 1
|
||||
session.use_strict_mode = 1
|
||||
zend.detect_unicode = 0
|
||||
|
||||
; https://symfony.com/doc/current/performance.html
|
||||
realpath_cache_size = 4096K
|
||||
realpath_cache_ttl = 600
|
||||
opcache.interned_strings_buffer = 16
|
||||
opcache.max_accelerated_files = 20000
|
||||
opcache.memory_consumption = 256
|
||||
opcache.enable_file_override = 1
|
||||
|
||||
memory_limit = 256M
|
||||
|
||||
upload_max_filesize=256M
|
||||
post_max_size=300M
|
2
.docker/frankenphp/conf.d/app.prod.ini
Normal file
2
.docker/frankenphp/conf.d/app.prod.ini
Normal file
|
@ -0,0 +1,2 @@
|
|||
opcache.preload_user = root
|
||||
opcache.preload = /app/config/preload.php
|
60
.docker/frankenphp/docker-entrypoint.sh
Normal file
60
.docker/frankenphp/docker-entrypoint.sh
Normal file
|
@ -0,0 +1,60 @@
|
|||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
if [ "$1" = 'frankenphp' ] || [ "$1" = 'php' ] || [ "$1" = 'bin/console' ]; then
|
||||
# Install the project the first time PHP is started
|
||||
# After the installation, the following block can be deleted
|
||||
if [ ! -f composer.json ]; then
|
||||
rm -Rf tmp/
|
||||
composer create-project "symfony/skeleton $SYMFONY_VERSION" tmp --stability="$STABILITY" --prefer-dist --no-progress --no-interaction --no-install
|
||||
|
||||
cd tmp
|
||||
cp -Rp . ..
|
||||
cd -
|
||||
rm -Rf tmp/
|
||||
|
||||
composer require "php:>=$PHP_VERSION" runtime/frankenphp-symfony
|
||||
composer config --json extra.symfony.docker 'true'
|
||||
|
||||
if grep -q ^DATABASE_URL= .env; then
|
||||
echo "To finish the installation please press Ctrl+C to stop Docker Compose and run: docker compose up --build -d --wait"
|
||||
sleep infinity
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$(ls -A 'vendor/' 2>/dev/null)" ]; then
|
||||
composer install --prefer-dist --no-progress --no-interaction
|
||||
fi
|
||||
|
||||
if grep -q ^DATABASE_URL= .env; then
|
||||
echo "Waiting for database to be ready..."
|
||||
ATTEMPTS_LEFT_TO_REACH_DATABASE=60
|
||||
until [ $ATTEMPTS_LEFT_TO_REACH_DATABASE -eq 0 ] || DATABASE_ERROR=$(php bin/console dbal:run-sql -q "SELECT 1" 2>&1); do
|
||||
if [ $? -eq 255 ]; then
|
||||
# If the Doctrine command exits with 255, an unrecoverable error occurred
|
||||
ATTEMPTS_LEFT_TO_REACH_DATABASE=0
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
ATTEMPTS_LEFT_TO_REACH_DATABASE=$((ATTEMPTS_LEFT_TO_REACH_DATABASE - 1))
|
||||
echo "Still waiting for database to be ready... Or maybe the database is not reachable. $ATTEMPTS_LEFT_TO_REACH_DATABASE attempts left."
|
||||
done
|
||||
|
||||
if [ $ATTEMPTS_LEFT_TO_REACH_DATABASE -eq 0 ]; then
|
||||
echo "The database is not up or not reachable:"
|
||||
echo "$DATABASE_ERROR"
|
||||
exit 1
|
||||
else
|
||||
echo "The database is now ready and reachable"
|
||||
fi
|
||||
|
||||
if [ "$( find ./migrations -iname '*.php' -print -quit )" ]; then
|
||||
php bin/console doctrine:migrations:migrate --no-interaction
|
||||
fi
|
||||
fi
|
||||
|
||||
setfacl -R -m u:www-data:rwX -m u:"$(whoami)":rwX var
|
||||
setfacl -dR -m u:www-data:rwX -m u:"$(whoami)":rwX var
|
||||
fi
|
||||
|
||||
exec docker-php-entrypoint "$@"
|
4
.docker/frankenphp/worker.Caddyfile
Normal file
4
.docker/frankenphp/worker.Caddyfile
Normal file
|
@ -0,0 +1,4 @@
|
|||
worker {
|
||||
file ./public/index.php
|
||||
env APP_RUNTIME Runtime\FrankenPhpSymfony\Runtime
|
||||
}
|
|
@ -39,8 +39,50 @@ if [ -d /var/www/html/var/db ]; then
|
|||
fi
|
||||
fi
|
||||
|
||||
# Start PHP-FPM
|
||||
service php8.1-fpm start
|
||||
# Start PHP-FPM (the PHP_VERSION is replaced by the configured version in the Dockerfile)
|
||||
service phpPHP_VERSION-fpm start
|
||||
|
||||
|
||||
# Run migrations if automigration is enabled via env variable DB_AUTOMIGRATE
|
||||
if [ "$DB_AUTOMIGRATE" = "true" ]; then
|
||||
echo "Waiting for database to be ready..."
|
||||
ATTEMPTS_LEFT_TO_REACH_DATABASE=60
|
||||
until [ $ATTEMPTS_LEFT_TO_REACH_DATABASE -eq 0 ] || DATABASE_ERROR=$(sudo -E -u www-data php bin/console dbal:run-sql -q "SELECT 1" 2>&1); do
|
||||
if [ $? -eq 255 ]; then
|
||||
# If the Doctrine command exits with 255, an unrecoverable error occurred
|
||||
ATTEMPTS_LEFT_TO_REACH_DATABASE=0
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
ATTEMPTS_LEFT_TO_REACH_DATABASE=$((ATTEMPTS_LEFT_TO_REACH_DATABASE - 1))
|
||||
echo "Still waiting for database to be ready... Or maybe the database is not reachable. $ATTEMPTS_LEFT_TO_REACH_DATABASE attempts left."
|
||||
done
|
||||
|
||||
if [ $ATTEMPTS_LEFT_TO_REACH_DATABASE -eq 0 ]; then
|
||||
echo "The database is not up or not reachable:"
|
||||
echo "$DATABASE_ERROR"
|
||||
exit 1
|
||||
else
|
||||
echo "The database is now ready and reachable"
|
||||
fi
|
||||
|
||||
# Check if there are any available migrations to do, by executing doctrine:migrations:up-to-date
|
||||
# and checking if the exit code is 0 (up to date) or 1 (not up to date)
|
||||
if sudo -E -u www-data php bin/console doctrine:migrations:up-to-date --no-interaction; then
|
||||
echo "Database is up to date, no migrations necessary."
|
||||
else
|
||||
echo "Migrations available..."
|
||||
echo "Do backup of database..."
|
||||
|
||||
sudo -E -u www-data mkdir -p /var/www/html/uploads/.automigration-backup/
|
||||
# Backup the database
|
||||
sudo -E -u www-data php bin/console partdb:backup -n --database /var/www/html/uploads/.automigration-backup/backup-$(date +%Y-%m-%d_%H-%M-%S).zip
|
||||
|
||||
# Check if there are any migration files
|
||||
sudo -E -u www-data php bin/console doctrine:migrations:migrate --no-interaction
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
# 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
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
CustomLog ${APACHE_LOG_DIR}/access.log combined
|
||||
|
||||
# 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 REDIRECT_TO_HTTPS
|
||||
PassEnv APP_ENV APP_DEBUG APP_SECRET REDIRECT_TO_HTTPS DISABLE_YEAR2038_BUG_CHECK
|
||||
PassEnv TRUSTED_PROXIES TRUSTED_HOSTS LOCK_DSN
|
||||
PassEnv DATABASE_URL ENFORCE_CHANGE_COMMENTS_FOR DATABASE_MYSQL_USE_SSL_CA DATABASE_MYSQL_SSL_VERIFY_CERT
|
||||
PassEnv DEFAULT_LANG DEFAULT_TIMEZONE BASE_CURRENCY INSTANCE_NAME ALLOW_ATTACHMENT_DOWNLOADS USE_GRAVATAR MAX_ATTACHMENT_FILE_SIZE DEFAULT_URI CHECK_FOR_UPDATES ATTACHMENT_DOWNLOAD_BY_DEFAULT
|
||||
|
@ -42,6 +42,10 @@
|
|||
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
|
||||
PassEnv PROVIDER_MOUSER_KEY PROVIDER_MOUSER_SEARCH_OPTION PROVIDER_MOUSER_SEARCH_LIMIT PROVIDER_MOUSER_SEARCH_WITH_SIGNUP_LANGUAGE
|
||||
PassEnv PROVIDER_LCSC_ENABLED PROVIDER_LCSC_CURRENCY
|
||||
PassEnv PROVIDER_OEMSECRETS_KEY PROVIDER_OEMSECRETS_COUNTRY_CODE PROVIDER_OEMSECRETS_CURRENCY PROVIDER_OEMSECRETS_ZERO_PRICE PROVIDER_OEMSECRETS_SET_PARAM PROVIDER_OEMSECRETS_SORT_CRITERIA
|
||||
PassEnv PROVIDER_REICHELT_ENABLED PROVIDER_REICHELT_CURRENCY PROVIDER_REICHELT_COUNTRY PROVIDER_REICHELT_LANGUAGE PROVIDER_REICHELT_INCLUDE_VAT
|
||||
PassEnv PROVIDER_POLLIN_ENABLED
|
||||
PassEnv EDA_KICAD_CATEGORY_DEPTH
|
||||
|
||||
# For most configuration files from conf-available/, which are
|
||||
|
|
|
@ -5,6 +5,8 @@ tests/
|
|||
docs/
|
||||
.git
|
||||
|
||||
/public/media/*
|
||||
|
||||
###> symfony/framework-bundle ###
|
||||
/.env.local
|
||||
/.env.local.php
|
||||
|
@ -42,3 +44,39 @@ yarn-error.log
|
|||
/phpunit.xml
|
||||
.phpunit.result.cache
|
||||
###< phpunit/phpunit ###
|
||||
|
||||
|
||||
### From frankenphp
|
||||
|
||||
**/*.log
|
||||
**/*.php~
|
||||
**/*.dist.php
|
||||
**/*.dist
|
||||
**/*.cache
|
||||
**/._*
|
||||
**/.dockerignore
|
||||
**/.DS_Store
|
||||
**/.git/
|
||||
**/.gitattributes
|
||||
**/.gitignore
|
||||
**/.gitmodules
|
||||
**/compose.*.yaml
|
||||
**/compose.*.yml
|
||||
**/compose.yaml
|
||||
**/compose.yml
|
||||
**/docker-compose.*.yaml
|
||||
**/docker-compose.*.yml
|
||||
**/docker-compose.yaml
|
||||
**/docker-compose.yml
|
||||
**/Dockerfile
|
||||
**/Thumbs.db
|
||||
.github/
|
||||
public/bundles/
|
||||
var/
|
||||
vendor/
|
||||
.editorconfig
|
||||
.env.*.local
|
||||
.env.local
|
||||
.env.local.php
|
||||
.env.test
|
||||
|
||||
|
|
73
.env
73
.env
|
@ -23,6 +23,10 @@ DATABASE_MYSQL_USE_SSL_CA=0
|
|||
# Only do this, if you know what you are doing!
|
||||
DATABASE_MYSQL_SSL_VERIFY_CERT=1
|
||||
|
||||
# Emulate natural sorting of strings even on databases that do not support it (like SQLite, MySQL or MariaDB < 10.7)
|
||||
# This can be slow on big databases and might have some problems and quirks, so use it with caution
|
||||
DATABASE_EMULATE_NATURAL_SORT=0
|
||||
|
||||
###################################################################################
|
||||
# General settings
|
||||
###################################################################################
|
||||
|
@ -139,7 +143,8 @@ PROVIDER_TME_CURRENCY=EUR
|
|||
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
|
||||
# [DEPRECATED] Set this to 1 to get gross prices (including VAT) instead of net prices
|
||||
# With private API keys, this option cannot be used anymore is ignored by Part-DB. The VAT inclusion depends on your TME account settings.
|
||||
PROVIDER_TME_GET_GROSS_PRICES=1
|
||||
|
||||
# Octopart / Nexar Provider:
|
||||
|
@ -168,6 +173,70 @@ PROVIDER_MOUSER_SEARCH_LIMIT=50
|
|||
# Used when searching for keywords in the language specified when you signed up for Search API.
|
||||
PROVIDER_MOUSER_SEARCH_WITH_SIGNUP_LANGUAGE='true'
|
||||
|
||||
# LCSC Provider:
|
||||
# LCSC does not provide an offical API, so this used the API LCSC uses to render their webshop.
|
||||
# LCSC did not intended the use of this API and it could break any time, so use it at your own risk.
|
||||
|
||||
# We dont require an API key for LCSC, just set this to 1 to enable LCSC support
|
||||
PROVIDER_LCSC_ENABLED=0
|
||||
# The currency to get prices in (e.g. EUR, USD, etc.)
|
||||
PROVIDER_LCSC_CURRENCY=EUR
|
||||
|
||||
# Oemsecrets Provider API 3.0.1:
|
||||
# You can get your API key from https://www.oemsecrets.com/api
|
||||
PROVIDER_OEMSECRETS_KEY=
|
||||
# The country you want the output for
|
||||
PROVIDER_OEMSECRETS_COUNTRY_CODE=DE
|
||||
# Available country code are:
|
||||
# AD, AE, AQ, AR, AT, AU, BE, BO, BR, BV, BY, CA, CH, CL, CN, CO, CZ, DE, DK, EC, EE, EH,
|
||||
# ES, FI, FK, FO, FR, GB, GE, GF, GG, GI, GL, GR, GS, GY, HK, HM, HR, HU, IE, IM, IN, IS,
|
||||
# IT, JM, JP, KP, KR, KZ, LI, LK, LT, LU, MC, MD, ME, MK, MT, NL, NO, NZ, PE, PH, PL, PT,
|
||||
# PY, RO, RS, RU, SB, SD, SE, SG, SI, SJ, SK, SM, SO, SR, SY, SZ, TC, TF, TG, TH, TJ, TK,
|
||||
# TM, TN, TO, TR, TT, TV, TW, TZ, UA, UG, UM, US, UY, UZ, VA, VE, VG, VI, VN, VU, WF, YE,
|
||||
# ZA, ZM, ZW
|
||||
#
|
||||
# The currency you want the prices to be displayed in
|
||||
PROVIDER_OEMSECRETS_CURRENCY=EUR
|
||||
# Available currency are:AUD, CAD, CHF, CNY, DKK, EUR, GBP, HKD, ILS, INR, JPY, KRW, NOK,
|
||||
# NZD, RUB, SEK, SGD, TWD, USD
|
||||
#
|
||||
# If PROVIDER_OEMSECRETS_ZERO_PRICE is set to 0, distributors with zero prices
|
||||
# will be discarded from the creation of a new part (set to 1 otherwise)
|
||||
PROVIDER_OEMSECRETS_ZERO_PRICE=0
|
||||
#
|
||||
# When PROVIDER_OEMSECRETS_SET_PARAM is set to 1 the parameters for the part are generated
|
||||
# from the description transforming unstructured descriptions into structured parameters;
|
||||
# each parameter in description should have the form: "...;name1:value1;name2:value2"
|
||||
PROVIDER_OEMSECRETS_SET_PARAM=1
|
||||
#
|
||||
# This environment variable determines the sorting criteria for product results.
|
||||
# The sorting process first arranges items based on the provided keyword.
|
||||
# Then, if set to 'C', it further sorts by completeness (prioritizing items with the most
|
||||
# detailed information). If set to 'M', it further sorts by manufacturer name.
|
||||
#If unset or set to any other value, no sorting is performed.
|
||||
PROVIDER_OEMSECRETS_SORT_CRITERIA=C
|
||||
|
||||
|
||||
# Reichelt provider:
|
||||
# Reichelt.com offers no official API, so this info provider webscrapes the website to extract info
|
||||
# It could break at any time, use it at your own risk
|
||||
# We dont require an API key for Reichelt, just set this to 1 to enable Reichelt support
|
||||
PROVIDER_REICHELT_ENABLED=0
|
||||
# The country to get prices for
|
||||
PROVIDER_REICHELT_COUNTRY=DE
|
||||
# The language to get results in (en, de, fr, nl, pl, it, es)
|
||||
PROVIDER_REICHELT_LANGUAGE=en
|
||||
# Include VAT in prices (set to 1 to include VAT, 0 to exclude VAT)
|
||||
PROVIDER_REICHELT_INCLUDE_VAT=1
|
||||
# The currency to get prices in (only for countries with countries other than EUR)
|
||||
PROVIDER_REICHELT_CURRENCY=EUR
|
||||
|
||||
# Pollin provider:
|
||||
# Pollin.de offers no official API, so this info provider webscrapes the website to extract info
|
||||
# It could break at any time, use it at your own risk
|
||||
# We dont require an API key for Pollin, just set this to 1 to enable Pollin support
|
||||
PROVIDER_POLLIN_ENABLED=0
|
||||
|
||||
##################################################################################
|
||||
# EDA integration related settings
|
||||
##################################################################################
|
||||
|
@ -239,6 +308,8 @@ BANNER=""
|
|||
APP_ENV=prod
|
||||
APP_SECRET=a03498528f5a5fc089273ec9ae5b2849
|
||||
|
||||
# Set this to zero, if you want to disable the year 2038 bug check on 32-bit systems (it will cause errors with current 32-bit PHP versions)
|
||||
DISABLE_YEAR2038_BUG_CHECK=0
|
||||
|
||||
# Set the trusted IPs here, when using an reverse proxy
|
||||
#TRUSTED_PROXIES=127.0.0.0/8,::1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16
|
||||
|
|
0
.env.dev
Normal file
0
.env.dev
Normal file
2
.github/workflows/docker_build.yml
vendored
2
.github/workflows/docker_build.yml
vendored
|
@ -65,7 +65,7 @@ jobs:
|
|||
|
||||
-
|
||||
name: Build and push
|
||||
uses: docker/build-push-action@v5
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64,linux/arm/v7
|
||||
|
|
77
.github/workflows/docker_frankenphp.yml
vendored
Normal file
77
.github/workflows/docker_frankenphp.yml
vendored
Normal file
|
@ -0,0 +1,77 @@
|
|||
name: Docker Image Build (FrankenPHP)
|
||||
|
||||
on:
|
||||
#schedule:
|
||||
# - cron: '0 10 * * *' # everyday at 10am
|
||||
push:
|
||||
branches:
|
||||
- '**'
|
||||
- '!l10n_**'
|
||||
tags:
|
||||
- 'v*.*.*'
|
||||
- 'v*.*.*-**'
|
||||
|
||||
jobs:
|
||||
docker:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
-
|
||||
name: Docker meta
|
||||
id: docker_meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
# list of Docker images to use as base name for tags
|
||||
images: |
|
||||
partdborg/part-db
|
||||
# Mark the image build from master as latest (as we dont have really releases yet)
|
||||
tags: |
|
||||
type=edge,branch=master
|
||||
type=ref,event=branch,
|
||||
type=ref,event=tag,
|
||||
type=schedule
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=semver,pattern={{major}}
|
||||
type=ref,event=branch
|
||||
type=ref,event=pr
|
||||
labels: |
|
||||
org.opencontainers.image.source=${{ github.event.repository.clone_url }}
|
||||
org.opencontainers.image.revision=${{ github.sha }}
|
||||
org.opencontainers.image.title=Part-DB
|
||||
org.opencontainers.image.description=Part-DB is a web application for managing electronic components and your inventory.
|
||||
org.opencontainers.image.url=https://github.com/Part-DB/Part-DB-server
|
||||
org.opencontainers.image.source=https://github.com/Part-DB/Part-DB-server
|
||||
org.opencontainers.image.authors=Jan Böhmer
|
||||
org.opencontainers.licenses=AGPL-3.0-or-later
|
||||
|
||||
-
|
||||
name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
with:
|
||||
platforms: 'arm64,arm'
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
-
|
||||
name: Login to DockerHub
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
-
|
||||
name: Build and push
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: Dockerfile-frankenphp
|
||||
platforms: linux/amd64,linux/arm64,linux/arm/v7
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
tags: ${{ steps.docker_meta.outputs.tags }}
|
||||
labels: ${{ steps.docker_meta.outputs.labels }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
37
.github/workflows/tests.yml
vendored
37
.github/workflows/tests.yml
vendored
|
@ -16,9 +16,10 @@ jobs:
|
|||
runs-on: ubuntu-22.04
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
php-versions: [ '8.1', '8.2', '8.3' ]
|
||||
db-type: [ 'mysql', 'sqlite' ]
|
||||
php-versions: [ '8.1', '8.2', '8.3', '8.4' ]
|
||||
db-type: [ 'mysql', 'sqlite', 'postgres' ]
|
||||
|
||||
env:
|
||||
# Note that we set DATABASE URL later based on our db-type matrix value
|
||||
|
@ -30,13 +31,17 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Set Database env for MySQL
|
||||
run: echo "DATABASE_URL=mysql://root:root@127.0.0.1:3306/test" >> $GITHUB_ENV
|
||||
run: echo "DATABASE_URL=mysql://root:root@127.0.0.1:3306/partdb?serverVersion=8.0.35" >> $GITHUB_ENV
|
||||
if: matrix.db-type == 'mysql'
|
||||
|
||||
- name: Set Database env for SQLite
|
||||
run: echo "DATABASE_URL="sqlite:///%kernel.project_dir%/var/app_test.db"" >> $GITHUB_ENV
|
||||
if: matrix.db-type == 'sqlite'
|
||||
|
||||
- name: Set Database env for PostgreSQL
|
||||
run: echo "DATABASE_URL=postgresql://postgres:postgres @127.0.0.1:5432/partdb?serverVersion=14&charset=utf8" >> $GITHUB_ENV
|
||||
if: matrix.db-type == 'postgres'
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
|
@ -50,8 +55,17 @@ jobs:
|
|||
|
||||
- name: Start MySQL
|
||||
run: sudo systemctl start mysql.service
|
||||
if: matrix.db-type == 'mysql'
|
||||
|
||||
#- name: Setup MySQL
|
||||
# Replace the scram-sha-256 with trust for host connections, to avoid password authentication
|
||||
- name: Start PostgreSQL
|
||||
run: |
|
||||
sudo sed -i 's/^\(host.*all.*all.*\)scram-sha-256/\1trust/' /etc/postgresql/14/main/pg_hba.conf
|
||||
sudo systemctl start postgresql.service
|
||||
sudo -u postgres psql -c "ALTER USER postgres PASSWORD 'postgres';"
|
||||
if: matrix.db-type == 'postgres'
|
||||
|
||||
#- name: Setup MySQL
|
||||
# uses: mirromutth/mysql-action@v1.1
|
||||
# with:
|
||||
# mysql version: 5.7
|
||||
|
@ -99,12 +113,7 @@ jobs:
|
|||
|
||||
- name: Create DB
|
||||
run: php bin/console --env test doctrine:database:create --if-not-exists -n
|
||||
if: matrix.db-type == 'mysql'
|
||||
|
||||
# Checkinf for existance is not supported for sqlite, so do it without it
|
||||
- name: Create DB
|
||||
run: php bin/console --env test doctrine:database:create -n
|
||||
if: matrix.db-type == 'sqlite'
|
||||
if: matrix.db-type == 'mysql' || matrix.db-type == 'postgres'
|
||||
|
||||
- name: Do migrations
|
||||
run: php bin/console --env test doctrine:migrations:migrate -n
|
||||
|
@ -117,7 +126,7 @@ jobs:
|
|||
run: ./bin/phpunit --coverage-clover=coverage.xml
|
||||
|
||||
- name: Upload coverage
|
||||
uses: codecov/codecov-action@v3
|
||||
uses: codecov/codecov-action@v5
|
||||
with:
|
||||
env_vars: PHP_VERSION,DB_TYPE
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
@ -135,11 +144,11 @@ jobs:
|
|||
- name: Test check-requirements command
|
||||
run: php bin/console partdb:check-requirements -n
|
||||
|
||||
- name: Test partdb:backup command
|
||||
run: php bin/console partdb:backup -n --full /tmp/test_backup.zip
|
||||
|
||||
- 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
|
||||
|
||||
|
||||
|
||||
|
|
187
Dockerfile
187
Dockerfile
|
@ -1,22 +1,64 @@
|
|||
FROM debian:bullseye-slim
|
||||
ARG BASE_IMAGE=debian:bookworm-slim
|
||||
ARG PHP_VERSION=8.3
|
||||
|
||||
FROM ${BASE_IMAGE} AS base
|
||||
ARG PHP_VERSION
|
||||
|
||||
# Install needed dependencies for PHP build
|
||||
#RUN apt-get update && apt-get install -y pkg-config curl libcurl4-openssl-dev libicu-dev \
|
||||
# libpng-dev libjpeg-dev libfreetype6-dev gnupg zip libzip-dev libjpeg62-turbo-dev libonig-dev libxslt-dev libwebp-dev vim \
|
||||
# && apt-get -y autoremove && apt-get clean autoclean && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN apt-get update && apt-get -y install apt-transport-https lsb-release ca-certificates curl zip mariadb-client \
|
||||
RUN apt-get update && apt-get -y install \
|
||||
apt-transport-https \
|
||||
lsb-release \
|
||||
ca-certificates \
|
||||
curl \
|
||||
zip \
|
||||
mariadb-client \
|
||||
postgresql-client \
|
||||
&& 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 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
|
||||
ENV APACHE_ENVVARS $APACHE_CONFDIR/envvars
|
||||
|
||||
&& apt-get install -y \
|
||||
apache2 \
|
||||
php${PHP_VERSION} \
|
||||
php${PHP_VERSION}-fpm \
|
||||
php${PHP_VERSION}-opcache \
|
||||
php${PHP_VERSION}-curl \
|
||||
php${PHP_VERSION}-gd \
|
||||
php${PHP_VERSION}-mbstring \
|
||||
php${PHP_VERSION}-xml \
|
||||
php${PHP_VERSION}-bcmath \
|
||||
php${PHP_VERSION}-intl \
|
||||
php${PHP_VERSION}-zip \
|
||||
php${PHP_VERSION}-xsl \
|
||||
php${PHP_VERSION}-sqlite3 \
|
||||
php${PHP_VERSION}-mysql \
|
||||
php${PHP_VERSION}-pgsql \
|
||||
gpg \
|
||||
sudo \
|
||||
&& apt-get -y autoremove && apt-get clean autoclean && rm -rf /var/lib/apt/lists/* \
|
||||
# Create workdir and set permissions if directory does not exists
|
||||
RUN mkdir -p /var/www/html && chown -R www-data:www-data /var/www/html
|
||||
&& mkdir -p /var/www/html \
|
||||
&& chown -R www-data:www-data /var/www/html \
|
||||
# delete the "index.html" that installing Apache drops in here
|
||||
&& rm -rvf /var/www/html/*
|
||||
|
||||
# Install node and yarn
|
||||
RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \
|
||||
echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \
|
||||
curl -sL https://deb.nodesource.com/setup_20.x | bash - && \
|
||||
apt-get update && apt-get install -y \
|
||||
nodejs \
|
||||
yarn \
|
||||
&& apt-get -y autoremove && apt-get clean autoclean && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install composer
|
||||
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
|
||||
|
||||
ENV APACHE_CONFDIR=/etc/apache2
|
||||
ENV APACHE_ENVVARS=$APACHE_CONFDIR/envvars
|
||||
|
||||
# Configure apache 2 (taken from https://github.com/docker-library/php/blob/master/8.2/bullseye/apache/Dockerfile)
|
||||
# generically convert lines like
|
||||
|
@ -27,8 +69,6 @@ RUN mkdir -p /var/www/html && chown -R www-data:www-data /var/www/html
|
|||
# so that they can be overridden at runtime ("-e APACHE_RUN_USER=...")
|
||||
RUN sed -ri 's/^export ([^=]+)=(.*)$/: ${\1:=\2}\nexport \1/' "$APACHE_ENVVARS"; \
|
||||
set -eux; . "$APACHE_ENVVARS"; \
|
||||
# delete the "index.html" that installing Apache drops in here
|
||||
rm -rvf /var/www/html/*; \
|
||||
\
|
||||
# logs should go to stdout / stderr
|
||||
ln -sfT /dev/stderr "$APACHE_LOG_DIR/error.log"; \
|
||||
|
@ -36,82 +76,87 @@ 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 php-fpm
|
||||
RUN a2enmod proxy_fcgi setenvif && a2enconf php8.1-fpm
|
||||
# ---
|
||||
|
||||
FROM scratch AS apache-config
|
||||
ARG PHP_VERSION
|
||||
# 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"
|
||||
COPY <<EOF /etc/php/${PHP_VERSION}/fpm/pool.d/zz-docker.conf
|
||||
[global]
|
||||
error_log = /proc/1/fd/1
|
||||
|
||||
[www]
|
||||
access.log = /proc/1/fd/1
|
||||
catch_workers_output = yes
|
||||
decorate_workers_output = no
|
||||
clear_env = no
|
||||
EOF
|
||||
|
||||
# PHP files should be handled by PHP, and should be preferred over any other file type
|
||||
RUN { \
|
||||
echo '<FilesMatch \.php$>'; \
|
||||
echo '\tSetHandler application/x-httpd-php'; \
|
||||
echo '</FilesMatch>'; \
|
||||
echo; \
|
||||
echo 'DirectoryIndex disabled'; \
|
||||
echo 'DirectoryIndex index.php index.html'; \
|
||||
echo; \
|
||||
echo '<Directory /var/www/>'; \
|
||||
echo '\tOptions -Indexes'; \
|
||||
echo '\tAllowOverride All'; \
|
||||
echo '</Directory>'; \
|
||||
} | tee "$APACHE_CONFDIR/conf-available/docker-php.conf" \
|
||||
&& a2enconf docker-php
|
||||
COPY <<EOF /etc/apache2/conf-available/docker-php.conf
|
||||
<FilesMatch \\.php$>
|
||||
SetHandler application/x-httpd-php
|
||||
</FilesMatch>
|
||||
|
||||
DirectoryIndex disabled
|
||||
DirectoryIndex index.php index.html
|
||||
|
||||
<Directory /var/www/>
|
||||
Options -Indexes
|
||||
AllowOverride All
|
||||
</Directory>
|
||||
EOF
|
||||
|
||||
# Enable opcache and configure it recommended for symfony (see https://symfony.com/doc/current/performance.html)
|
||||
RUN \
|
||||
{ \
|
||||
echo 'opcache.memory_consumption=256'; \
|
||||
echo 'opcache.max_accelerated_files=20000'; \
|
||||
echo 'opcache.validate_timestamp=0'; \
|
||||
# Configure Realpath cache for performance
|
||||
echo 'realpath_cache_size=4096K'; \
|
||||
echo 'realpath_cache_ttl=600'; \
|
||||
} > /etc/php/8.1/fpm/conf.d/symfony-recommended.ini
|
||||
COPY <<EOF /etc/php/${PHP_VERSION}/fpm/conf.d/symfony-recommended.ini
|
||||
opcache.memory_consumption=256
|
||||
opcache.max_accelerated_files=20000
|
||||
opcache.validate_timestamp=0
|
||||
# Configure Realpath cache for performance
|
||||
realpath_cache_size=4096K
|
||||
realpath_cache_ttl=600
|
||||
EOF
|
||||
|
||||
# Increase upload limit and enable preloading
|
||||
RUN \
|
||||
{ \
|
||||
echo 'upload_max_filesize=256M'; \
|
||||
echo 'post_max_size=300M'; \
|
||||
echo 'opcache.preload_user=www-data'; \
|
||||
echo 'opcache.preload=/var/www/html/config/preload.php'; \
|
||||
} > /etc/php/8.1/fpm/conf.d/partdb.ini
|
||||
COPY <<EOF /etc/php/${PHP_VERSION}/fpm/conf.d/partdb.ini
|
||||
upload_max_filesize=256M
|
||||
post_max_size=300M
|
||||
opcache.preload_user=www-data
|
||||
opcache.preload=/var/www/html/config/preload.php
|
||||
log_limit=8096
|
||||
EOF
|
||||
|
||||
# Install node and yarn
|
||||
RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
|
||||
RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
|
||||
RUN curl -sL https://deb.nodesource.com/setup_18.x | bash - && apt-get update && apt-get install -y nodejs yarn && apt-get -y autoremove && apt-get clean autoclean && rm -rf /var/lib/apt/lists/*
|
||||
COPY ./.docker/symfony.conf /etc/apache2/sites-available/symfony.conf
|
||||
|
||||
# Install composer
|
||||
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
|
||||
# ---
|
||||
|
||||
FROM base
|
||||
ARG PHP_VERSION
|
||||
|
||||
# Set working dir
|
||||
WORKDIR /var/www/html
|
||||
COPY --from=apache-config / /
|
||||
COPY --chown=www-data:www-data . .
|
||||
|
||||
# Setup apache2
|
||||
RUN a2dissite 000-default.conf
|
||||
COPY ./.docker/symfony.conf /etc/apache2/sites-available/symfony.conf
|
||||
RUN a2ensite symfony.conf
|
||||
RUN a2enmod rewrite
|
||||
RUN a2dissite 000-default.conf && \
|
||||
a2ensite symfony.conf && \
|
||||
# Enable php-fpm
|
||||
a2enmod proxy_fcgi setenvif && \
|
||||
a2enconf php${PHP_VERSION}-fpm && \
|
||||
a2enconf docker-php && \
|
||||
a2enmod rewrite
|
||||
|
||||
# Install composer and yarn dependencies for Part-DB
|
||||
USER www-data
|
||||
RUN composer install -a --no-dev && composer clear-cache
|
||||
RUN yarn install --network-timeout 600000 && yarn build && yarn cache clean && rm -rf node_modules/
|
||||
RUN composer install -a --no-dev && \
|
||||
composer clear-cache
|
||||
RUN yarn install --network-timeout 600000 && \
|
||||
yarn build && \
|
||||
yarn cache clean && \
|
||||
rm -rf node_modules/
|
||||
|
||||
# Use docker env to output logs to stdout
|
||||
ENV APP_ENV=docker
|
||||
|
@ -119,10 +164,12 @@ ENV DATABASE_URL="sqlite:///%kernel.project_dir%/uploads/app.db"
|
|||
|
||||
USER root
|
||||
|
||||
# Copy entrypoint to /usr/local/bin and make it executable
|
||||
RUN cp ./.docker/partdb-entrypoint.sh /usr/local/bin/partdb-entrypoint.sh && chmod +x /usr/local/bin/partdb-entrypoint.sh
|
||||
# Copy apache2-foreground to /usr/local/bin and make it executable
|
||||
RUN cp ./.docker/apache2-foreground /usr/local/bin/apache2-foreground && chmod +x /usr/local/bin/apache2-foreground
|
||||
# Replace the php version placeholder in the entry point, with our php version
|
||||
RUN sed -i "s/PHP_VERSION/${PHP_VERSION}/g" ./.docker/partdb-entrypoint.sh
|
||||
|
||||
# Copy entrypoint and apache2-foreground to /usr/local/bin and make it executable
|
||||
RUN install ./.docker/partdb-entrypoint.sh /usr/local/bin && \
|
||||
install ./.docker/apache2-foreground /usr/local/bin
|
||||
ENTRYPOINT ["partdb-entrypoint.sh"]
|
||||
CMD ["apache2-foreground"]
|
||||
|
||||
|
@ -130,4 +177,4 @@ CMD ["apache2-foreground"]
|
|||
STOPSIGNAL SIGWINCH
|
||||
|
||||
EXPOSE 80
|
||||
VOLUME ["/var/www/html/uploads", "/var/www/html/public/media"]
|
||||
VOLUME ["/var/www/html/uploads", "/var/www/html/public/media"]
|
||||
|
|
101
Dockerfile-frankenphp
Normal file
101
Dockerfile-frankenphp
Normal file
|
@ -0,0 +1,101 @@
|
|||
FROM dunglas/frankenphp:1-php8.3 AS frankenphp_upstream
|
||||
|
||||
RUN apt-get update && apt-get -y install \
|
||||
curl \
|
||||
ca-certificates \
|
||||
mariadb-client \
|
||||
postgresql-client \
|
||||
file \
|
||||
acl \
|
||||
git \
|
||||
gettext \
|
||||
gnupg \
|
||||
zip \
|
||||
&& apt-get -y autoremove && apt-get clean autoclean && rm -rf /var/lib/apt/lists/*;
|
||||
|
||||
# Install node and yarn
|
||||
RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \
|
||||
echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \
|
||||
curl -sL https://deb.nodesource.com/setup_20.x | bash - && \
|
||||
apt-get update && apt-get install -y \
|
||||
nodejs yarn \
|
||||
&& apt-get -y autoremove && apt-get clean autoclean && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install PHP
|
||||
RUN set -eux; \
|
||||
install-php-extensions \
|
||||
@composer \
|
||||
apcu \
|
||||
intl \
|
||||
opcache \
|
||||
zip \
|
||||
pdo_mysql \
|
||||
pdo_sqlite \
|
||||
pdo_pgsql \
|
||||
gd \
|
||||
bcmath \
|
||||
xsl \
|
||||
;
|
||||
|
||||
# Copy config files for php and caddy
|
||||
COPY --link .docker/frankenphp/conf.d/app.ini $PHP_INI_DIR/conf.d/
|
||||
COPY --chmod=755 .docker/frankenphp/docker-entrypoint.sh /usr/local/bin/docker-entrypoint
|
||||
COPY --link .docker/frankenphp/Caddyfile /etc/caddy/Caddyfile
|
||||
COPY --link .docker/frankenphp/conf.d/app.prod.ini $PHP_INI_DIR/conf.d/
|
||||
COPY --link .docker/frankenphp/worker.Caddyfile /etc/caddy/worker.Caddyfile
|
||||
ENV FRANKENPHP_CONFIG="import worker.Caddyfile"
|
||||
|
||||
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
|
||||
|
||||
# Install composer
|
||||
ENV COMPOSER_ALLOW_SUPERUSER=1
|
||||
#COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
|
||||
|
||||
# Create workdir and set permissions if directory does not exists
|
||||
WORKDIR /app
|
||||
|
||||
# prevent the reinstallation of vendors at every changes in the source code
|
||||
COPY --link composer.* symfony.* ./
|
||||
RUN set -eux; \
|
||||
composer install --no-cache --prefer-dist --no-dev --no-autoloader --no-scripts --no-progress
|
||||
|
||||
# copy sources
|
||||
COPY --link . ./
|
||||
|
||||
# Install composer and yarn dependencies for Part-DB
|
||||
RUN set -eux; \
|
||||
mkdir -p var/cache var/log; \
|
||||
composer dump-autoload --classmap-authoritative --no-dev; \
|
||||
composer dump-env prod; \
|
||||
composer run-script --no-dev post-install-cmd; \
|
||||
chmod +x bin/console; sync;
|
||||
|
||||
RUN yarn install --network-timeout 600000 && \
|
||||
yarn build && \
|
||||
yarn cache clean && \
|
||||
rm -rf node_modules/
|
||||
|
||||
# Use docker env to output logs to stdout
|
||||
ENV APP_ENV=docker
|
||||
ENV DATABASE_URL="sqlite:///%kernel.project_dir%/uploads/app.db"
|
||||
|
||||
USER root
|
||||
|
||||
ENTRYPOINT ["docker-entrypoint"]
|
||||
CMD ["frankenphp", "run", "--config", "/etc/caddy/Caddyfile"]
|
||||
|
||||
# https://httpd.apache.org/docs/2.4/stopping.html#gracefulstop
|
||||
STOPSIGNAL SIGWINCH
|
||||
|
||||
VOLUME ["/var/www/html/uploads", "/var/www/html/public/media"]
|
||||
|
||||
HEALTHCHECK --start-period=60s CMD curl -f http://localhost:2019/metrics || exit 1
|
||||
|
||||
# See https://caddyserver.com/docs/conventions#file-locations for details
|
||||
ENV XDG_CONFIG_HOME /config
|
||||
ENV XDG_DATA_HOME /data
|
||||
|
||||
EXPOSE 80
|
||||
EXPOSE 443
|
||||
EXPOSE 443/udp
|
||||
EXPOSE 2019
|
54
README.md
54
README.md
|
@ -30,7 +30,7 @@ If you want to test Part-DB without installing it, you can use [this](https://de
|
|||
You can log in with username: *user* and password: *user*.
|
||||
|
||||
Every change to the master branch gets automatically deployed, so it represents the current development progress and is
|
||||
maybe not completely stable. Please mind, that the free Heroku instance is used, so it can take some time when loading
|
||||
may not completely stable. Please mind, that the free Heroku instance is used, so it can take some time when loading
|
||||
the page
|
||||
for the first time.
|
||||
|
||||
|
@ -39,46 +39,46 @@ for the first time.
|
|||
|
||||
## Features
|
||||
|
||||
* Inventory management of your electronic parts. Each part can be assigned to a category, footprint, manufacturer
|
||||
* Inventory management of your electronic parts. Each part can be assigned to a category, footprint, manufacturer,
|
||||
and multiple store locations and price information. Parts can be grouped using tags. You can associate various files
|
||||
like datasheets or pictures with the parts.
|
||||
* Multi-Language support (currently German, English, Russian, Japanese and French (experimental))
|
||||
* Multi-language support (currently German, English, Russian, Japanese, French, Czech, Danish, and Chinese)
|
||||
* 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 setup.
|
||||
Password reset via email can be set up.
|
||||
* 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.
|
||||
* Import/Export system for parts and data structure. 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
|
||||
* Event log: Track what changes happen 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.
|
||||
* MySQL and SQLite supported as database backends
|
||||
* Responsive design: You can use Part-DB on your PC, your tablet, and your smartphone using the same interface.
|
||||
* MySQL, SQLite and PostgreSQL are supported as database backends
|
||||
* 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)
|
||||
* Automatic thumbnail generation for pictures
|
||||
* Use cloud providers (like Octopart, Digikey, farnell or TME) to automatically get part information, datasheets and
|
||||
* Use cloud providers (like Octopart, Digikey, Farnell, LCSC or TME) to automatically get part information, datasheets, and
|
||||
prices for parts
|
||||
* API to access Part-DB from other applications/scripts
|
||||
* [Integration with KiCad](https://docs.part-db.de/usage/eda_integration.html): Use Part-DB as central datasource for your
|
||||
KiCad and see available parts from Part-DB directly inside KiCad.
|
||||
* [Integration with KiCad](https://docs.part-db.de/usage/eda_integration.html): Use Part-DB as the central datasource for your
|
||||
KiCad and see available parts from Part-DB directly inside KiCad.
|
||||
|
||||
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.
|
||||
With these features, Part-DB is useful to hobbyists, who want to keep track of their private electronic parts inventory,
|
||||
or maker spaces, where many users should have (controlled) access to the shared inventory.
|
||||
|
||||
Part-DB is also used by small companies and universities for managing their inventory.
|
||||
|
||||
## Requirements
|
||||
|
||||
* A **web server** (like Apache2 or nginx) that is capable of
|
||||
running [Symfony 5](https://symfony.com/doc/current/reference/requirements.html),
|
||||
running [Symfony 6](https://symfony.com/doc/current/reference/requirements.html),
|
||||
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** (>= 18.0) is needed.
|
||||
* A **MySQL** (at least 5.7) /**MariaDB** (at least 10.4) database server, or **PostgreSQL** 10+ if you do not want to use SQLite.
|
||||
* Shell access to your server is highly recommended!
|
||||
* For building the client-side assets **yarn** and **nodejs** (>= 18.0) is needed.
|
||||
|
||||
## Installation
|
||||
|
||||
|
@ -88,8 +88,8 @@ read [this](https://docs.part-db.de/upgrade_legacy.html) first.
|
|||
*Hint:* A docker image is available under [jbtronics/part-db1](https://hub.docker.com/r/jbtronics/part-db1). How to set
|
||||
up Part-DB via docker is described [here](https://docs.part-db.de/installation/installation_docker.html).
|
||||
|
||||
**Below you find some very rough outline of the installation process, see [here](https://docs.part-db.de/installation/)
|
||||
for a detailed guide how to install Part-DB.**
|
||||
**Below you find a very rough outline of the installation process, see [here](https://docs.part-db.de/installation/)
|
||||
for a detailed guide on how to install Part-DB.**
|
||||
|
||||
1. Copy or clone this repository into a folder on your server.
|
||||
2. Configure your webserver to serve from the `public/` folder.
|
||||
|
@ -107,13 +107,13 @@ for a detailed guide how to install Part-DB.**
|
|||
6. _Optional_ (speeds up first load): Warmup cache: `php bin/console cache:warmup`
|
||||
7. Upgrade database to new scheme (or create it, when it was empty): `php bin/console doctrine:migrations:migrate` and
|
||||
follow the instructions given. During the process the password for the admin is user is shown. Copy it. **Caution**:
|
||||
This steps tamper with your database and could potentially destroy it. So make sure to make a backup of your
|
||||
These steps tamper with your database and could potentially destroy it. So make sure to make a backup of your
|
||||
database.
|
||||
8. You can configure Part-DB via `config/parameters.yaml`. You should check if settings match your expectations, after
|
||||
8. You can configure Part-DB via `config/parameters.yaml`. You should check if settings match your expectations after
|
||||
you installed/upgraded Part-DB. Check if `partdb.default_currency` matches your mainly used currency (this can not be
|
||||
changed after creating price information).
|
||||
Run `php bin/console cache:clear` when you changed something.
|
||||
9. Access Part-DB in your browser (under the URL you put it) and login with user *admin*. Password is the one outputted
|
||||
Run `php bin/console cache:clear` when you change something.
|
||||
9. Access Part-DB in your browser (under the URL you put it) and log in with user *admin*. Password is the one outputted
|
||||
during DB setup.
|
||||
If you can not remember the password, set a new one with `php bin/console app:set-password admin`. You can create
|
||||
new users with the admin user and start using Part-DB.
|
||||
|
@ -122,23 +122,23 @@ When you want to upgrade to a newer version, then just copy the new files into t
|
|||
and repeat the steps 4. to 7.
|
||||
|
||||
Normally a random password is generated when the admin user is created during initial database creation,
|
||||
however you can set the initial admin password, by setting the `INITIAL_ADMIN_PW` env var.
|
||||
however, you can set the initial admin password, by setting the `INITIAL_ADMIN_PW` env var.
|
||||
|
||||
You can configure Part-DB to your needs by changing environment variables in the `.env.local` file.
|
||||
See [here](https://docs.part-db.de/configuration.html) for more information.
|
||||
|
||||
### Reverse proxy
|
||||
|
||||
If you are using a reverse proxy, you have to ensure that the proxies sets the `X-Forwarded-*` headers correctly, or you
|
||||
If you are using a reverse proxy, you have to ensure that the proxies set the `X-Forwarded-*` headers correctly, or you
|
||||
will get HTTP/HTTPS mixup and wrong hostnames.
|
||||
If the reverse proxy is on a different server (or it cannot access Part-DB via localhost) you have to set
|
||||
the `TRUSTED_PROXIES` env variable to match your reverse proxies IP-address (or IP block). You can do this in
|
||||
the `TRUSTED_PROXIES` env variable to match your reverse proxy's IP address (or IP block). You can do this in
|
||||
your `.env.local` or (when using docker) in your `docker-compose.yml` file.
|
||||
|
||||
## Donate for development
|
||||
|
||||
If you want to donate to the Part-DB developer, see the sponsor button in the top bar (next to the repo name).
|
||||
There you will find various methods to support development on a monthly or a one time base.
|
||||
There you will find various methods to support development on a monthly or a one-time base.
|
||||
|
||||
## Built with
|
||||
|
||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
1.10.5
|
||||
1.17.1
|
||||
|
|
|
@ -128,6 +128,8 @@ const PLACEHOLDERS = [
|
|||
['[[BARCODE_QR]]', 'QR code linking to this element'],
|
||||
['[[BARCODE_C128]]', 'Code 128 barcode linking to this element'],
|
||||
['[[BARCODE_C39]]', 'Code 39 barcode linking to this element'],
|
||||
['[[BARCODE_C93]]', 'Code 93 barcode linking to this element'],
|
||||
['[[BARCODE_DATAMATRIX]]', 'Datamatrix code linking to this element'],
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
|
@ -69,6 +69,8 @@ Object.assign( window.CKEDITOR_TRANSLATIONS[ 'de' ].dictionary, {
|
|||
'QR code linking to this element': 'QR Code verknüpft mit diesem Element',
|
||||
'Code 128 barcode linking to this element': 'Code 128 Barcode verknüpft mit diesem Element',
|
||||
'Code 39 barcode linking to this element': 'Code 39 Barcode verknüpft mit diesem Element',
|
||||
'Code 93 barcode linking to this element': 'Code 93 Barcode verknüpft mit diesem Element',
|
||||
'Datamatrix code linking to this element': 'Datamatrix Code verknüpft mit diesem Element',
|
||||
|
||||
'Location ID': 'Lagerort ID',
|
||||
'Name': 'Name',
|
||||
|
|
|
@ -88,5 +88,8 @@ export default class extends Controller {
|
|||
} else {
|
||||
this.hideSidebar();
|
||||
}
|
||||
|
||||
//Hide the tootip on the button
|
||||
this._toggle_button.blur();
|
||||
}
|
||||
}
|
|
@ -23,6 +23,12 @@ import "tom-select/dist/css/tom-select.bootstrap5.css";
|
|||
import '../../css/components/tom-select_extensions.css';
|
||||
import TomSelect from "tom-select";
|
||||
|
||||
import TomSelect_click_to_edit from '../../tomselect/click_to_edit/click_to_edit'
|
||||
import TomSelect_autoselect_typed from '../../tomselect/autoselect_typed/autoselect_typed'
|
||||
|
||||
TomSelect.define('click_to_edit', TomSelect_click_to_edit)
|
||||
TomSelect.define('autoselect_typed', TomSelect_autoselect_typed)
|
||||
|
||||
export default class extends Controller {
|
||||
_tomSelect;
|
||||
|
||||
|
@ -46,6 +52,12 @@ export default class extends Controller {
|
|||
}
|
||||
return '<div>' + escape(data.label) + '</div>';
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
'autoselect_typed': {},
|
||||
'click_to_edit': {},
|
||||
'clear_button': {},
|
||||
"restore_on_backspace": {}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -53,6 +53,7 @@ export default class extends Controller {
|
|||
|
||||
const config = {
|
||||
language: language,
|
||||
licenseKey: "GPL",
|
||||
}
|
||||
|
||||
const watchdog = new EditorWatchdog();
|
||||
|
|
|
@ -75,13 +75,49 @@ export default class extends Controller {
|
|||
|
||||
//Insert new html after the last child element
|
||||
//If the table has a tbody, insert it there
|
||||
//Afterwards return the newly created row
|
||||
if(targetTable.tBodies[0]) {
|
||||
targetTable.tBodies[0].insertAdjacentHTML('beforeend', newElementStr);
|
||||
return targetTable.tBodies[0].lastElementChild;
|
||||
} else { //Otherwise just insert it
|
||||
targetTable.insertAdjacentHTML('beforeend', newElementStr);
|
||||
return targetTable.lastElementChild;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This action opens a file dialog to select multiple files and then creates a new element for each file, where
|
||||
* the file is assigned to the input field.
|
||||
* This should only be used for attachments collection types
|
||||
* @param event
|
||||
*/
|
||||
uploadMultipleFiles(event) {
|
||||
//Open a file dialog to select multiple files
|
||||
const input = document.createElement('input');
|
||||
input.type = 'file';
|
||||
input.multiple = true;
|
||||
input.click();
|
||||
|
||||
input.addEventListener('change', (event) => {
|
||||
//Create a element for each file
|
||||
|
||||
for (let i = 0; i < input.files.length; i++) {
|
||||
const file = input.files[i];
|
||||
|
||||
const newElement = this.createElement(event);
|
||||
const rowInput = newElement.querySelector("input[type='file']");
|
||||
|
||||
//We can not directly assign the file to the input, so we have to create a new DataTransfer object
|
||||
const dataTransfer = new DataTransfer();
|
||||
dataTransfer.items.add(file);
|
||||
|
||||
rowInput.files = dataTransfer.files;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Similar to createEvent Pricedetails need some special handling to fill min amount
|
||||
* @param event
|
||||
|
|
|
@ -24,18 +24,25 @@ import 'datatables.net-bs5/css/dataTables.bootstrap5.css'
|
|||
import 'datatables.net-buttons-bs5/css/buttons.bootstrap5.css'
|
||||
import 'datatables.net-fixedheader-bs5/css/fixedHeader.bootstrap5.css'
|
||||
import 'datatables.net-responsive-bs5/css/responsive.bootstrap5.css';
|
||||
import 'datatables.net-select-bs5/css/select.bootstrap5.css';
|
||||
|
||||
//Use our own styles for the select extension which fit the bootstrap theme better
|
||||
//import 'datatables.net-select-bs5/css/select.bootstrap5.css';
|
||||
import '../../../css/components/datatables_select_bs5.css';
|
||||
|
||||
//JS
|
||||
import 'datatables.net-bs5';
|
||||
import 'datatables.net-buttons-bs5';
|
||||
import 'datatables.net-buttons/js/buttons.colVis.js';
|
||||
import 'datatables.net-fixedheader-bs5';
|
||||
import 'datatables.net-select-bs5';
|
||||
import 'datatables.net-colreorder-bs5';
|
||||
import 'datatables.net-responsive-bs5';
|
||||
import '../../../js/lib/datatables';
|
||||
|
||||
//import 'datatables.net-select-bs5';
|
||||
//Use the local version containing the fix for the select extension
|
||||
import '../../../js/lib/dataTables.select.mjs';
|
||||
|
||||
|
||||
const EVENT_DT_LOADED = 'dt:loaded';
|
||||
|
||||
export default class extends Controller {
|
||||
|
@ -132,7 +139,7 @@ export default class extends Controller {
|
|||
if(this.isSelectable()) {
|
||||
options.select = {
|
||||
style: 'multi+shift',
|
||||
selector: 'td.select-checkbox'
|
||||
selector: 'td.dt-select',
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -145,6 +152,12 @@ export default class extends Controller {
|
|||
|
||||
//Fix height of the length selector
|
||||
promise.then((dt) => {
|
||||
|
||||
//Draw the rows to make sure the correct status text is displayed ("No matching records found" instead of "Loading...")
|
||||
if (dt.data().length === 0) {
|
||||
dt.rows().draw()
|
||||
}
|
||||
|
||||
//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
|
||||
|
@ -180,27 +193,6 @@ 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));
|
||||
|
||||
|
|
200
assets/controllers/elements/part_search_controller.js
Normal file
200
assets/controllers/elements/part_search_controller.js
Normal file
|
@ -0,0 +1,200 @@
|
|||
/*
|
||||
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
|
||||
*
|
||||
* Copyright (C) 2019 - 2024 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 { autocomplete } from '@algolia/autocomplete-js';
|
||||
//import "@algolia/autocomplete-theme-classic/dist/theme.css";
|
||||
import "../../css/components/autocomplete_bootstrap_theme.css";
|
||||
import { createLocalStorageRecentSearchesPlugin } from '@algolia/autocomplete-plugin-recent-searches';
|
||||
import {marked} from "marked";
|
||||
|
||||
import {
|
||||
trans,
|
||||
SEARCH_PLACEHOLDER,
|
||||
SEARCH_SUBMIT,
|
||||
STATISTICS_PARTS
|
||||
} from '../../translator';
|
||||
|
||||
|
||||
/**
|
||||
* This controller is responsible for the search fields in the navbar and the homepage.
|
||||
* It uses the Algolia Autocomplete library to provide a fast and responsive search.
|
||||
*/
|
||||
export default class extends Controller {
|
||||
|
||||
static targets = ["input"];
|
||||
|
||||
_autocomplete;
|
||||
|
||||
// Highlight the search query in the results
|
||||
_highlight = (text, query) => {
|
||||
if (!text) return text;
|
||||
if (!query) return text;
|
||||
|
||||
const HIGHLIGHT_PRE_TAG = '__aa-highlight__'
|
||||
const HIGHLIGHT_POST_TAG = '__/aa-highlight__'
|
||||
|
||||
const escaped = query.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
|
||||
const regex = new RegExp(escaped, 'gi');
|
||||
|
||||
return text.replace(regex, (match) => `${HIGHLIGHT_PRE_TAG}${match}${HIGHLIGHT_POST_TAG}`);
|
||||
}
|
||||
|
||||
initialize() {
|
||||
// The endpoint for searching parts
|
||||
const base_url = this.element.dataset.autocomplete;
|
||||
// The URL template for the part detail pages
|
||||
const part_detail_uri_template = this.element.dataset.detailUrl;
|
||||
|
||||
//The URL of the placeholder picture
|
||||
const placeholder_image = this.element.dataset.placeholderImage;
|
||||
|
||||
//If the element is in navbar mode, or not
|
||||
const navbar_mode = this.element.dataset.navbarMode === "true";
|
||||
|
||||
const that = this;
|
||||
|
||||
const recentSearchesPlugin = createLocalStorageRecentSearchesPlugin({
|
||||
key: 'RECENT_SEARCH',
|
||||
limit: 5,
|
||||
});
|
||||
|
||||
this._autocomplete = autocomplete({
|
||||
container: this.element,
|
||||
//Place the panel in the navbar, if the element is in navbar mode
|
||||
panelContainer: navbar_mode ? document.getElementById("navbar-search-form") : document.body,
|
||||
panelPlacement: this.element.dataset.panelPlacement,
|
||||
plugins: [recentSearchesPlugin],
|
||||
openOnFocus: true,
|
||||
placeholder: trans(SEARCH_PLACEHOLDER),
|
||||
translations: {
|
||||
submitButtonTitle: trans(SEARCH_SUBMIT)
|
||||
},
|
||||
|
||||
// Use a navigator compatible with turbo:
|
||||
navigator: {
|
||||
navigate({ itemUrl }) {
|
||||
window.Turbo.visit(itemUrl, { action: "advance" });
|
||||
},
|
||||
navigateNewTab({ itemUrl }) {
|
||||
const windowReference = window.open(itemUrl, '_blank', 'noopener');
|
||||
|
||||
if (windowReference) {
|
||||
windowReference.focus();
|
||||
}
|
||||
},
|
||||
navigateNewWindow({ itemUrl }) {
|
||||
window.open(itemUrl, '_blank', 'noopener');
|
||||
},
|
||||
},
|
||||
|
||||
// If the form is submitted, forward the term to the form
|
||||
onSubmit({state, event, ...setters}) {
|
||||
//Put the current text into each target input field
|
||||
const input = that.inputTarget;
|
||||
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
|
||||
//Do not submit the form, if the input is empty
|
||||
if (state.query === "") {
|
||||
return;
|
||||
}
|
||||
|
||||
input.value = state.query;
|
||||
input.form.requestSubmit();
|
||||
},
|
||||
|
||||
|
||||
getSources({ query }) {
|
||||
return [
|
||||
// The parts source
|
||||
{
|
||||
sourceId: 'parts',
|
||||
getItems() {
|
||||
const url = base_url.replace('__QUERY__', encodeURIComponent(query));
|
||||
|
||||
const data = fetch(url)
|
||||
.then((response) => response.json())
|
||||
;
|
||||
|
||||
//Iterate over all fields besides the id and highlight them
|
||||
const fields = ["name", "description", "category", "footprint"];
|
||||
|
||||
data.then((items) => {
|
||||
items.forEach((item) => {
|
||||
for (const field of fields) {
|
||||
item[field] = that._highlight(item[field], query);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return data;
|
||||
},
|
||||
getItemUrl({ item }) {
|
||||
return part_detail_uri_template.replace('__ID__', item.id);
|
||||
},
|
||||
templates: {
|
||||
header({ html }) {
|
||||
return html`<span class="aa-SourceHeaderTitle">${trans(STATISTICS_PARTS)}</span>
|
||||
<div class="aa-SourceHeaderLine" />`;
|
||||
},
|
||||
item({item, components, html}) {
|
||||
const details_url = part_detail_uri_template.replace('__ID__', item.id);
|
||||
|
||||
return html`
|
||||
<a class="aa-ItemLink" href="${details_url}">
|
||||
<div class="aa-ItemContent">
|
||||
<div class="aa-ItemIcon aa-ItemIcon--picture aa-ItemIcon--alignTop">
|
||||
<img src="${item.image !== "" ? item.image : placeholder_image}" alt="${item.name}" width="30" height="30"/>
|
||||
</div>
|
||||
<div class="aa-ItemContentBody">
|
||||
<div class="aa-ItemContentTitle">
|
||||
<b>
|
||||
${components.Highlight({hit: item, attribute: 'name'})}
|
||||
</b>
|
||||
</div>
|
||||
<div class="aa-ItemContentDescription">
|
||||
${components.Highlight({hit: item, attribute: 'description'})}
|
||||
${item.category ? html`<p class="m-0"><span class="fa-solid fa-tags fa-fw"></span>${components.Highlight({hit: item, attribute: 'category'})}</p>` : ""}
|
||||
${item.footprint ? html`<p class="m-0"><span class="fa-solid fa-microchip fa-fw"></span>${components.Highlight({hit: item, attribute: 'footprint'})}</p>` : ""}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
`;
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
},
|
||||
});
|
||||
|
||||
//Try to find the input field and register a defocus handler. This is necessarry, as by default the autocomplete
|
||||
//lib has problems when multiple inputs are present on the page. (see https://github.com/algolia/autocomplete/issues/1216)
|
||||
const inputs = this.element.getElementsByClassName('aa-Input');
|
||||
for (const input of inputs) {
|
||||
input.addEventListener('blur', () => {
|
||||
this._autocomplete.setIsOpen(false);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -23,6 +23,12 @@ import "tom-select/dist/css/tom-select.bootstrap5.css";
|
|||
import '../../css/components/tom-select_extensions.css';
|
||||
import TomSelect from "tom-select";
|
||||
|
||||
import TomSelect_click_to_edit from '../../tomselect/click_to_edit/click_to_edit'
|
||||
import TomSelect_autoselect_typed from '../../tomselect/autoselect_typed/autoselect_typed'
|
||||
|
||||
TomSelect.define('click_to_edit', TomSelect_click_to_edit)
|
||||
TomSelect.define('autoselect_typed', TomSelect_autoselect_typed)
|
||||
|
||||
/**
|
||||
* This is the frontend controller for StaticFileAutocompleteType form element.
|
||||
* Basically it loads a text file from the given url (via data-url) and uses it as a source for the autocomplete.
|
||||
|
@ -46,7 +52,13 @@ export default class extends Controller {
|
|||
orderField: 'text',
|
||||
|
||||
//This a an ugly solution to disable the delimiter parsing of the TomSelect plugin
|
||||
delimiter: 'VERY_L0NG_D€LIMITER_WHICH_WILL_NEVER_BE_ENCOUNTERED_IN_A_STRING'
|
||||
delimiter: 'VERY_L0NG_D€LIMITER_WHICH_WILL_NEVER_BE_ENCOUNTERED_IN_A_STRING',
|
||||
plugins: {
|
||||
'autoselect_typed': {},
|
||||
'click_to_edit': {},
|
||||
'clear_button': {},
|
||||
'restore_on_backspace': {}
|
||||
}
|
||||
};
|
||||
|
||||
if (this.element.dataset.url) {
|
||||
|
|
|
@ -24,6 +24,8 @@ import {Controller} from "@hotwired/stimulus";
|
|||
|
||||
import {trans, ENTITY_SELECT_GROUP_NEW_NOT_ADDED_TO_DB} from '../../translator.js'
|
||||
|
||||
import TomSelect_autoselect_typed from '../../tomselect/autoselect_typed/autoselect_typed'
|
||||
TomSelect.define('autoselect_typed', TomSelect_autoselect_typed)
|
||||
|
||||
export default class extends Controller {
|
||||
_tomSelect;
|
||||
|
@ -38,11 +40,20 @@ export default class extends Controller {
|
|||
const allowAdd = this.element.getAttribute("data-allow-add") === "true";
|
||||
const addHint = this.element.getAttribute("data-add-hint") ?? "";
|
||||
|
||||
|
||||
|
||||
|
||||
let settings = {
|
||||
allowEmptyOption: true,
|
||||
selectOnTab: true,
|
||||
maxOptions: null,
|
||||
create: allowAdd ? this.createItem.bind(this) : false,
|
||||
createFilter: this.createFilter.bind(this),
|
||||
|
||||
// This three options allow us to paste element names with commas: (see issue #538)
|
||||
maxItems: 1,
|
||||
delimiter: "$$VERY_LONG_DELIMITER_THAT_SHOULD_NEVER_APPEAR$$",
|
||||
splitOn: null,
|
||||
|
||||
searchField: [
|
||||
{field: "text", weight : 2},
|
||||
|
@ -53,7 +64,21 @@ export default class extends Controller {
|
|||
render: {
|
||||
item: this.renderItem.bind(this),
|
||||
option: this.renderOption.bind(this),
|
||||
option_create: function(data, escape) {
|
||||
option_create: (data, escape) => {
|
||||
//If the input starts with "->", we prepend the current selected value, for easier extension of existing values
|
||||
//This here handles the display part, while the createItem function handles the actual creation
|
||||
if (data.input.startsWith("->")) {
|
||||
//Get current selected value
|
||||
const current = this._tomSelect.getItem(this._tomSelect.getValue()).textContent.replaceAll("→", "->").trim();
|
||||
//Prepend it to the input
|
||||
if (current) {
|
||||
data.input = current + " " + data.input;
|
||||
} else {
|
||||
//If there is no current value, we remove the "->"
|
||||
data.input = data.input.substring(2);
|
||||
}
|
||||
}
|
||||
|
||||
return '<div class="create"><i class="fa-solid fa-plus fa-fw"></i> <strong>' + escape(data.input) + '</strong>… ' +
|
||||
'<small class="text-muted float-end">(' + addHint +')</small>' +
|
||||
'</div>';
|
||||
|
@ -63,14 +88,39 @@ export default class extends Controller {
|
|||
//Add callbacks to update validity
|
||||
onInitialize: this.updateValidity.bind(this),
|
||||
onChange: this.updateValidity.bind(this),
|
||||
|
||||
plugins: {
|
||||
"autoselect_typed": {},
|
||||
}
|
||||
};
|
||||
|
||||
//Add clear button plugin, if an empty option is present
|
||||
if (this.element.querySelector("option[value='']") !== null) {
|
||||
settings.plugins["clear_button"] = {};
|
||||
}
|
||||
|
||||
this._tomSelect = new TomSelect(this.element, settings);
|
||||
//Do not do a sync here as this breaks the initial rendering of the empty option
|
||||
//this._tomSelect.sync();
|
||||
}
|
||||
|
||||
createItem(input, callback) {
|
||||
|
||||
//If the input starts with "->", we prepend the current selected value, for easier extension of existing values
|
||||
if (input.startsWith("->")) {
|
||||
//Get current selected value
|
||||
let current = this._tomSelect.getItem(this._tomSelect.getValue()).textContent.replaceAll("→", "->").trim();
|
||||
//Replace no break spaces with normal spaces
|
||||
current = current.replaceAll("\u00A0", " ");
|
||||
//Prepend it to the input
|
||||
if (current) {
|
||||
input = current + " " + input;
|
||||
} else {
|
||||
//If there is no current value, we remove the "->"
|
||||
input = input.substring(2);
|
||||
}
|
||||
}
|
||||
|
||||
callback({
|
||||
//$%$ is a special value prefix, that is used to identify items, that are not yet in the DB
|
||||
value: '$%$' + input,
|
||||
|
@ -79,6 +129,31 @@ export default class extends Controller {
|
|||
});
|
||||
}
|
||||
|
||||
createFilter(input) {
|
||||
|
||||
//Normalize the input (replace spacing around arrows)
|
||||
if (input.includes("->")) {
|
||||
const inputs = input.split("->");
|
||||
inputs.forEach((value, index) => {
|
||||
inputs[index] = value.trim();
|
||||
});
|
||||
input = inputs.join("->");
|
||||
} else {
|
||||
input = input.trim();
|
||||
}
|
||||
|
||||
const options = this._tomSelect.options;
|
||||
//Iterate over all options and check if the input is already present
|
||||
for (let index in options) {
|
||||
const option = options[index];
|
||||
if (option.path === input) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
updateValidity() {
|
||||
//Mark this input as invalid, if the selected option is disabled
|
||||
|
|
|
@ -23,14 +23,21 @@ import "tom-select/dist/css/tom-select.bootstrap5.css";
|
|||
import '../../css/components/tom-select_extensions.css';
|
||||
import TomSelect from "tom-select";
|
||||
|
||||
import TomSelect_click_to_edit from '../../tomselect/click_to_edit/click_to_edit'
|
||||
import TomSelect_autoselect_typed from '../../tomselect/autoselect_typed/autoselect_typed'
|
||||
|
||||
TomSelect.define('click_to_edit', TomSelect_click_to_edit)
|
||||
TomSelect.define('autoselect_typed', TomSelect_autoselect_typed)
|
||||
|
||||
export default class extends Controller {
|
||||
_tomSelect;
|
||||
|
||||
connect() {
|
||||
let settings = {
|
||||
plugins: {
|
||||
remove_button:{
|
||||
}
|
||||
remove_button:{},
|
||||
'autoselect_typed': {},
|
||||
'click_to_edit': {},
|
||||
},
|
||||
persistent: false,
|
||||
selectOnTab: true,
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
import {Controller} from "@hotwired/stimulus";
|
||||
//import * as ZXing from "@zxing/library";
|
||||
|
||||
import {Html5QrcodeScanner, Html5Qrcode} from "html5-qrcode";
|
||||
import {Html5QrcodeScanner, Html5Qrcode} from "@part-db/html5-qrcode";
|
||||
|
||||
/* stimulusFetch: 'lazy' */
|
||||
export default class extends Controller {
|
||||
|
@ -50,7 +50,7 @@ export default class extends Controller {
|
|||
});
|
||||
|
||||
this._scanner = new Html5QrcodeScanner(this.element.id, {
|
||||
fps: 2,
|
||||
fps: 10,
|
||||
qrbox: qrboxFunction,
|
||||
experimentalFeatures: {
|
||||
//This option improves reading quality on android chrome
|
||||
|
@ -61,6 +61,11 @@ export default class extends Controller {
|
|||
this._scanner.render(this.onScanSuccess.bind(this));
|
||||
}
|
||||
|
||||
disconnect() {
|
||||
this._scanner.pause();
|
||||
this._scanner.clear();
|
||||
}
|
||||
|
||||
onScanSuccess(decodedText, decodedResult) {
|
||||
//Put our decoded Text into the input box
|
||||
document.getElementById('scan_dialog_input').value = decodedText;
|
||||
|
|
|
@ -25,9 +25,20 @@ import "katex/dist/katex.css";
|
|||
export default class extends Controller {
|
||||
static targets = ["input", "preview"];
|
||||
|
||||
static values = {
|
||||
unit: {type: Boolean, default: false} //Render as upstanding (non-italic) text, useful for units
|
||||
}
|
||||
|
||||
updatePreview()
|
||||
{
|
||||
katex.render(this.inputTarget.value, this.previewTarget, {
|
||||
let value = "";
|
||||
if (this.unitValue) {
|
||||
value = "\\mathrm{" + this.inputTarget.value + "}";
|
||||
} else {
|
||||
value = this.inputTarget.value;
|
||||
}
|
||||
|
||||
katex.render(value, this.previewTarget, {
|
||||
throwOnError: false,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -22,6 +22,13 @@ import TomSelect from "tom-select";
|
|||
import katex from "katex";
|
||||
import "katex/dist/katex.css";
|
||||
|
||||
|
||||
import TomSelect_click_to_edit from '../../tomselect/click_to_edit/click_to_edit'
|
||||
import TomSelect_autoselect_typed from '../../tomselect/autoselect_typed/autoselect_typed'
|
||||
|
||||
TomSelect.define('click_to_edit', TomSelect_click_to_edit)
|
||||
TomSelect.define('autoselect_typed', TomSelect_autoselect_typed)
|
||||
|
||||
/* stimulusFetch: 'lazy' */
|
||||
export default class extends Controller
|
||||
{
|
||||
|
@ -53,7 +60,10 @@ export default class extends Controller
|
|||
connect() {
|
||||
const settings = {
|
||||
plugins: {
|
||||
clear_button:{}
|
||||
'autoselect_typed': {},
|
||||
'click_to_edit': {},
|
||||
'clear_button': {},
|
||||
'restore_on_backspace': {}
|
||||
},
|
||||
persistent: false,
|
||||
maxItems: 1,
|
||||
|
|
|
@ -111,4 +111,11 @@ ul.structural_link li a:hover {
|
|||
.permission-checkbox:checked {
|
||||
background-color: var(--bs-success);
|
||||
border-color: var(--bs-success);
|
||||
}
|
||||
|
||||
/***********************************************
|
||||
* Katex rendering with same height as text
|
||||
***********************************************/
|
||||
.katex-same-height-as-text .katex {
|
||||
font-size: 1.0em;
|
||||
}
|
|
@ -51,7 +51,6 @@
|
|||
.part-table-image {
|
||||
max-height: 40px;
|
||||
object-fit: contain;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.part-info-image {
|
||||
|
@ -61,4 +60,4 @@
|
|||
|
||||
.object-fit-cover {
|
||||
object-fit: cover;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -108,8 +108,8 @@ body {
|
|||
.back-to-top {
|
||||
cursor: pointer;
|
||||
position: fixed;
|
||||
bottom: 20px;
|
||||
right: 20px;
|
||||
bottom: 60px;
|
||||
right: 40px;
|
||||
display:none;
|
||||
z-index: 1030;
|
||||
}
|
||||
|
|
|
@ -63,10 +63,6 @@ table.dataTable > tbody > tr.selected > td > a {
|
|||
margin-block-end: 0;
|
||||
}
|
||||
|
||||
.card-footer-table {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
table.dataTable {
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
|
@ -84,7 +80,7 @@ th.select-checkbox {
|
|||
* Datatables definitions/overrides
|
||||
********************************************************************/
|
||||
|
||||
.dataTables_length {
|
||||
.dt-length {
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
|
@ -94,6 +90,16 @@ table.dataTable tr.selected td.select-checkbox:after
|
|||
margin-top: -20px !important;
|
||||
}
|
||||
|
||||
/** Show pagination right aligned */
|
||||
.dt-paging .pagination {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
/** Fix table row coloring */
|
||||
table.table.dataTable > :not(caption) > * > * {
|
||||
background-color: var(--bs-table-bg);
|
||||
}
|
||||
|
||||
|
||||
/******************************************************
|
||||
Classes for Datatables export
|
||||
|
@ -103,53 +109,4 @@ 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;
|
||||
}
|
||||
}
|
1120
assets/css/components/autocomplete_bootstrap_theme.css
Normal file
1120
assets/css/components/autocomplete_bootstrap_theme.css
Normal file
File diff suppressed because it is too large
Load diff
|
@ -24,9 +24,8 @@
|
|||
/** Should be the same settings, as in label_style.css */
|
||||
.ck-html-label .ck-content {
|
||||
font-family: "DejaVu Sans Mono", monospace;
|
||||
font-size: 12px;
|
||||
font-size: 12pt;
|
||||
line-height: 1.0;
|
||||
font-size-adjust: 1.5;
|
||||
}
|
||||
|
||||
.ck-html-label .ck-content p {
|
||||
|
|
69
assets/css/components/datatables_select_bs5.css
Normal file
69
assets/css/components/datatables_select_bs5.css
Normal file
|
@ -0,0 +1,69 @@
|
|||
/******************************************************************************************
|
||||
* This styles the checkboxes of the select extension exactly like the ones in bootstrap 5
|
||||
******************************************************************************************/
|
||||
|
||||
table.dataTable > tbody > tr > .selected {
|
||||
background-color: var(--bs-primary-bg-subtle) !important;
|
||||
color: white;
|
||||
}
|
||||
table.dataTable > tbody > tr > .dt-select {
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
table.dataTable > thead > tr > .dt-select {
|
||||
text-align: center;
|
||||
}
|
||||
table.dataTable input.dt-select-checkbox {
|
||||
--bs-form-check-bg: var(--bs-body-bg);
|
||||
flex-shrink: 0;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
margin-top: 0.25em;
|
||||
vertical-align: top;
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
background-color: var(--bs-form-check-bg);
|
||||
background-image: var(--bs-form-check-bg-image);
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
background-size: contain;
|
||||
border: var(--bs-border-width) solid var(--bs-border-color);
|
||||
-webkit-print-color-adjust: exact;
|
||||
color-adjust: exact;
|
||||
print-color-adjust: exact;
|
||||
border-radius: 0.25em;
|
||||
}
|
||||
|
||||
table.dataTable input.dt-select-checkbox:checked {
|
||||
background-color: rgb(var(--bs-secondary-rgb));
|
||||
border-color: rgb(var(--bs-secondary-rgb));
|
||||
--bs-form-check-bg-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='m6 10 3 3 6-6'/%3e%3c/svg%3e");
|
||||
}
|
||||
|
||||
table.dataTable input.dt-select-checkbox:indeterminate {
|
||||
background-color: rgb(var(--bs-secondary-rgb));
|
||||
border-color: rgb(var(--bs-secondary-rgb));
|
||||
--bs-form-check-bg-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10h8'/%3e%3c/svg%3e");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
div.dt-container span.select-info,
|
||||
div.dt-container span.select-item {
|
||||
margin-left: 0.5em;
|
||||
}
|
||||
|
||||
|
||||
@media screen and (max-width: 640px) {
|
||||
div.dt-container span.select-info,
|
||||
div.dt-container span.select-item {
|
||||
margin-left: 0;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
table.dataTable.table-sm tbody td.select-checkbox::before {
|
||||
margin-top: -9px;
|
||||
}
|
||||
|
|
@ -44,4 +44,18 @@ import "./register_events";
|
|||
import "./tristate_checkboxes";
|
||||
|
||||
//Define jquery globally
|
||||
window.$ = window.jQuery = require("jquery")
|
||||
window.$ = window.jQuery = require("jquery");
|
||||
|
||||
//Use the local WASM file for the ZXing library
|
||||
import {
|
||||
setZXingModuleOverrides,
|
||||
} from "barcode-detector/pure";
|
||||
import wasmFile from "../../node_modules/zxing-wasm/dist/reader/zxing_reader.wasm";
|
||||
setZXingModuleOverrides({
|
||||
locateFile: (path, prefix) => {
|
||||
if (path.endsWith(".wasm")) {
|
||||
return wasmFile;
|
||||
}
|
||||
return prefix + path;
|
||||
},
|
||||
});
|
1538
assets/js/lib/dataTables.select.mjs
Normal file
1538
assets/js/lib/dataTables.select.mjs
Normal file
File diff suppressed because it is too large
Load diff
|
@ -98,6 +98,15 @@
|
|||
dtOpts = config.options(dtOpts);
|
||||
}
|
||||
|
||||
//Choose the column where the className contains "select-column" and apply the select extension to its render field
|
||||
//Added for Part-DB
|
||||
for (let column of dtOpts.columns) {
|
||||
if (column.className && column.className.includes('dt-select')) {
|
||||
column.render = $.fn.dataTable.render.select();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
root.html(data.template);
|
||||
dt = $('table', root).DataTable(dtOpts);
|
||||
if (config.state !== 'none') {
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
import {Dropdown} from "bootstrap";
|
||||
import ClipboardJS from "clipboard";
|
||||
import {Modal} from "bootstrap";
|
||||
|
||||
class RegisterEventHelper {
|
||||
constructor() {
|
||||
|
@ -31,9 +32,11 @@ class RegisterEventHelper {
|
|||
//Initialize ClipboardJS
|
||||
this.registerLoadHandler(() => {
|
||||
new ClipboardJS('.btn');
|
||||
})
|
||||
});
|
||||
|
||||
this.registerModalDropRemovalOnFormSubmit();
|
||||
|
||||
|
||||
}
|
||||
|
||||
registerModalDropRemovalOnFormSubmit() {
|
||||
|
@ -43,6 +46,15 @@ class RegisterEventHelper {
|
|||
if (back_drop) {
|
||||
back_drop.remove();
|
||||
}
|
||||
|
||||
//Remove scroll-lock if it is still active
|
||||
if (document.body.classList.contains('modal-open')) {
|
||||
document.body.classList.remove('modal-open');
|
||||
|
||||
//Remove the padding-right and overflow:hidden from the body
|
||||
document.body.style.paddingRight = '';
|
||||
document.body.style.overflow = '';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
63
assets/tomselect/autoselect_typed/autoselect_typed.js
Normal file
63
assets/tomselect/autoselect_typed/autoselect_typed.js
Normal file
|
@ -0,0 +1,63 @@
|
|||
/**
|
||||
* Autoselect Typed plugin for Tomselect
|
||||
*
|
||||
* This plugin allows automatically selecting an option matching the typed text when the Tomselect element goes out of
|
||||
* focus (is blurred) and/or when the delimiter is typed.
|
||||
*
|
||||
* #select_on_blur option
|
||||
* Tomselect natively supports the "createOnBlur" option. This option picks up any remaining text in the input field
|
||||
* and uses it to create a new option and selects that option. It does behave a bit strangely though, in that it will
|
||||
* not select an already existing option when the input is blurred, so if you typed something that matches an option in
|
||||
* the list and then click outside the box (without pressing enter) the entered text is just removed (unless you have
|
||||
* allow duplicates on in which case it will create a new option).
|
||||
* This plugin fixes that, such that Tomselect will first try to select an option matching the remaining uncommitted
|
||||
* text and only when no matching option is found tries to create a new one (if createOnBlur and create is on)
|
||||
*
|
||||
* #select_on_delimiter option
|
||||
* Normally when typing the delimiter (space by default) Tomselect will try to create a new option (and select it) (if
|
||||
* create is on), but if the typed text matches an option (and allow duplicates is off) it refuses to react at all until
|
||||
* you press enter. With this option, the delimiter will also allow selecting an option, not just creating it.
|
||||
*/
|
||||
function select_current_input(self){
|
||||
if(self.isLocked){
|
||||
return
|
||||
}
|
||||
|
||||
const val = self.inputValue()
|
||||
//Do nothing if the input is empty
|
||||
if (!val) {
|
||||
return
|
||||
}
|
||||
|
||||
if (self.options[val]) {
|
||||
self.addItem(val)
|
||||
self.setTextboxValue()
|
||||
}
|
||||
}
|
||||
|
||||
export default function(plugin_options_) {
|
||||
const plugin_options = Object.assign({
|
||||
//Autoselect the typed text when the input element goes out of focus
|
||||
select_on_blur: true,
|
||||
//Autoselect the typed text when the delimiter is typed
|
||||
select_on_delimiter: true,
|
||||
}, plugin_options_);
|
||||
|
||||
const self = this
|
||||
|
||||
if(plugin_options.select_on_blur) {
|
||||
this.hook("before", "onBlur", function () {
|
||||
select_current_input(self)
|
||||
})
|
||||
}
|
||||
|
||||
if(plugin_options.select_on_delimiter) {
|
||||
this.hook("before", "onKeyPress", function (e) {
|
||||
const character = String.fromCharCode(e.keyCode || e.which);
|
||||
if (self.settings.mode === 'multi' && character === self.settings.delimiter) {
|
||||
select_current_input(self)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
93
assets/tomselect/click_to_edit/click_to_edit.js
Normal file
93
assets/tomselect/click_to_edit/click_to_edit.js
Normal file
|
@ -0,0 +1,93 @@
|
|||
/**
|
||||
* click_to_edit plugin for Tomselect
|
||||
*
|
||||
* This plugin allows editing (and selecting text in) any selected item by clicking it.
|
||||
*
|
||||
* Usually, when the user typed some text and created an item in Tomselect that item cannot be edited anymore. To make
|
||||
* a change, the item has to be deleted and retyped completely. There is also generally no way to copy text out of a
|
||||
* tomselect item. The "restore_on_backspace" plugin improves that somewhat, by allowing the user to edit an item after
|
||||
* pressing backspace. However, it is somewhat confusing to first have to focus the field an then hit backspace in order
|
||||
* to copy a piece of text. It may also not be immediately obvious for editing.
|
||||
* This plugin transforms an item into editable text when it is clicked, e.g. when the user tries to place the caret
|
||||
* within an item or when they try to drag across the text to highlight it.
|
||||
* It also plays nice with the remove_button plugin which still removes (deselects) an option entirely.
|
||||
*
|
||||
* It is recommended to also enable the autoselect_typed plugin when using this plugin. Without it, the text in the
|
||||
* input field (i.e. the item that was just clicked) is lost when the user clicks outside the field. Also, when the user
|
||||
* clicks an option (making it text) and then tries to enter another one by entering the delimiter (e.g. space) nothing
|
||||
* happens until enter is pressed or the text is changed from what it was.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Return a dom element from either a dom query string, jQuery object, a dom element or html string
|
||||
* https://stackoverflow.com/questions/494143/creating-a-new-dom-element-from-an-html-string-using-built-in-dom-methods-or-pro/35385518#35385518
|
||||
*
|
||||
* param query should be {}
|
||||
*/
|
||||
const getDom = query => {
|
||||
if (query.jquery) {
|
||||
return query[0];
|
||||
}
|
||||
if (query instanceof HTMLElement) {
|
||||
return query;
|
||||
}
|
||||
if (isHtmlString(query)) {
|
||||
var tpl = document.createElement('template');
|
||||
tpl.innerHTML = query.trim(); // Never return a text node of whitespace as the result
|
||||
return tpl.content.firstChild;
|
||||
}
|
||||
return document.querySelector(query);
|
||||
};
|
||||
const isHtmlString = arg => {
|
||||
if (typeof arg === 'string' && arg.indexOf('<') > -1) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
function plugin(plugin_options_) {
|
||||
const self = this
|
||||
|
||||
const plugin_options = Object.assign({
|
||||
//If there is unsubmitted text in the input field, should that text be automatically used to select a matching
|
||||
//element? If this is off, clicking on item1 and then clicking on item2 will result in item1 being deselected
|
||||
auto_select_before_edit: true,
|
||||
//If there is unsubmitted text in the input field, should that text be automatically used to create a matching
|
||||
//element if no matching element was found or auto_select_before_edit is off?
|
||||
auto_create_before_edit: true,
|
||||
//customize this function to change which text the item is replaced with when clicking on it
|
||||
text: option => {
|
||||
return option[self.settings.labelField];
|
||||
}
|
||||
}, plugin_options_);
|
||||
|
||||
|
||||
self.hook('after', 'setupTemplates', () => {
|
||||
const orig_render_item = self.settings.render.item;
|
||||
self.settings.render.item = (data, escape) => {
|
||||
const item = getDom(orig_render_item.call(self, data, escape));
|
||||
|
||||
item.addEventListener('click', evt => {
|
||||
if (self.isLocked) {
|
||||
return;
|
||||
}
|
||||
const val = self.inputValue();
|
||||
|
||||
if (self.options[val]) {
|
||||
self.addItem(val)
|
||||
} else if (self.settings.create) {
|
||||
self.createItem();
|
||||
}
|
||||
const option = self.options[item.dataset.value]
|
||||
self.setTextboxValue(plugin_options.text.call(self, option));
|
||||
self.focus();
|
||||
self.removeItem(item);
|
||||
}
|
||||
);
|
||||
|
||||
return item;
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
export { plugin as default };
|
|
@ -4,6 +4,10 @@
|
|||
use App\Kernel;
|
||||
use Symfony\Bundle\FrameworkBundle\Console\Application;
|
||||
|
||||
if (!is_dir(dirname(__DIR__).'/vendor')) {
|
||||
throw new LogicException('Dependencies are missing. Try running "composer install".');
|
||||
}
|
||||
|
||||
//Increase xdebug.max_nesting_level to 1000 if required (see issue #411)
|
||||
//Check if xdebug extension is active, and xdebug.max_nesting_level is set to 256 or lower
|
||||
if (extension_loaded('xdebug') && ((int) ini_get('xdebug.max_nesting_level')) <= 256) {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
"name": "part-db/part-db-server",
|
||||
"type": "project",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"require": {
|
||||
|
@ -10,22 +11,23 @@
|
|||
"ext-intl": "*",
|
||||
"ext-json": "*",
|
||||
"ext-mbstring": "*",
|
||||
"amphp/http-client": "^5.1",
|
||||
"api-platform/core": "^3.1",
|
||||
"beberlei/doctrineextensions": "^1.2",
|
||||
"brick/math": "0.12.1 as 0.11.0",
|
||||
"composer/ca-bundle": "^1.3",
|
||||
"composer/ca-bundle": "^1.5",
|
||||
"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/data-fixtures": "^2.0.0",
|
||||
"doctrine/dbal": "^4.0.0",
|
||||
"doctrine/doctrine-bundle": "^2.0",
|
||||
"doctrine/doctrine-migrations-bundle": "^3.0",
|
||||
"doctrine/orm": "^2.16",
|
||||
"dompdf/dompdf": "dev-master#c9cf4be933e2406a51990bd4eb9e70612e790cc0 as v2.0.4",
|
||||
"doctrine/orm": "^3.2.0",
|
||||
"dompdf/dompdf": "^v3.0.0",
|
||||
"erusev/parsedown": "^1.7",
|
||||
"florianv/swap": "^4.0",
|
||||
"florianv/swap-bundle": "dev-master",
|
||||
"gregwar/captcha-bundle": "^2.1.0",
|
||||
"hshn/base64-encoded-file": "^5.0",
|
||||
"jbtronics/2fa-webauthn": "^v2.2.0",
|
||||
"jbtronics/dompdf-font-loader-bundle": "^1.0.0",
|
||||
"jfcherng/php-diff": "^6.14",
|
||||
|
@ -38,12 +40,11 @@
|
|||
"nelmio/cors-bundle": "^2.3",
|
||||
"nelmio/security-bundle": "^3.0",
|
||||
"nyholm/psr7": "^1.1",
|
||||
"ocramius/proxy-manager": "2.2.*",
|
||||
"omines/datatables-bundle": "^0.8.0",
|
||||
"omines/datatables-bundle": "^0.9.1",
|
||||
"paragonie/sodium_compat": "^1.21",
|
||||
"part-db/label-fonts": "^1.0",
|
||||
"php-translation/symfony-bundle": "^0.14.0",
|
||||
"phpdocumentor/reflection-docblock": "^5.2",
|
||||
"phpstan/phpdoc-parser": "^1.23",
|
||||
"rhukster/dom-sanitizer": "^1.0",
|
||||
"runtime/frankenphp-symfony": "^0.2.0",
|
||||
"s9e/text-formatter": "^2.1",
|
||||
"scheb/2fa-backup-code": "^6.8.0",
|
||||
"scheb/2fa-bundle": "^6.8.0",
|
||||
|
@ -54,6 +55,8 @@
|
|||
"symfony/apache-pack": "^1.0",
|
||||
"symfony/asset": "6.4.*",
|
||||
"symfony/console": "6.4.*",
|
||||
"symfony/css-selector": "6.4.*",
|
||||
"symfony/dom-crawler": "6.4.*",
|
||||
"symfony/dotenv": "6.4.*",
|
||||
"symfony/expression-language": "6.4.*",
|
||||
"symfony/flex": "^v2.3.1",
|
||||
|
@ -67,7 +70,6 @@
|
|||
"symfony/process": "6.4.*",
|
||||
"symfony/property-access": "6.4.*",
|
||||
"symfony/property-info": "6.4.*",
|
||||
"symfony/proxy-manager-bridge": "6.4.*",
|
||||
"symfony/rate-limiter": "6.4.*",
|
||||
"symfony/runtime": "6.4.*",
|
||||
"symfony/security-bundle": "6.4.*",
|
||||
|
@ -83,36 +85,34 @@
|
|||
"symfony/yaml": "6.4.*",
|
||||
"tecnickcom/tc-lib-barcode": "^2.1.4",
|
||||
"twig/cssinliner-extra": "^3.0",
|
||||
"twig/extra-bundle": "^3.0",
|
||||
"twig/html-extra": "^3.0",
|
||||
"twig/extra-bundle": "^3.8",
|
||||
"twig/html-extra": "^3.8",
|
||||
"twig/inky-extra": "^3.0",
|
||||
"twig/intl-extra": "^3.0",
|
||||
"twig/markdown-extra": "^3.0",
|
||||
"web-auth/webauthn-symfony-bundle": "^4.0.0",
|
||||
"webmozart/assert": "^1.4"
|
||||
"twig/intl-extra": "^3.8",
|
||||
"twig/markdown-extra": "^3.8",
|
||||
"twig/string-extra": "^3.8",
|
||||
"web-auth/webauthn-symfony-bundle": "^4.0.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"dama/doctrine-test-bundle": "^v8.0.0",
|
||||
"doctrine/doctrine-fixtures-bundle": "^3.2",
|
||||
"ekino/phpstan-banned-code": "^v1.0.0",
|
||||
"doctrine/doctrine-fixtures-bundle": "^4.0.0",
|
||||
"ekino/phpstan-banned-code": "^v3.0.0",
|
||||
"jbtronics/translation-editor-bundle": "^1.0",
|
||||
"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",
|
||||
"phpstan/phpstan": "^2.0.4",
|
||||
"phpstan/phpstan-doctrine": "^2.0.1",
|
||||
"phpstan/phpstan-strict-rules": "^2.0.1",
|
||||
"phpstan/phpstan-symfony": "^2.0.0",
|
||||
"phpunit/phpunit": "^9.5",
|
||||
"psalm/plugin-symfony": "^v5.0.1",
|
||||
"rector/rector": "^0.18.0",
|
||||
"rector/rector": "^2.0.4",
|
||||
"roave/security-advisories": "dev-latest",
|
||||
"symfony/browser-kit": "6.4.*",
|
||||
"symfony/css-selector": "6.4.*",
|
||||
"symfony/debug-bundle": "6.4.*",
|
||||
"symfony/maker-bundle": "^1.13",
|
||||
"symfony/phpunit-bridge": "6.4.*",
|
||||
"symfony/stopwatch": "6.4.*",
|
||||
"symfony/web-profiler-bundle": "6.4.*",
|
||||
"symplify/easy-coding-standard": "^12.0",
|
||||
"vimeo/psalm": "^5.6.0"
|
||||
"symplify/easy-coding-standard": "^12.0"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-bcmath": "Used to improve price calculation performance",
|
||||
|
@ -163,7 +163,8 @@
|
|||
"extra": {
|
||||
"symfony": {
|
||||
"allow-contrib": false,
|
||||
"require": "6.4.*"
|
||||
"require": "6.4.*",
|
||||
"docker": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
8266
composer.lock
generated
8266
composer.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -18,13 +18,11 @@ return [
|
|||
DAMA\DoctrineTestBundle\DAMADoctrineTestBundle::class => ['test' => true],
|
||||
Twig\Extra\TwigExtraBundle\TwigExtraBundle::class => ['all' => true],
|
||||
Gregwar\CaptchaBundle\GregwarCaptchaBundle::class => ['all' => true],
|
||||
Translation\Bundle\TranslationBundle::class => ['all' => true],
|
||||
Florianv\SwapBundle\FlorianvSwapBundle::class => ['all' => true],
|
||||
Nelmio\SecurityBundle\NelmioSecurityBundle::class => ['all' => true],
|
||||
Symfony\UX\Turbo\TurboBundle::class => ['all' => true],
|
||||
Jbtronics\TFAWebauthn\TFAWebauthnBundle::class => ['all' => true],
|
||||
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],
|
||||
|
@ -33,4 +31,5 @@ return [
|
|||
KnpU\OAuth2ClientBundle\KnpUOAuth2ClientBundle::class => ['all' => true],
|
||||
Nelmio\CorsBundle\NelmioCorsBundle::class => ['all' => true],
|
||||
ApiPlatform\Symfony\Bundle\ApiPlatformBundle::class => ['all' => true],
|
||||
Jbtronics\TranslationEditorBundle\JbtronicsTranslationEditorBundle::class => ['dev' => true],
|
||||
];
|
||||
|
|
|
@ -33,4 +33,9 @@ api_platform:
|
|||
pagination_client_items_per_page: true # Allow clients to override the default items per page
|
||||
|
||||
keep_legacy_inflector: false
|
||||
event_listeners_backward_compatibility_layer: false
|
||||
# Need to be true, or some tests will fail
|
||||
use_symfony_listeners: true
|
||||
|
||||
serializer:
|
||||
# Change this to false later, to remove the hydra prefix on the API
|
||||
hydra_prefix: true
|
5
config/packages/dama_doctrine_test_bundle.yaml
Normal file
5
config/packages/dama_doctrine_test_bundle.yaml
Normal file
|
@ -0,0 +1,5 @@
|
|||
when@test:
|
||||
dama_doctrine_test:
|
||||
enable_static_connection: true
|
||||
enable_static_meta_data_cache: true
|
||||
enable_static_query_cache: true
|
|
@ -8,15 +8,14 @@ datatables:
|
|||
|
||||
# Set options, as documented at https://datatables.net/reference/option/
|
||||
options:
|
||||
lengthMenu : [[10, 25, 50, 100, -1], [10, 25, 50, 100, "All"]]
|
||||
lengthMenu : [[10, 25, 50, 100], [10, 25, 50, 100]] # We add the "All" option, when part tables are generated
|
||||
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'
|
||||
rt
|
||||
<'card-footer card-footer-table text-muted' i >
|
||||
>
|
||||
<'row'<'col mt-2 input-group' B l> <'col mt-2' <'pull-right' p>>>"
|
||||
dom: " <'row' <'col mb-2 input-group flex-nowrap' B l > <'col-auto mb-2' < p >>>
|
||||
<'card'
|
||||
rt
|
||||
<'card-footer card-footer-table text-muted' i >
|
||||
>
|
||||
<'row' <'col mt-2 input-group flex-nowrap' B l > <'col-auto mt-2' < p >>>"
|
||||
pagingType: 'simple_numbers'
|
||||
searching: true
|
||||
stateSave: true
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
translation:
|
||||
symfony_profiler:
|
||||
enabled: true
|
||||
webui:
|
||||
enabled: true
|
|
@ -9,14 +9,25 @@ doctrine:
|
|||
# either here or in the DATABASE_URL env var (see .env file)
|
||||
|
||||
types:
|
||||
# UTC datetimes
|
||||
datetime:
|
||||
class: App\Doctrine\Types\UTCDateTimeType
|
||||
date:
|
||||
class: App\Doctrine\Types\UTCDateTimeType
|
||||
|
||||
datetime_immutable:
|
||||
class: App\Doctrine\Types\UTCDateTimeImmutableType
|
||||
date_immutable:
|
||||
class: App\Doctrine\Types\UTCDateTimeImmutableType
|
||||
|
||||
big_decimal:
|
||||
class: App\Doctrine\Types\BigDecimalType
|
||||
tinyint:
|
||||
class: App\Doctrine\Types\TinyIntType
|
||||
|
||||
# This was removed in doctrine/orm 4.0 but we need it for the WebauthnKey entity
|
||||
array:
|
||||
class: App\Doctrine\Types\ArrayType
|
||||
|
||||
schema_filter: ~^(?!internal)~
|
||||
# Only enable this when needed
|
||||
|
@ -29,6 +40,8 @@ doctrine:
|
|||
validate_xml_mapping: true
|
||||
naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware
|
||||
auto_mapping: true
|
||||
controller_resolver:
|
||||
auto_mapping: true
|
||||
mappings:
|
||||
App:
|
||||
type: attribute
|
||||
|
@ -39,10 +52,12 @@ doctrine:
|
|||
|
||||
dql:
|
||||
string_functions:
|
||||
regexp: DoctrineExtensions\Query\Mysql\Regexp
|
||||
ifnull: DoctrineExtensions\Query\Mysql\IfNull
|
||||
regexp: App\Doctrine\Functions\Regexp
|
||||
field: DoctrineExtensions\Query\Mysql\Field
|
||||
field2: App\Doctrine\Functions\Field2
|
||||
natsort: App\Doctrine\Functions\Natsort
|
||||
array_position: App\Doctrine\Functions\ArrayPosition
|
||||
ilike: App\Doctrine\Functions\ILike
|
||||
|
||||
when@test:
|
||||
doctrine:
|
||||
|
|
|
@ -50,7 +50,6 @@ when@prod:
|
|||
type: stream
|
||||
path: "%kernel.logs_dir%/%kernel.environment%.log"
|
||||
level: debug
|
||||
formatter: monolog.formatter.json
|
||||
console:
|
||||
type: console
|
||||
process_psr_3_messages: false
|
||||
|
@ -74,7 +73,6 @@ when@docker:
|
|||
type: stream
|
||||
path: "php://stderr"
|
||||
level: debug
|
||||
formatter: monolog.formatter.json
|
||||
console:
|
||||
type: console
|
||||
process_psr_3_messages: false
|
||||
|
|
|
@ -51,12 +51,16 @@ nelmio_security:
|
|||
img-src:
|
||||
- '*'
|
||||
- 'data:'
|
||||
# Required for be able to load pictures in the QR code scanner
|
||||
- 'blob:'
|
||||
style-src:
|
||||
- 'self'
|
||||
- 'unsafe-inline'
|
||||
- 'data:'
|
||||
script-src:
|
||||
- 'self'
|
||||
# Required for loading the Wasm for the barcode scanner:
|
||||
- 'wasm-unsafe-eval'
|
||||
object-src:
|
||||
- 'self'
|
||||
- 'data:'
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
translation:
|
||||
locales: ["en", "de"]
|
||||
edit_in_place:
|
||||
enabled: false
|
||||
config_name: app
|
||||
configs:
|
||||
app:
|
||||
dirs: ["%kernel.project_dir%/templates", "%kernel.project_dir%/src"]
|
||||
output_dir: "%kernel.project_dir%/translations"
|
||||
excluded_names: ["*TestCase.php", "*Test.php"]
|
||||
excluded_dirs: [cache, data, logs]
|
|
@ -11,11 +11,13 @@ 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', 'it', 'fr', 'ru', 'ja', 'cs', 'da'] # The languages that are shown in user drop down menu
|
||||
partdb.locale_menu: ['en', 'de', 'it', 'fr', 'ru', 'ja', 'cs', 'da', 'zh', 'pl'] # 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
|
||||
|
||||
partdb.db.emulate_natural_sort: '%env(bool:DATABASE_EMULATE_NATURAL_SORT)%' # If this is set to true, natural sorting is emulated on platforms that do not support it natively. This can be slow on large datasets.
|
||||
|
||||
######################################################################################################################
|
||||
# Users and Privacy
|
||||
######################################################################################################################
|
||||
|
@ -145,3 +147,5 @@ parameters:
|
|||
env(HISTORY_SAVE_NEW_DATA): 1
|
||||
|
||||
env(EDA_KICAD_CATEGORY_DEPTH): 0
|
||||
|
||||
env(DATABASE_EMULATE_NATURAL_SORT): 0
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
_translation_webui:
|
||||
resource: '@TranslationBundle/Resources/config/routing_webui.yaml'
|
||||
prefix: /admin
|
||||
|
||||
_translation_profiler:
|
||||
resource: '@TranslationBundle/Resources/config/routing_symfony_profiler.yaml'
|
3
config/routes/jbtronics_translation_editor.yaml
Normal file
3
config/routes/jbtronics_translation_editor.yaml
Normal file
|
@ -0,0 +1,3 @@
|
|||
when@dev:
|
||||
translation_editor:
|
||||
resource: '@JbtronicsTranslationEditorBundle/config/routes.php'
|
|
@ -1,3 +0,0 @@
|
|||
_translation_edit_in_place:
|
||||
resource: '@TranslationBundle/Resources/config/routing_edit_in_place.yaml'
|
||||
prefix: /admin
|
|
@ -76,18 +76,12 @@ services:
|
|||
# Only the event classes specified here are saved to DB (set to []) to log all events
|
||||
$whitelist: []
|
||||
|
||||
App\EventSubscriber\LogSystem\EventLoggerSubscriber:
|
||||
App\EventListener\LogSystem\EventLoggerListener:
|
||||
arguments:
|
||||
$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' }
|
||||
|
||||
App\EventSubscriber\LogSystem\LogDBMigrationSubscriber:
|
||||
tags:
|
||||
- { name: 'doctrine.event_subscriber' }
|
||||
|
||||
App\Form\AttachmentFormType:
|
||||
arguments:
|
||||
|
@ -307,6 +301,21 @@ services:
|
|||
$options: '%env(string:PROVIDER_MOUSER_SEARCH_OPTION)%'
|
||||
$search_limit: '%env(int:PROVIDER_MOUSER_SEARCH_LIMIT)%'
|
||||
|
||||
App\Services\InfoProviderSystem\Providers\LCSCProvider:
|
||||
arguments:
|
||||
$enabled: '%env(bool:PROVIDER_LCSC_ENABLED)%'
|
||||
$currency: '%env(string:PROVIDER_LCSC_CURRENCY)%'
|
||||
|
||||
App\Services\InfoProviderSystem\Providers\OEMSecretsProvider:
|
||||
arguments:
|
||||
$api_key: '%env(string:PROVIDER_OEMSECRETS_KEY)%'
|
||||
$country_code: '%env(string:PROVIDER_OEMSECRETS_COUNTRY_CODE)%'
|
||||
$currency: '%env(PROVIDER_OEMSECRETS_CURRENCY)%'
|
||||
$zero_price: '%env(PROVIDER_OEMSECRETS_ZERO_PRICE)%'
|
||||
$set_param: '%env(PROVIDER_OEMSECRETS_SET_PARAM)%'
|
||||
$sort_criteria: '%env(PROVIDER_OEMSECRETS_SORT_CRITERIA)%'
|
||||
|
||||
|
||||
####################################################################################################################
|
||||
# API system
|
||||
####################################################################################################################
|
||||
|
@ -401,4 +410,4 @@ when@test:
|
|||
arguments:
|
||||
- '@doctrine.fixtures.loader'
|
||||
- '@doctrine'
|
||||
- { default: '@App\Doctrine\Purger\DoNotUsePurgerFactory' }
|
||||
- { default: '@App\Doctrine\Purger\DoNotUsePurgerFactory' }
|
||||
|
|
|
@ -11,15 +11,14 @@ To use API endpoints, the external application has to authenticate itself, so th
|
|||
the data and which permissions
|
||||
the application should have during the access. Authentication is always bound to a specific user, so the external
|
||||
applications is acting on behalf of a
|
||||
specific user. This user limits the permissions of the application, so that it can only access data, which the user is
|
||||
specific user. This user limits the permissions of the application so that it can only access data, which the user is
|
||||
allowed to access.
|
||||
|
||||
The only method currently available for authentication is to use API tokens:
|
||||
|
||||
## API tokens
|
||||
|
||||
An API token is a long alphanumeric string, which is bound to a specific user and can be used to authenticate as this
|
||||
user, when accessing the API.
|
||||
An API token is a long alphanumeric string, which is bound to a specific user and can be used to authenticate as this user when accessing the API.
|
||||
The API token is passed via the `Authorization` HTTP header during the API request, like the
|
||||
following: `Authorization: Bearer tcp_sdjfks....`.
|
||||
|
||||
|
@ -36,7 +35,7 @@ not access the API anymore with this token.
|
|||
### Token permissions and scopes
|
||||
|
||||
API tokens are ultimately limited by the permissions of the user, which belongs to the token. That means that the token
|
||||
can only access data, which the user is allowed to access, no matter the token permissions.
|
||||
can only access data, that the user is allowed to access, no matter the token permissions.
|
||||
|
||||
But you can further limit the permissions of a token by choosing a specific scope for the token. The scope defines which
|
||||
subset of permissions the token has, which can be less than the permissions of the user. For example, you can have a
|
||||
|
@ -50,15 +49,15 @@ change anything in the database.
|
|||
> Only use the full or admin scope, if you really need it, as they could potentially be used to do a lot of damage to
|
||||
> your Part-DB instance.
|
||||
|
||||
Following token scopes are available:
|
||||
The following token scopes are available:
|
||||
|
||||
* **Read-Only**: The token can only read non-sensitive data (like parts, but no users or groups) from the API and can
|
||||
not change anything.
|
||||
* **Edit**: The token can read and write non-sensitive data via the API. This includes creating, updating and deleting
|
||||
data. This should be enough for most applications.
|
||||
* **Admin**: The token can read and write all data via the API, including sensitive data like users and groups. This
|
||||
should only be used for trusted applications, which need to access sensitive data, and perform administrative actions.
|
||||
* **Full**: The token can do anything the user can do, including changing the users password and create new tokens. This
|
||||
should only be used for trusted applications, which need to access sensitive data and perform administrative actions.
|
||||
* **Full**: The token can do anything the user can do, including changing the user's password and creating new tokens. This
|
||||
should only be used for highly trusted applications!!
|
||||
|
||||
Please note, that in early versions of the API, there might be no endpoints yet, to really perform the actions, which
|
||||
|
|
|
@ -29,15 +29,14 @@ features and how to use them.
|
|||
|
||||
The API is available under the `/api` path, but not reachable without proper permissions.
|
||||
You have to give the users, which should be able to access the API the proper permissions (Miscellaneous -> API).
|
||||
Please note that there are two relevant permissions, the first one allows users to access the `/api/` path at all and
|
||||
showing the documentation,
|
||||
and the second one allows them to create API tokens which is needed for authentication of external applications.
|
||||
Please note that there are two relevant permissions, the first one allows users to access the `/api/` path at all and show the documentation,
|
||||
and the second one allows them to create API tokens which are needed for the authentication of external applications.
|
||||
|
||||
## Authentication
|
||||
|
||||
To use API endpoints, the external application has to authenticate itself, so that Part-DB knows which user is accessing
|
||||
the data and
|
||||
which permissions the application should have. Basically this is done by creating an API token for a user and then
|
||||
which permissions the application should have. Basically, this is done by creating an API token for a user and then
|
||||
passing it on every request
|
||||
with the `Authorization` header as bearer token, so you add a header `Authorization: Bearer <your token>`.
|
||||
|
||||
|
@ -46,11 +45,10 @@ See [Authentication chapter]({% link api/authentication.md %}) for more details.
|
|||
## API endpoints
|
||||
|
||||
The API is split into different endpoints, which are reachable under the `/api/` path of your Part-DB instance (
|
||||
so `https://your-part-db.local/api/`).
|
||||
There are various endpoints for each entity type (like `part`, `manufacturer`, etc.), which allow you to read and write
|
||||
data and some special endpoints like `search` or `statistics`.
|
||||
e.g. `https://your-part-db.local/api/`).
|
||||
There are various endpoints for each entity type (like `part`, `manufacturer`, etc.), which allow you to read and write data, and some special endpoints like `search` or `statistics`.
|
||||
|
||||
For example all API endpoints for managing categories are available under `/api/categories/`. Depending on the exact
|
||||
For example, all API endpoints for managing categories are available under `/api/categories/`. Depending on the exact
|
||||
path and the HTTP method used, you can read, create, update or delete categories.
|
||||
For most entities, there are endpoints like this:
|
||||
|
||||
|
@ -66,29 +64,28 @@ For most entities, there are endpoints like this:
|
|||
A full (interactive) list of endpoints can be displayed when visiting the `/api/` path in your browser, when you are
|
||||
logged in with a user, which is allowed to access the API.
|
||||
There is also a link to this page, on the user settings page in the API token section.
|
||||
This documentation also list all available fields for each entity type and the allowed operations.
|
||||
This documentation also lists all available fields for each entity type and the allowed operations.
|
||||
|
||||
## Formats
|
||||
|
||||
The API supports different formats for the request and response data, which you can control via the `Accept`
|
||||
and `Content-Type` headers.
|
||||
You should use [JSON-LD](https://json-ld.org/) as format, which is basically JSON with some additional metadata, which
|
||||
allows
|
||||
to describe the data in a more structured way and also allows to link between different entities. You can achieve this
|
||||
allows you to describe the data in a more structured way and also allows to link between different entities. You can achieve this
|
||||
by setting `Accept: application/ld+json` header to the API requests.
|
||||
|
||||
To get plain JSON without any metadata or links, use the `Accept: application/json` header.
|
||||
|
||||
Without an `Accept` header (e.g. when you call the endpoint in a browser), the API will return an HTML page with the
|
||||
documentation, so be sure to include the desired `Accept` header in your API requests.
|
||||
If you can not control the `Accept` header, you can add an `.json` or `.jsonld` suffix to the URL to enforce a JSON or
|
||||
If you can not control the `Accept` header, you can add a `.json` or `.jsonld` suffix to the URL to enforce a JSON or
|
||||
JSON-LD response (e.g. `/api/parts.jsonld`).
|
||||
|
||||
## OpenAPI schema
|
||||
|
||||
Part-DB provides a [OpenAPI](https://swagger.io/specification/) (formally Swagger) schema for the API
|
||||
under `/api/docs.json` (so `https://your-part-db.local/api/docs.json`).
|
||||
This schema is a machine-readable description of the API, which can be imported in software to test the API or even
|
||||
This schema is a machine-readable description of the API, which can be imported into software to test the API or even
|
||||
automatically generate client libraries for the API.
|
||||
|
||||
API generators which can generate a client library for the API from the schema are available for many programming
|
||||
|
@ -120,14 +117,10 @@ See [API Platform docs](https://api-platform.com/docs/core/pagination) for more
|
|||
## Filtering results / Searching
|
||||
|
||||
When retrieving a list of entities, you can restrict the results by various filters. Almost all entities have a search
|
||||
filter,
|
||||
which allows you to only include entities, which (text) fields match the given search term: For example if you only want
|
||||
to
|
||||
get parts, with the Name "BC547", you can use `/api/parts.jsonld?name=BC547`. You can use `%` as wildcard for multiple
|
||||
characters
|
||||
in the search term (Be sure to properly encode the search term, if you use special characters). For example if you want
|
||||
to get all parts,
|
||||
whose name starts with "BC", you can use `/api/parts.jsonld?name=BC%25` (the `%25` is the url encoded version of `%`).
|
||||
filter, which allows you to only include entities, which (text) fields match the given search term: For example, if you only want
|
||||
to get parts, with the Name "BC547", you can use `/api/parts.jsonld?name=BC547`. You can use `%` as a wildcard for multiple
|
||||
characters in the search term (Be sure to properly encode the search term, if you use special characters). For example, if you want
|
||||
to get all parts, whose name starts with "BC", you can use `/api/parts.jsonld?name=BC%25` (the `%25` is the url encoded version of `%`).
|
||||
|
||||
There are other filters available for some entities, allowing you to search on other fields, or restricting the results
|
||||
by numeric values or dates. See the endpoint documentation for the available filters.
|
||||
|
@ -136,8 +129,8 @@ by numeric values or dates. See the endpoint documentation for the available fil
|
|||
|
||||
To get all parts with a certain category, manufacturer, etc. you can use the `category`, `manufacturer`, etc. query
|
||||
parameters of the `/api/parts` endpoint.
|
||||
They are so-called entity filters and accept a comma separated list of IDs of the entities you want to filter by.
|
||||
For example if you want to get all parts with the category "Resistor" (Category ID 1) and "Capacitor" (Category ID 2),
|
||||
They are so-called entity filters and accept a comma-separated list of IDs of the entities you want to filter by.
|
||||
For example, if you want to get all parts with the category "Resistor" (Category ID 1) and "Capacitor" (Category ID 2),
|
||||
you can use `/api/parts.jsonld?category=1,2`.
|
||||
|
||||
Suffix an id with `+` to suffix, to include all direct children categories of the given category. Use the `++` suffix to
|
||||
|
@ -150,7 +143,7 @@ See the endpoint documentation for the available entity filters.
|
|||
## Ordering results
|
||||
|
||||
When retrieving a list of entities, you can order the results by various fields using the `order` query parameter.
|
||||
For example if you want to get all parts ordered by their name, you can use `/api/parts/?order[name]=asc`. You can use
|
||||
For example, if you want to get all parts ordered by their name, you can use `/api/parts/?order[name]=asc`. You can use
|
||||
this parameter multiple times to order by multiple fields.
|
||||
|
||||
See the endpoint documentation for the available fields to order by.
|
||||
|
@ -161,12 +154,12 @@ Sometimes you only want to get a subset of the properties of an entity, for exam
|
|||
part, but not all the other properties.
|
||||
You can achieve this using the `properties[]` query parameter with the name of the field you want to get. You can use
|
||||
this parameter multiple times to get multiple fields.
|
||||
For example if you only want to get the name and the description of a part, you can
|
||||
For example, if you only want to get the name and the description of a part, you can
|
||||
use `/api/parts/123?properties[]=name&properties[]=description`.
|
||||
It is also possible to use this filters on list endpoints (get collection), to only get a subset of the properties of
|
||||
It is also possible to use these filters on list endpoints (get collection), to only get a subset of the properties of
|
||||
all entities in the collection.
|
||||
|
||||
See [API Platform docs](https://api-platform.com/docs/core/filters/#property-filter) for more infos.
|
||||
See [API Platform docs](https://api-platform.com/docs/core/filters/#property-filter) for more info.
|
||||
|
||||
## Change comment
|
||||
|
||||
|
@ -174,30 +167,63 @@ Similar to the changes using Part-DB web interface, you can add a change comment
|
|||
which will be
|
||||
visible in the log of the entity.
|
||||
|
||||
You can pass the text for this via the `_comment` query parameter (beware the proper encoding). For
|
||||
You can pass the text for this via the `_comment` query parameter (beware of the proper encoding). For
|
||||
example `/api/parts/123?_comment=This%20is%20a%20change%20comment`.
|
||||
|
||||
## Creating attachments and parameters
|
||||
|
||||
{: .warning }
|
||||
> The way described below is more a workaround than a proper solution. This might break in future versions of Part-DB!
|
||||
To create attachments and parameters, use the POST endpoint. Internally there are different types of attachments and
|
||||
parameters, for each entity type, where the attachments or parameters are used (e.g. PartAttachment for parts, etc.).
|
||||
The type of the attachment or parameter is automatically determined by the `element` property of the request data if a
|
||||
IRI is passed. You can use the `_type` property to explicitly set the type of the attachment or parameter (the value must
|
||||
be the value of the `@type` property of the owning entity. e.g. `Part` for parts).
|
||||
|
||||
Currently it is not possible to create attachments or parameters via a `POST` operation on the entity endpoint.
|
||||
The workaround for this is to send a patch request to the owning entity endpoint (e.g. parts `/api/parts/123`):
|
||||
For example, to create an attachment on a part, you can use the following request:
|
||||
|
||||
```
|
||||
PATCH /api/parts/123
|
||||
POST /api/attachments
|
||||
|
||||
{
|
||||
"attachments": [
|
||||
{"name": "front68", "attachment_type": "/api/attachment_types/1", "url": "https://invalid.invalid/test.url"}
|
||||
],
|
||||
"parameters": [
|
||||
{"name": "value", "unit": "Ohm", "value": 100}
|
||||
]
|
||||
{
|
||||
"name": "front68",
|
||||
"attachment_type": "/api/attachment_types/1",
|
||||
"url": "https://invalid.invalid/test.url",
|
||||
"element": "/api/parts/123"
|
||||
}
|
||||
```
|
||||
|
||||
The limitation of this is, that this will override/delete all existing attachments/parameters of the entity.
|
||||
## Uploading files to attachments
|
||||
|
||||
See [issue #502](https://github.com/Part-DB/Part-DB-server/issues/502) for more details on this topic.
|
||||
To upload files to the attachments you can use the special `upload` property of the attachment entity during write operations (POST, PUT, PATCH).
|
||||
Under `data` you can pass a base64 encoded string of the file content, and under `filename` the name of the file.
|
||||
Using the `private` property you can control if the file is the attachment should be stored privately or public.
|
||||
|
||||
For example, to upload a file to an attachment, you can use the following request:
|
||||
|
||||
```
|
||||
PATCH /api/attachments/123
|
||||
|
||||
{
|
||||
"upload": {
|
||||
"data": "data:@file/octet-stream;base64,LS0gcGhwTXlB[...]",
|
||||
"filename": "test.csv",
|
||||
"private": false
|
||||
},
|
||||
"name": "Rename attachment"
|
||||
}
|
||||
```
|
||||
|
||||
This also works for creating new attachments, by including the `upload` property in the request data along with the other properties.
|
||||
|
||||
Using the `downloadUrl` property of `upload` you can say Part-DB to upload the file specified at the URL set on the attachment.
|
||||
|
||||
```
|
||||
PATCH /api/attachments/123
|
||||
|
||||
{
|
||||
"upload": {
|
||||
"downloadUrl": true
|
||||
},
|
||||
"url": "https://host.invalid/myfile.pdf"
|
||||
}
|
||||
|
||||
```
|
105
docs/concepts.md
105
docs/concepts.md
|
@ -11,55 +11,55 @@ This page explains the different concepts of Part-DB and what their intended use
|
|||
1. TOC
|
||||
{:toc}
|
||||
|
||||
## Part managment
|
||||
## Part management
|
||||
|
||||
### Part
|
||||
|
||||
A part is the central concept of Part-DB. A part represents a single kind (or type) of a thing, like an electronic
|
||||
component, a device, a book or similar (depending on what you use Part-DB for). A part entity just represents a certain
|
||||
type of thing, so if you have 1000 times an BC547 transistor you would create ONE part with the name BC547 and set its
|
||||
type of thing, so if you have 1000 times a BC547 transistor you would create ONE part with the name BC547 and set its
|
||||
quantity to 1000. The individual quantities (so a single BC547 transistor) of a part, should be indistinguishable from
|
||||
each other, so that it does not matter which one of your 1000 things of Part you use.
|
||||
A part entity have many fields, which can be used to describe it better. Most of the fields are optional:
|
||||
each other so that it does not matter which one of your 1000 things of Part you use.
|
||||
A part entity has many fields, which can be used to describe it better. Most of the fields are optional:
|
||||
|
||||
* **Name** (Required): The name of the part or how you want to call it. This could be a manufacturer provided name, or a
|
||||
name you thought of your self. The name have to be unique in a single category.
|
||||
* **Description**: A short (single-line) description of what this part is/does. For longer information you should use
|
||||
* **Name** (Required): The name of the part or how you want to call it. This could be a manufacturer-provided name, or a
|
||||
name you thought of yourself. Each name needs to be unique and must exist in a single category.
|
||||
* **Description**: A short (single-line) description of what this part is/does. For longer information, you should use
|
||||
the comment field or the specifications
|
||||
* **Category** (Required): The category (see there) to which this part belongs to.
|
||||
* **Tags**: The list of tags this part belong to. Tags can be used to group parts logically (similar to the category),
|
||||
* **Tags**: The list of tags this part belongs to. Tags can be used to group parts logically (similar to the category),
|
||||
but tags are much less strict and formal (they don't have to be defined forehands) and you can assign multiple tags to
|
||||
a part. When clicking on a tag, a list with all parts which have the same tag, is shown.
|
||||
* **Min Instock**: *Not really implemented yet*. Parts where the total instock is below this value, will show up for
|
||||
ordering.
|
||||
* **Footprint**: See there. Useful especially for electronic parts, which have one of the common electronic footprints (
|
||||
like DIP8, SMD0805 or similar). If a part has no explicit defined preview picture, the preview picture of its
|
||||
like DIP8, SMD0805 or similar). If a part has no explicitly defined preview picture, the preview picture of its
|
||||
footprint will be shown instead in tables.
|
||||
* **Manufacturer**: The manufacturer which has manufactured (not sold) this part. See Manufacturer entity for more info.
|
||||
* **Manufacturer part number** (MPN): If you have used your own name for a part, you can put the part number the
|
||||
manufacturer uses in this field, so that you can find a part also under its manufacturer number.
|
||||
manufacturer uses in this field so that you can find a part also under its manufacturer number.
|
||||
* **Link to product page**: If you want to link to the manufacturer website of a part, and it is not possible to
|
||||
determine it automatically from the part name, set in the manufacturer entity (or no manufacturer is set), you can set
|
||||
the link here for each part individually.
|
||||
* **Manufacturing Status**: The manufacturing status of this part, meaning the information about where the part is in
|
||||
its manufacturing lifecycle.
|
||||
* **Needs review**: If you think parts information maybe are inaccurate or incomplete and needs some later
|
||||
review/checking, you can set this flag. A part with this flag is marked, so that users know the information are not
|
||||
* **Needs review**: If you think parts information may be inaccurate or incomplete and needs some later
|
||||
review/checking, you can set this flag. A part with this flag is marked, so that users know the information is not
|
||||
completely trustworthy.
|
||||
* **Favorite**: Parts with this flag are highlighted in parts lists
|
||||
* **Mass**: The mass of a single piece of this part (so of a single transistor). Given in grams.
|
||||
* **Internal Part number** (IPN): Each part is automatically assigned a numerical ID which identifies a part in the
|
||||
* **Internal Part number** (IPN): Each part is automatically assigned a numerical ID that identifies a part in the
|
||||
database. This ID depends on when a part was created and can not be changed. If you want to assign your own unique
|
||||
identifiers, or sync parts identifiers with the identifiers of another database you can use this field.
|
||||
|
||||
### Stock / Part lot
|
||||
|
||||
A part can have many stock at multiple different locations. This is represented by part lots / stocks, which consists
|
||||
basically of a storage location (so where are the parts of this lot are stored) and an amount (how many parts are there).
|
||||
A part can have many stocks at multiple different locations. This is represented by part lots/stocks, which consists
|
||||
basically of a storage location (so where the parts of this lot are stored) and an amount (how many parts are there).
|
||||
|
||||
### Purchase Information
|
||||
|
||||
The purchase information describe where the part can be bought (at which vendors) and to which prices.
|
||||
The purchase information describes where the part can be bought (at which vendors) and at which prices.
|
||||
The first part (the order information) describes at which supplier the part can be bought and which is the name of the
|
||||
part under which you can order the part there.
|
||||
An order information can contain multiple price information, which describes the prices for the part at the supplier
|
||||
|
@ -67,13 +67,13 @@ including bulk discount, etc.
|
|||
|
||||
### Parameters
|
||||
|
||||
Parameters represents various specifications / parameters of a part, like the maximum current of a diode, etc. The
|
||||
Parameters represent various specifications/parameters of a part, like the maximum current of a diode, etc. The
|
||||
advantage of using parameters instead of just putting the data in the comment field or so, is that you can filter for
|
||||
parameters values (including ranges and more) later on.
|
||||
Parameters describe can describe numeric values and/or text values for which they can be filtered. This basically allows
|
||||
parameter's values (including ranges and more) later on.
|
||||
Parameters can describe numeric values and/or text values for which they can be filtered. This allows
|
||||
you to define custom fields on a part.
|
||||
|
||||
Using the group field a parameter allows you to group parameters together in the info page later (all parameters with
|
||||
Using the group field as a parameter allows you to group parameters together on the info page later (all parameters with
|
||||
the same group value will be shown under the same group title).
|
||||
|
||||
## Core data
|
||||
|
@ -99,17 +99,17 @@ possible category tree could look like this:
|
|||
|
||||
### Supplier
|
||||
|
||||
A Supplier is a vendor / distributor where you can buy/order parts. Price information of parts are associated with a
|
||||
A Supplier is a vendor/distributor where you can buy/order parts. Price information of parts is associated with a
|
||||
supplier.
|
||||
|
||||
### Manufacturer
|
||||
|
||||
A manufacturer represents the company that manufacturer / build various parts (not necessary sell them). If the
|
||||
manufacturer also sell the parts, you have to create a supplier for that.
|
||||
A manufacturer represents the company that manufacturers/builds various parts (not necessarily sell them). If the
|
||||
manufacturer also sells the parts, you have to create a supplier for that.
|
||||
|
||||
### Storage location
|
||||
|
||||
A storage location represents a place where parts can be stored. This could be a box, a shelf or other things (like the
|
||||
A storage location represents a place where parts can be stored. This could be a box, a shelf, or other things (like the
|
||||
SMD feeder of a machine or so).
|
||||
|
||||
Storage locations are hierarchical to represent storage locations contained in each other.
|
||||
|
@ -129,12 +129,12 @@ Storage locations should be defined down to the smallest possible location, to m
|
|||
|
||||
### Footprint
|
||||
|
||||
In electronics many components have one of the common components cases / footprints. The footprint entity describes such
|
||||
In electronics, many components have one of the common components cases/footprints. The footprint entity describes such
|
||||
common footprints, which can be assigned to parts.
|
||||
You can assign an image (and an 3D model) as an attachment to a footprint, which will be used as preview for parts with
|
||||
You can assign an image (and a 3D model) as an attachment to a footprint, which will be used as preview for parts with
|
||||
this footprint, even if the parts do not have an explicitly assigned preview image.
|
||||
|
||||
Footprints are a hierarchically which allows you to build logical sorted trees. An example tree could look like this:
|
||||
Footprints are hierarchically which allows you to build logically sorted trees. An example tree could look like this:
|
||||
|
||||
* Through-Hole components
|
||||
* DIP
|
||||
|
@ -152,18 +152,21 @@ Footprints are a hierarchically which allows you to build logical sorted trees.
|
|||
|
||||
### Measurement Unit
|
||||
|
||||
By default, part instock is counted in number of individual parts, which is fine for things like electronic components,
|
||||
which exists only in integer quantities. However, if you have things with fractional units like the length of a wire or
|
||||
By default, part in stock is counted in number of individual parts, which is fine for things like electronic components,
|
||||
which exist only in integer quantities. However, if you have things with fractional units like the length of a wire or
|
||||
the volume of a liquid, you have to define a measurement unit.
|
||||
The measurement unit represents a physical quantity like mass, volume or length.
|
||||
The measurement unit represents a physical quantity like mass, volume, or length.
|
||||
|
||||
You can define a short unit for it (like m for Meters, or g for gramms) which will be shown, when a quantity of a part
|
||||
You can define a short unit for it (like m for Meters, or g for grams) which will be shown when a quantity of a part
|
||||
with this unit is shown.
|
||||
|
||||
In order to cover wider use cases and allow you to define measurement units further, it is possible to define parameters
|
||||
associated to a measurement unit. These parameters are distinct from a part's parameters and are not inherited.
|
||||
|
||||
### Currency
|
||||
|
||||
By default, all prices are set in the base currency configured for the instance (by default euros). If you want to use
|
||||
multiple currencies together (as e.g. vendors use foreign currencies for their price, and you do not want to update the
|
||||
multiple currencies together (e.g. vendors use foreign currencies for their price, and you do not want to update the
|
||||
prices for every exchange rate change), you have to define these currencies here.
|
||||
|
||||
You can set an exchange rate here in terms of the base currency (or fetch it from the internet if configured). The
|
||||
|
@ -173,57 +176,57 @@ exchange rate will be used to show users the prices in their preferred currency.
|
|||
|
||||
### Attachment
|
||||
|
||||
An attachment is a file that can be associated with another entity (like a Part, Storelocation, User, etc.). This could
|
||||
An attachment is a file that can be associated with another entity (like a Part, location, User, etc.). This could
|
||||
for example be a datasheet in a Part, the logo of a vendor or some CAD drawing of a footprint.
|
||||
|
||||
An attachment has an attachment type (see below), which groups the attachments logically (and optionally restricts the
|
||||
allowed file types), a name describing the attachment and a file. The file can either be uploaded to the server and
|
||||
stored there, or given as a link to a file on another web path. If configured in the settings, it is also possible that
|
||||
the webserver downloads the file from the supplied website and stores it locally on the server.
|
||||
the web server downloads the file from the supplied website and stores it locally on the server.
|
||||
|
||||
By default, all uploaded files, are accessible for everyone (even non-logged-in users), if the link is known. If your
|
||||
Part-DB instance is publicly available, and you want to store private/sensitive files on it, you should mark the
|
||||
attachment as "Private attachment". Private attachments are only accessible to users, which has the permission to access
|
||||
attachment as "Private attachment". Private attachments are only accessible to users, which has permission to access
|
||||
private attachments.
|
||||
Please not, that no thumbnails are generated for private attachments, which can have a performance impact.
|
||||
Please note, that no thumbnails are generated for private attachments, which can have a performance impact.
|
||||
|
||||
Part-DB ships some preview images for various common footprints like DIP-8 and others, as internal resources. These can
|
||||
be accessed/searched by typing the keyword in the URL field of a part and choosing one of the choices from the dropdown.
|
||||
|
||||
### Preview image / attachment
|
||||
### Preview image/attachment
|
||||
|
||||
Most entities with attachments allow you to select one of the defined attachments as "Preview image". You can select an
|
||||
image attachment here, that previews the entity, this could be a picture of a Part, the logo of a manufacturer or
|
||||
supplier, the schematic symbol of a category or the image of a footprint.
|
||||
The preview image will be shown in various locations together with the entities name.
|
||||
The preview image will be shown in various locations together with the entity's name.
|
||||
|
||||
Please note that as long as the picture is not secret, it should be stored on the Part-DB instance (by upload, or
|
||||
letting Part-DB download the file) and *not* be marked as a private attachments, so that thumbnails can be generated for
|
||||
Please note that as long as the picture is not secret, it should be stored on the Part-DB instance (by uploading, or
|
||||
letting Part-DB download the file) and *not* be marked as a private attachment, so that thumbnails can be generated for
|
||||
the picture (which improves performance).
|
||||
|
||||
### Attachment types
|
||||
|
||||
Attachment types define logical groups of attachments. For example, you could define an attachment group "Datasheets"
|
||||
where all datasheets of Parts, Footprints, etc. belong in, "Pictures" for preview images and more.
|
||||
You can define file type restrictions, which file types and extensions are allowed for files with that attachment type.
|
||||
You can define file type restrictions, and which file types and extensions are allowed for files with that attachment type.
|
||||
|
||||
## User System
|
||||
|
||||
### User
|
||||
|
||||
Each person which should be able to use Part-DB (by logging in) is represented by a user entity, which defines things
|
||||
like access rights, the password, and other things. For security reasons, every person which will use Part-DB should use
|
||||
its own personal account with a secret password. This allows to track activity of the users via the log.
|
||||
Each person who should be able to use Part-DB (by logging in) is represented by a user entity, which defines things
|
||||
like access rights, the password, and other things. For security reasons, every person who will use Part-DB should use
|
||||
their own personal account with a secret password. This allows to track activity of the users via the log.
|
||||
|
||||
There is a special user called `anonymous`, whose access rights are used to determine what a non-logged in user can do.
|
||||
There is a special user called `anonymous`, whose access rights are used to determine what a non-logged-in user can do.
|
||||
Normally the anonymous user should be the most restricted user.
|
||||
|
||||
For simplification of access management users can be assigned to groups.
|
||||
|
||||
### Group
|
||||
|
||||
A group is entity, to which users can be assigned to. This can be used to logically group users by for example
|
||||
organisational structures and to simplify permissions management, as you can define groups with access rights for common
|
||||
A group is an entity, to which users can be assigned to. This can be used to logically group users by for example
|
||||
organizational structures and to simplify permissions management, as you can define groups with access rights for common
|
||||
use cases and then just assign users to them, without the need to change every permission on the users individually.
|
||||
|
||||
## Labels
|
||||
|
@ -231,9 +234,9 @@ use cases and then just assign users to them, without the need to change every p
|
|||
### Label profiles
|
||||
|
||||
A label profile represents a template for a label (for a storage location, a part or part lot). It consists of a size, a
|
||||
barcode type and the content. There are various placeholders which can be inserted in the text content and which will be
|
||||
used replaced with data for the actual thing.
|
||||
barcode type and the content. There are various placeholders that can be inserted in the text content and which will be
|
||||
replaced with data for the actual thing.
|
||||
|
||||
You do not have to define a label profile to generate labels (you can just set the settings on the fly in the label
|
||||
dialog), however if you want to generate many labels, it is recommended to save the settings as label profile, to save
|
||||
it for later usage. This ensures that all generated labels look the same.
|
||||
dialog), however, if you want to generate many labels, it is recommended to save the settings as a label profile, to save
|
||||
it for later usage. This ensures that all generated labels look the same.
|
||||
|
|
|
@ -6,21 +6,21 @@ nav_order: 5
|
|||
|
||||
# Configuration
|
||||
|
||||
Part-DBs behavior can be configured to your needs. There are different kind of configuration options: Options which are
|
||||
user changeable (changeable dynamically via frontend), options which can be configured by environment variables, and
|
||||
options which are only configurable via symfony config files.
|
||||
Part-DBs behavior can be configured to your needs. There are different kinds of configuration options: Options, which are
|
||||
user-changeable (changeable dynamically via frontend), options that can be configured by environment variables, and
|
||||
options that are only configurable via Symfony config files.
|
||||
|
||||
## User changeable
|
||||
|
||||
Following things can be changed for every user and a user can change it for himself (if he has the correct permission
|
||||
for it). Configuration is either possible via the users own setting page (where you can also change the password) or via
|
||||
The following things can be changed for every user and a user can change it for himself (if he has the correct permission
|
||||
for it). Configuration is either possible via the user's own settings page (where you can also change the password) or via
|
||||
the user admin page:
|
||||
|
||||
* **Language**: The language that the users prefers, and which will be used when no language is explicitly specified.
|
||||
Language can still always be changed via the language selector. By default, the global configured language is used.
|
||||
* **Timezone**: The timezone which the user resides in and in which all dates and times should be shown. By default, the
|
||||
* **Language**: The language that the users prefer, and which will be used when no language is explicitly specified.
|
||||
Language can still always be changed via the language selector. By default, the globally configured language is used.
|
||||
* **Timezone**: The timezone in which the user resides and in which all dates and times should be shown. By default, the
|
||||
globally configured language.
|
||||
* **Theme**: The theme to use for the frontend. Allows the user to choose the frontend design, he prefers.
|
||||
* **Theme**: The theme to use for the front end. Allows the user to choose the front end design, he prefers.
|
||||
* **Preferred currency**: One of the defined currencies, in which all prices should be shown, if possible. Prices with
|
||||
other currencies will be converted to the price selected here
|
||||
|
||||
|
@ -28,19 +28,27 @@ the user admin page:
|
|||
|
||||
The following configuration options can only be changed by the server administrator, by either changing the server
|
||||
variables, changing the `.env.local` file or setting env for your docker container. Here are just the most important
|
||||
options listed, see `.env` file for full list of possible env variables.
|
||||
options listed, see `.env` file for the full list of possible env variables.
|
||||
|
||||
### General options
|
||||
|
||||
* `DATABASE_URL`: Configures the database which Part-DB uses. For mysql use a string in the form
|
||||
of `mysql://<USERNAME>:<PASSWORD>@<HOST>:<PORT>/<TABLE_NAME>` here
|
||||
(e.g. `DATABASE_URL=mysql://user:password@127.0.0.1:3306/part-db`). For sqlite use the following format to specify the
|
||||
* `DATABASE_URL`: Configures the database which Part-DB uses:
|
||||
* For MySQL (or MariaDB) use a string in the form of `mysql://<USERNAME>:<PASSWORD>@<HOST>:<PORT>/<TABLE_NAME>` here
|
||||
(e.g. `DATABASE_URL=mysql://user:password@127.0.0.1:3306/part-db`).
|
||||
* For SQLite use the following format to specify the
|
||||
absolute path where it should be located `sqlite:///path/part/app.db`. You can use `%kernel.project_dir%` as
|
||||
placeholder for the Part-DB root folder (e.g. `sqlite:///%kernel.project_dir%/var/app.db`)
|
||||
* For Postgresql use a string in the form of `DATABASE_URL=postgresql://user:password@127.0.0.1:5432/part-db?serverVersion=x.y`.
|
||||
|
||||
Please note that **`serverVersion=x.y`** variable is required due to dependency of Symfony framework.
|
||||
|
||||
* `DATABASE_MYSQL_USE_SSL_CA`: If this value is set to `1` or `true` and a MySQL connection is used, then the connection
|
||||
is encrypted by SSL/TLS and the server certificate is verified against the system CA certificates or the CA certificate
|
||||
bundled with Part-DB. Set `DATABASE_MYSQL_SSL_VERIFY_CERT` if you want to accept all certificates.
|
||||
* `DEFAULT_LANG`: The default language to use server wide (when no language is explicitly specified by a user or via
|
||||
* `DATABASE_EMULATE_NATURAL_SORT` (default 0): If set to 1, Part-DB will emulate natural sorting, even if the database
|
||||
does not support it natively. However this is much slower than the native sorting, and contain bugs or quirks, so use
|
||||
it only, if you have to.
|
||||
* `DEFAULT_LANG`: The default language to use server-wide (when no language is explicitly specified by a user or via
|
||||
language chooser). Must be something like `en`, `de`, `fr`, etc.
|
||||
* `DEFAULT_TIMEZONE`: The default timezone to use globally, when a user has no timezone specified. Must be something
|
||||
like `Europe/Berlin`. See [here](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) under TZ Database name
|
||||
|
@ -53,7 +61,7 @@ bundled with Part-DB. Set `DATABASE_MYSQL_SSL_VERIFY_CERT` if you want to accept
|
|||
* `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 a URL and create it as local file. Please note that this allows users access to all
|
||||
download a file specified as a URL and create it as a local file. Please note that this allows users access to all
|
||||
resources publicly available to the server (so full access to other servers in the same local network), which could
|
||||
be a security risk.
|
||||
* `ATTACHMENT_DOWNLOAD_BY_DEFAULT`: When this is set to 1, the "download external file" checkbox is checked by default
|
||||
|
@ -63,7 +71,7 @@ bundled with Part-DB. Set `DATABASE_MYSQL_SSL_VERIFY_CERT` if you want to accept
|
|||
not set their own picture). The users browsers have to download the pictures from a third-party (gravatar) 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
|
||||
to specify the size in kilobytes, megabytes or gigabytes. By default `100M` (100 megabytes). Please note that this is
|
||||
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.
|
||||
|
@ -71,8 +79,8 @@ bundled with Part-DB. Set `DATABASE_MYSQL_SSL_VERIFY_CERT` if you want to accept
|
|||
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
|
||||
* `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 an existing part
|
||||
* `part_delete`: Delete operation of an existing part
|
||||
|
@ -83,6 +91,10 @@ bundled with Part-DB. Set `DATABASE_MYSQL_SSL_VERIFY_CERT` if you want to accept
|
|||
* `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.
|
||||
* `APP_SECRET`: This variable is a configuration parameter used for various security-related purposes,
|
||||
particularly for securing and protecting various aspects of your application. It's a secret key that is used for
|
||||
cryptographic operations and security measures (session management, CSRF protection, etc..). Therefore this
|
||||
value should be handled as confidential data and not shared publicly.
|
||||
|
||||
### E-Mail settings
|
||||
|
||||
|
@ -91,10 +103,10 @@ bundled with Part-DB. Set `DATABASE_MYSQL_SSL_VERIFY_CERT` if you want to accept
|
|||
mail account, you can use the following syntax `MAILER_DSN=smtp://user:password@smtp.mailserver.invalid:587`
|
||||
* `EMAIL_SENDER_EMAIL`: The email address from which emails should be sent from (in most cases this has to be the same
|
||||
as the email address used for SMTP access)
|
||||
* `EMAIL_SENDER_NAME`: Similar to `EMAIL_SENDER_EMAIL` but this allows you to specify the name from which the mails are
|
||||
* `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 want to allow users to reset their password via an email
|
||||
notification. You have to configure the mailprovider first before via the MAILER_DSN setting.
|
||||
notification. You have to configure the mail provider first before via the MAILER_DSN setting.
|
||||
|
||||
### Table related settings
|
||||
|
||||
|
@ -105,15 +117,15 @@ bundled with Part-DB. Set `DATABASE_MYSQL_SSL_VERIFY_CERT` if you want to accept
|
|||
Also specify the default order of the columns. This is a comma separated list of column names. Available columns
|
||||
are: `name`, `id`, `ipn`, `description`, `category`, `footprint`, `manufacturer`, `storage_location`, `amount`, `minamount`, `partUnit`, `addedDate`, `lastModified`, `needs_review`, `favorite`, `manufacturing_status`, `manufacturer_product_number`, `mass`, `tags`, `attachments`, `edit`.
|
||||
|
||||
### History/Eventlog related settings
|
||||
### 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
|
||||
* `HISTORY_SAVE_CHANGED_FIELDS`: When this option is set to true, the name of the fields that 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
|
||||
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.
|
||||
|
@ -126,10 +138,10 @@ then `HISTORY_SAVE_CHANGED_FIELDS`, `HISTORY_SAVE_CHANGED_DATA` and `HISTORY_SAV
|
|||
|
||||
### Error pages settings
|
||||
|
||||
* `ERROR_PAGE_ADMIN_EMAIL`: You can set an email-address here, which is shown on the error page, who should be contacted
|
||||
* `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 sensitive information, but could confuse end-users.
|
||||
contain sensitive information but could confuse end-users.
|
||||
|
||||
### EDA related settings
|
||||
|
||||
|
@ -143,21 +155,21 @@ then `HISTORY_SAVE_CHANGED_FIELDS`, `HISTORY_SAVE_CHANGED_DATA` and `HISTORY_SAV
|
|||
|
||||
The following settings can be used to enable and configure Single-Sign on via SAML. This allows users to log in 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
|
||||
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 backed up by the backup script, so you have to back up 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.
|
||||
have to configure the SAML settings below before you can use this feature.
|
||||
* `SAML_BEHIND_PROXY`: Set this to 1, if Part-DB is behind a reverse proxy. See [here]({% link installation/reverse-proxy.md %})
|
||||
for more information. Otherwise, leave it to 0 (default.)
|
||||
* `SAML_ROLE_MAPPING`: A [JSON](https://en.wikipedia.org/wiki/JSON) encoded map which specifies how Part-DB should
|
||||
* `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.
|
||||
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 afterward by editing the user.
|
||||
|
@ -185,27 +197,31 @@ want to edit it on docker, you have to map the file to a volume.
|
|||
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
|
||||
### 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 information (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.
|
||||
* `DEMO_MODE`: Set Part-DB into demo mode, which forbids users to change their passwords and settings. Used for the demo
|
||||
instance, should not be needed for normal installations.
|
||||
instance. This should not be needed for normal installations.
|
||||
* `NO_URL_REWRITE_AVAILABLE` (allowed values `true` or `false`): Set this value to true, if your webserver does not
|
||||
support rewrite. In this case, all URL paths will contain index.php/, which is needed then. Normally this setting do
|
||||
support rewrite. In this case, all URL paths will contain index.php/, which is needed then. Normally this setting does
|
||||
not need to be changed.
|
||||
* `REDIRECT_TO_HTTPS`: If this is set to true, all requests to http will be redirected to https. This is useful, if your
|
||||
webserver does not already do this (like the one used in the demo instance). If your webserver already redirects to
|
||||
https, you don't need to set this. Ensure that Part-DB is accessible via https, before you enable this setting.
|
||||
* `REDIRECT_TO_HTTPS`: If this is set to true, all requests to http will be redirected to https. This is useful if your
|
||||
web server does not already do this (like the one used in the demo instance). If your web server already redirects to
|
||||
https, you don't need to set this. Ensure that Part-DB is accessible via HTTPS before you enable this setting.
|
||||
* `FIXER_API_KEY`: If you want to automatically retrieve exchange rates for base currencies other than euros, you have to
|
||||
configure an exchange rate provider API. [Fixer.io](https://fixer.io/) is preconfigured, and you just have to register
|
||||
there and set the retrieved API key in this environment variable.
|
||||
* `APP_ENV`: This value should always be set to `prod` in normal use. Set it to `dev` to enable debug/development
|
||||
mode. (**You should not do this on a publicly accessible server, as it will leak sensitive information!**)
|
||||
* `BANNER`: You can configure the text that should be shown as the banner on the homepage. Useful especially for docker
|
||||
container. In all other applications you can just change the `config/banner.md` file.
|
||||
containers. In all other applications you can just change the `config/banner.md` file.
|
||||
* `DISABLE_YEAR2038_BUG_CHECK`: If set to `1`, the year 2038 bug check is disabled on 32-bit systems, and dates after
|
||||
2038 are no longer forbidden. However this will lead to 500 error messages when rendering dates after 2038 as all current
|
||||
32-bit PHP versions can not format these dates correctly. This setting is for the case that future PHP versions will
|
||||
handle this correctly on 32-bit systems. 64-bit systems are not affected by this bug, and the check is always disabled.
|
||||
|
||||
## Banner
|
||||
|
||||
|
@ -218,8 +234,7 @@ markdown (and even some subset of HTML) syntax to format the text.
|
|||
You can also configure some options via the `config/parameters.yaml` file. This should normally not need,
|
||||
and you should know what you are doing, when you change something here. You should expect, that you will have to do some
|
||||
manual merge, when you have changed something here and update to a newer version of Part-DB. It is possible that
|
||||
configuration
|
||||
options here will change or completely removed in future versions of Part-DB.
|
||||
configuration options here will change or be completely removed in future versions of Part-DB.
|
||||
|
||||
If you change something here, you have to clear the cache, before the changes will take effect with the
|
||||
command `bin/console cache:clear`.
|
||||
|
@ -237,4 +252,4 @@ The following options are available:
|
|||
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
|
||||
* `partdb.available_themes`: The list of available themes a user can choose from.
|
||||
* `partdb.available_themes`: The list of available themes a user can choose from.
|
||||
|
|
|
@ -25,10 +25,10 @@ It is installed on a web server and so can be accessed with any browser without
|
|||
|
||||
## Features
|
||||
|
||||
* Inventory management of your electronic parts. Each part can be assigned to a category, footprint, manufacturer
|
||||
* Inventory management of your electronic parts. Each part can be assigned to a category, footprint, manufacturer,
|
||||
and multiple store locations and price information. Parts can be grouped using tags. You can associate various files
|
||||
like datasheets or pictures with the parts.
|
||||
* Multi-Language support (currently German, English, Russian, Japanese and French (experimental))
|
||||
* Multi-language support (currently German, English, Russian, Japanese and French (experimental))
|
||||
* 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.
|
||||
|
@ -41,12 +41,12 @@ It is installed on a web server and so can be accessed with any browser without
|
|||
* 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.
|
||||
* MySQL and SQLite supported as database backends
|
||||
* MySQL, SQLite and PostgreSQL are supported as database backends
|
||||
* 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
|
||||
* 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 %}))
|
||||
* API to access Part-DB from other applications/scripts
|
||||
* [Integration with KiCad]({%link usage/eda_integration.md %}): Use Part-DB as central datasource for your
|
||||
|
|
|
@ -7,10 +7,18 @@ nav_order: 1
|
|||
|
||||
# Choosing database: SQLite or MySQL
|
||||
|
||||
Part-DB saves its data in a [relational (SQL) database](https://en.wikipedia.org/wiki/Relational_database). Part-DB
|
||||
supports either the use of [SQLite](https://www.sqlite.org/index.html)
|
||||
or [MySQL](https://www.mysql.com/) / [MariaDB](https://mariadb.org/) (which are mostly the same, except for some minor
|
||||
differences).
|
||||
Part-DB saves its data in a [relational (SQL) database](https://en.wikipedia.org/wiki/Relational_database).
|
||||
|
||||
For this multiple database types are supported, currently these are:
|
||||
|
||||
* [SQLite](https://www.sqlite.org/index.html)
|
||||
* [MySQL](https://www.mysql.com/) / [MariaDB](https://mariadb.org/) (which are mostly the same, except for some minor
|
||||
differences)
|
||||
* [PostgreSQL](https://www.postgresql.org/)
|
||||
|
||||
All these database types allow for the same basic functionality and allow Part-DB to run. However, there are some minor
|
||||
differences between them, which might be important for you. Therefore the pros and cons of the different database types
|
||||
are listed here.
|
||||
|
||||
{: .important }
|
||||
You have to choose between the database types before you start using Part-DB and **you can not change it (easily) after
|
||||
|
@ -18,30 +26,157 @@ you have started creating data**. So you should choose the database type for you
|
|||
|
||||
## Comparison
|
||||
|
||||
**SQLite** is the default database type which is configured out of the box. All data is saved in a single file (
|
||||
normally `var/app.db` in the Part-DB folder) and no additional installation or configuration besides Part-DB is needed.
|
||||
To use **MySQL/MariaDB** as database, you have to install and configure the MySQL server, configure it and create a
|
||||
database and user for Part-DB, which needs some additional work. When using docker you need an additional docker
|
||||
container, and volume for the data
|
||||
### SQLite
|
||||
|
||||
When using **SQLite** The database can be backuped easily by just copying the SQLite file to a safe place. Ideally the *
|
||||
*MySQL** database has to be dumped to a SQL file (using `mysqldump`). The `console partdb:backup` command can do this
|
||||
automatically
|
||||
#### Pros
|
||||
|
||||
However, SQLite does not support certain operations like regex search, which has to be emulated by PHP and therefore are
|
||||
pretty slow compared to the same operation at MySQL. In future there might be features that may only be available, when
|
||||
using MySQL. Also SQLite has limitations in comparisons and sorting of unicode characters, which might lead to unexpected
|
||||
behavior when using non-ASCII characters in your data. For example `µ` (micro sign) is not seen as equal to `μ`(greek minuscle mu),
|
||||
therefore searching for `µ` (micro sign) will not find parts containing `μ` (mu) and vice versa. In MySQL identical
|
||||
looking characters are seen as equal, which is more intuitive in most cases.
|
||||
* **Easy to use**: No additional installation or configuration is needed, just start Part-DB and it will work out of the box
|
||||
* **Easy backup**: Just copy the SQLite file to a safe place, and you have a backup, which you can restore by copying it
|
||||
back. No need to work with SQL dumps
|
||||
|
||||
In general MySQL might perform better for big Part-DB instances with many entries, lots of users and high activity, than
|
||||
SQLite.
|
||||
#### Cons
|
||||
|
||||
## Conclusion and Suggestion
|
||||
* **Performance**: SQLite is not as fast as MySQL or PostgreSQL, especially when using complex queries or many users.
|
||||
* **Emulated RegEx search**: SQLite does not support RegEx search natively. Part-DB can emulate it, however that is pretty slow.
|
||||
* **Emualted natural sorting**: SQLite does not support natural sorting natively. Part-DB can emulate it, but it is pretty slow.
|
||||
* **Limitations with Unicode**: SQLite has limitations in comparisons and sorting of Unicode characters, which might lead to
|
||||
unexpected behavior when using non-ASCII characters in your data. For example `µ` (micro sign) is not seen as equal to
|
||||
`μ` (greek minuscule mu), therefore searching for `µ` (micro sign) will not find parts containing `μ` (mu) and vice versa.
|
||||
The other databases behave more intuitive in this case.
|
||||
* **No advanced features**: SQLite do no support many of the advanced features of MySQL or PostgreSQL, which might be utilized
|
||||
in future versions of Part-DB
|
||||
|
||||
|
||||
### MySQL/MariaDB
|
||||
|
||||
**If possible, it is recommended to use MariaDB 10.7+ (instead of MySQL), as it supports natural sorting of columns natively.**
|
||||
|
||||
#### Pros
|
||||
|
||||
* **Performance**: Compared to SQLite, MySQL/MariaDB will probably perform better, especially in large databases with many
|
||||
users and high activity.
|
||||
* **Natural Sorting**: MariaDB 10.7+ supports natural sorting of columns. On other databases it has to be emulated, which is pretty
|
||||
slow.
|
||||
* **Native RegEx search**: MySQL supports RegEx search natively, which is faster than emulating it in PHP.
|
||||
* **Advanced features**: MySQL/MariaDB supports many advanced features, which might be utilized in future versions of Part-DB.
|
||||
* **Full Unicode support**: MySQL/MariaDB has better support for Unicode characters, which makes it more intuitive to use
|
||||
non-ASCII characters in your data.
|
||||
|
||||
#### Cons
|
||||
|
||||
* **Additional installation and configuration**: You have to install and configure the MySQL server, create a database and
|
||||
user for Part-DB, which needs some additional work compared to SQLite.
|
||||
* **Backup**: The MySQL database has to be dumped to a SQL file (using `mysqldump`). The `console partdb:backup` command can automate this.
|
||||
|
||||
|
||||
### PostgreSQL
|
||||
|
||||
#### Pros
|
||||
* **Performance**: PostgreSQL is known for its performance, especially in large databases with many users and high activity.
|
||||
* **Advanced features**: PostgreSQL supports many advanced features, which might be utilized in future versions of Part-DB.
|
||||
* **Full Unicode support**: PostgreSQL has better support for Unicode characters, which makes it more intuitive to use
|
||||
non-ASCII characters in your data.
|
||||
* **Native RegEx search**: PostgreSQL supports RegEx search natively, which is faster than emulating it in PHP.
|
||||
* **Native Natural Sorting**: PostgreSQL supports natural sorting of columns natively in all versions and in general the support for it
|
||||
is better than on MariaDB.
|
||||
* **Support of transactional DDL**: PostgreSQL supports transactional DDL, which means that if you encounter a problem during a schema change,
|
||||
the database will automatically rollback the changes. On MySQL/MariaDB you have to manually rollback the changes, by restoring from a database backup.
|
||||
|
||||
#### Cons
|
||||
* **New backend**: The support of postgresql is new, and it was not tested as much as the other backends. There might be some bugs caused by this.
|
||||
* **Additional installation and configuration**: You have to install and configure the PostgreSQL server, create a database and
|
||||
user for Part-DB, which needs some additional work compared to SQLite.
|
||||
* **Backup**: The PostgreSQL database has to be dumped to a SQL file (using `pg_dump`). The `console partdb:backup` command can automate this.
|
||||
|
||||
|
||||
## Recommendation
|
||||
|
||||
When you are a hobbyist and use Part-DB for your own small inventory management with only you as user (or maybe sometimes
|
||||
a few other people), then the easy-to-use SQLite database will be fine.
|
||||
a few other people), then the easy-to-use SQLite database will be fine, as long as you can live with the limitations, stated above.
|
||||
However using MariaDB (or PostgreSQL), has no disadvantages in that situation (besides the initial setup requirements), so you might
|
||||
want to use it, to be prepared for future use cases.
|
||||
|
||||
When you are planning to have a very big database, with a lot of entries and many users which regularly (and
|
||||
concurrently) using Part-DB you should maybe use MySQL as this will scale better.
|
||||
When you are planning to have a very big database, with a lot of entries and many users which regularly using Part-DB, then you should
|
||||
use MariaDB or PostgreSQL, as they will perform better in that situation and allow for more advanced features.
|
||||
If you should use MariaDB or PostgreSQL depends on your personal preference and what you already have installed on your servers and
|
||||
what you are familiar with.
|
||||
|
||||
## Using the different databases
|
||||
|
||||
The only difference in using the different databases, is a different value in the `DATABASE_URL` environment variable in the `.env.local` file
|
||||
or in the `DATABASE_URL` environment variable in your server or container configuration. It has the shape of a URL, where the scheme (the part before `://`)
|
||||
is the database type, and the rest is connection information.
|
||||
|
||||
**The env var format below is for the `env.local` file. It might work differently for other env configuration. E.g. in a docker-compose file you have to remove the quotes!**
|
||||
|
||||
### SQLite
|
||||
|
||||
```shell
|
||||
DATABASE_URL="sqlite:///%kernel.project_dir%/var/app.db"
|
||||
```
|
||||
|
||||
Here you just need to configure the path to the SQLite file, which is created by Part-DB when performing the database migrations.
|
||||
The `%kernel.project_dir%` is a placeholder for the path to the project directory, which is replaced by the actual path by Symfony, so that you do not
|
||||
need to specify the path manually. In the example the database will be created as `app.db` in the `var` directory of your Part-DB installation folder.
|
||||
|
||||
### MySQL/MariaDB
|
||||
|
||||
```shell
|
||||
DATABASE_URL="mysql://user:password@127.0.0.1:3306/database?serverVersion=8.0.37"
|
||||
```
|
||||
|
||||
Here you have to replace `user`, `password` and `database` with the credentials of the MySQL/MariaDB user and the database name you want to use.
|
||||
The host (here 127.0.0.1) and port should also be specified according to your MySQL/MariaDB server configuration.
|
||||
|
||||
In the `serverVersion` parameter you can specify the version of the MySQL/MariaDB server you are using, in the way the server returns it
|
||||
(e.g. `8.0.37` for MySQL and `10.4.14-MariaDB`). If you do not know it, you can leave the default value.
|
||||
|
||||
If you want to use a unix socket for the connection instead of a TCP connnection, you can specify the socket path in the `unix_socket` parameter.
|
||||
```shell
|
||||
DATABASE_URL="mysql://user:password@localhost/database?serverVersion=8.0.37&unix_socket=/var/run/mysqld/mysqld.sock"
|
||||
```
|
||||
|
||||
### PostgreSQL
|
||||
|
||||
```shell
|
||||
DATABASE_URL="postgresql://db_user:db_password@127.0.0.1:5432/db_name?serverVersion=12.19&charset=utf8"
|
||||
```
|
||||
|
||||
Here you have to replace `db_user`, `db_password` and `db_name` with the credentials of the PostgreSQL user and the database name you want to use.
|
||||
The host (here 127.0.0.1) and port should also be specified according to your PostgreSQL server configuration.
|
||||
|
||||
In the `serverVersion` parameter you can specify the version of the PostgreSQL server you are using, in the way the server returns it
|
||||
(e.g. `12.19 (Debian 12.19-1.pgdg120+1)`). If you do not know it, you can leave the default value.
|
||||
|
||||
The `charset` parameter specify the character set of the database. It should be set to `utf8` to ensure that all characters are stored correctly.
|
||||
|
||||
If you want to use a unix socket for the connection instead of a TCP connnection, you can specify the socket path in the `host` parameter.
|
||||
```shell
|
||||
DATABASE_URL="postgresql://db_user@localhost/db_name?serverVersion=16.6&charset=utf8&host=/var/run/postgresql"
|
||||
```
|
||||
|
||||
|
||||
## Natural Sorting
|
||||
|
||||
Natural sorting is the sorting of strings in a way that numbers are sorted by their numerical value, not by their ASCII value.
|
||||
|
||||
For example in the classical binary sorting the string `DIP-4`, `DIP-8`, `DIP-16`, `DIP-28` would be sorted as following:
|
||||
|
||||
* `DIP-16`
|
||||
* `DIP-28`
|
||||
* `DIP-4`
|
||||
* `DIP-8`
|
||||
|
||||
In natural sorting, it would be sorted as:
|
||||
|
||||
* `DIP-4`
|
||||
* `DIP-8`
|
||||
* `DIP-16`
|
||||
* `DIP-28`
|
||||
|
||||
Part-DB can sort names in part tables and tree views naturally. PostgreSQL and MariaDB 10.7+ support natural sorting natively,
|
||||
and it is automatically used if available.
|
||||
|
||||
For SQLite and MySQL < 10.7 it has to be emulated if wanted, which is pretty slow. Therefore it has to be explicity enabled by setting the
|
||||
`DATABASE_EMULATE_NATURAL_SORT` environment variable to `1`. If it is 0 the classical binary sorting is used, on these databases. The emulations
|
||||
might have some quirks and issues, so it is recommended to use a database which supports natural sorting natively, if you want to use it.
|
||||
|
|
|
@ -6,4 +6,6 @@ has_children: true
|
|||
---
|
||||
|
||||
# Installation
|
||||
Below you can find some guides to install Part-DB.
|
||||
Below you can find some guides to install Part-DB.
|
||||
|
||||
For the hobbyists without much experience, we recommend the docker installation or direct installation on debian.
|
|
@ -16,11 +16,14 @@ where docker is available (especially recommended for Windows and macOS).
|
|||
> network.
|
||||
> If you want to expose Part-DB to the internet, you have to configure a reverse proxy with an SSL certificate!
|
||||
|
||||
It is recommended to install Part-DB on a 64-bit system, as the 32-bit version of PHP is affected by the
|
||||
[Year 2038 problem](https://en.wikipedia.org/wiki/Year_2038_problem) and can not handle dates after 2038 correctly.
|
||||
|
||||
## Docker-compose
|
||||
|
||||
Docker-compose configures the needed images and automatically creates the needed containers and volumes.
|
||||
|
||||
1. Install docker and docker-compose like described under https://docs.docker.com/compose/install/
|
||||
1. Install docker and docker-compose as described under https://docs.docker.com/compose/install/
|
||||
2. Create a folder where the Part-DB data should live
|
||||
3. Create a file named docker-compose.yaml with the following content:
|
||||
|
||||
|
@ -44,6 +47,12 @@ services:
|
|||
- DATABASE_URL=sqlite:///%kernel.project_dir%/var/db/app.db
|
||||
# In docker env logs will be redirected to stderr
|
||||
- APP_ENV=docker
|
||||
|
||||
# Uncomment this, if you want to use the automatic database migration feature. With this you have you do not have to
|
||||
# run the doctrine:migrations:migrate commands on installation or upgrade. A database backup is written to the uploads/
|
||||
# folder (under .automigration-backup), so you can restore it, if the migration fails.
|
||||
# This feature is currently experimental, so use it at your own risk!
|
||||
# - DB_AUTOMIGRATE=true
|
||||
|
||||
# You can configure Part-DB using environment variables
|
||||
# Below you can find the most essential ones predefined
|
||||
|
@ -74,7 +83,7 @@ services:
|
|||
# - TRUSTED_PROXIES=127.0.0.0/8,::1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16
|
||||
```
|
||||
|
||||
4. Customize the settings by changing the environment variables (or add new ones). See [Configuration]({% link
|
||||
4. Customize the settings by changing the environment variables (or adding new ones). See [Configuration]({% link
|
||||
configuration.md %}) for more information.
|
||||
5. Inside the folder, run
|
||||
|
||||
|
@ -90,10 +99,10 @@ docker exec --user=www-data partdb php bin/console doctrine:migrations:migrate
|
|||
|
||||
and watch for the password output
|
||||
|
||||
6. Part-DB is available under `http://localhost:8080` and you can log in with username `admin` and the password shown
|
||||
6. Part-DB is available under `http://localhost:8080` and you can log in with the username `admin` and the password shown
|
||||
before
|
||||
|
||||
The docker image uses a SQLite database and all data (database, uploads and other media) is put into folders relative to
|
||||
The docker image uses a SQLite database and all data (database, uploads, and other media) is put into folders relative to
|
||||
the docker-compose.yml.
|
||||
|
||||
### MySQL
|
||||
|
@ -127,6 +136,12 @@ services:
|
|||
# In docker env logs will be redirected to stderr
|
||||
- APP_ENV=docker
|
||||
|
||||
# Uncomment this, if you want to use the automatic database migration feature. With this you have you do not have to
|
||||
# run the doctrine:migrations:migrate commands on installation or upgrade. A database backup is written to the uploads/
|
||||
# folder (under .automigration-backup), so you can restore it, if the migration fails.
|
||||
# This feature is currently experimental, so use it at your own risk!
|
||||
# - DB_AUTOMIGRATE=true
|
||||
|
||||
# You can configure Part-DB using environment variables
|
||||
# Below you can find the most essential ones predefined
|
||||
# However you can add add any other environment configuration you want here
|
||||
|
@ -155,7 +170,7 @@ services:
|
|||
container_name: partdb_database
|
||||
image: mysql:8.0
|
||||
restart: unless-stopped
|
||||
command: --default-authentication-plugin=mysql_native_password
|
||||
command: --default-authentication-plugin=mysql_native_password --log-bin-trust-function-creators=1
|
||||
environment:
|
||||
# Change this Password
|
||||
MYSQL_ROOT_PASSWORD: SECRET_ROOT_PASSWORD
|
||||
|
@ -183,25 +198,29 @@ docker exec --user=www-data partdb php bin/console doctrine:migrations:migrate
|
|||
|
||||
## Direct use of docker image
|
||||
|
||||
You can use the `jbtronics/part-db1:master` image directly. You have to expose the port 80 to a host port and configure
|
||||
You can use the `jbtronics/part-db1:master` image directly. You have to expose port 80 to a host port and configure
|
||||
volumes for `/var/www/html/uploads` and `/var/www/html/public/media`.
|
||||
|
||||
If you want to use SQLite database (which is default), you have to configure Part-DB to put the database file in a
|
||||
mapped volume via the `DATABASE_URL` environment variable.
|
||||
For example if you set `DATABASE_URL=sqlite:///%kernel.project_dir%/var/db/app.db` then you will have to map
|
||||
For example, if you set `DATABASE_URL=sqlite:///%kernel.project_dir%/var/db/app.db` then you will have to map
|
||||
the `/var/www/html/var/db/` folder to the docker container (see docker-compose.yaml for example).
|
||||
|
||||
You also have to create the database like described above in step 4.
|
||||
You also have to create the database as described above in step 4.
|
||||
|
||||
## Running console commands
|
||||
|
||||
You can run the console commands described in README by
|
||||
executing `docker exec --user=www-data -it partdb bin/console [command]`
|
||||
|
||||
{: .warning }
|
||||
> If you run a root console inside the container, and wanna execute commands on the webserver behalf, be sure to use `sudo -E` command (with the `-E` flag) to preserve env variables from the current shell.
|
||||
> Otherwise Part-DB console might use the wrong configuration to execute commands.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
*Login not possible. Login page is just reloading and no error message is shown or something like "CSFR token invalid"*:
|
||||
*Login is not possible. Login page is just reloading and no error message is shown or something like "CSFR token invalid"*:
|
||||
|
||||
Clear all cookies in your browser or use an inkognito tab for Part-DB.
|
||||
This related to the fact that Part-DB can not set cookies via HTTP, after some webpage has set cookies before under
|
||||
localhost via https. This is a security mechanism of the browser and can not be bypassed by Part-DB.
|
||||
Clear all cookies in your browser or use an incognito tab for Part-DB.
|
||||
This is related to the fact that Part-DB can not set cookies via HTTP after some webpages have set cookies before under
|
||||
localhost via HTTPS. This is a security mechanism of the browser and can not be bypassed by Part-DB.
|
||||
|
|
|
@ -8,9 +8,9 @@ nav_order: 4
|
|||
# Part-DB installation guide for Debian 11 (Bullseye)
|
||||
|
||||
This guide shows you how to install Part-DB directly on Debian 11 using apache2 and SQLite. This guide should work with
|
||||
recent Ubuntu and other Debian based distributions with little to no changes.
|
||||
recent Ubuntu and other Debian-based distributions with little to no changes.
|
||||
Depending on what you want to do, using the prebuilt docker images may be a better choice, as you don't need to install
|
||||
this many dependencies. See [here]({% link installation/installation_docker.md %}) for more information of the docker
|
||||
this many dependencies. See [here]({% link installation/installation_docker.md %}) for more information on the docker
|
||||
installation.
|
||||
|
||||
{: .warning }
|
||||
|
@ -18,6 +18,9 @@ installation.
|
|||
> network.
|
||||
> If you want to expose Part-DB to the internet, you HAVE to configure an SSL connection!
|
||||
|
||||
It is recommended to install Part-DB on a 64-bit system, as the 32-bit version of PHP is affected by the
|
||||
[Year 2038 problem](https://en.wikipedia.org/wiki/Year_2038_problem) and can not handle dates after 2038 correctly.
|
||||
|
||||
## Installation with SQLite database
|
||||
|
||||
### Install prerequisites
|
||||
|
@ -30,8 +33,8 @@ 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 8.1 or
|
||||
higher, however it is recommended to use the most recent version of PHP for performance reasons and future
|
||||
Part-DB is written in [PHP](https://php.net) and therefore needs a 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 its default repositories, we have to add a repository for it. You can skip this
|
||||
|
@ -46,7 +49,7 @@ sudo curl -sSL https://packages.sury.org/php/README.txt | sudo bash -x
|
|||
sudo apt update && sudo apt upgrade
|
||||
```
|
||||
|
||||
Now you can install PHP 8.1 and required packages (change the 8.1 in the package version according to the version you
|
||||
Now you can install PHP 8.1 and the required packages (change the 8.1 in the package version according to the version you
|
||||
want to use):
|
||||
|
||||
```bash
|
||||
|
@ -57,8 +60,8 @@ The apache2 webserver should be already installed with this command and configur
|
|||
|
||||
### Install composer
|
||||
|
||||
Part-DB uses [composer](https://getcomposer.org/) to install required PHP libraries. As the versions shipped in the
|
||||
repositories is pretty old we install it manually:
|
||||
Part-DB uses [composer](https://getcomposer.org/) to install required PHP libraries. As the version shipped in the
|
||||
repositories is pretty old, we will install it manually:
|
||||
|
||||
```bash
|
||||
# Download composer installer script
|
||||
|
@ -71,8 +74,8 @@ chmod +x /usr/local/bin/composer
|
|||
|
||||
### Install yarn and nodejs
|
||||
|
||||
To build the frontend (the user interface) Part-DB uses [yarn](https://yarnpkg.com/). As it depends on Node.js and the
|
||||
shipped versions are pretty old, we install new versions from official Node.js repository:
|
||||
To build the front end (the user interface) Part-DB uses [yarn](https://yarnpkg.com/). As it depends on Node.js and the
|
||||
shipped versions are pretty old, we install new versions from the official Node.js repository:
|
||||
|
||||
```bash
|
||||
# Add recent node repository (nodejs 18 is supported until 2025)
|
||||
|
@ -102,7 +105,7 @@ later.
|
|||
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
|
||||
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
|
||||
|
@ -110,7 +113,7 @@ can switch to the latest stable version (tagged) by running the following comman
|
|||
git checkout $(git describe --tags $(git rev-list --tags --max-count=1))
|
||||
```
|
||||
|
||||
Alternatively you can check out a specific version by running (
|
||||
Alternatively, you can check out a specific version by running (
|
||||
see [GitHub Releases page](https://github.com/Part-DB/Part-DB-server/releases) for a list of available versions):
|
||||
|
||||
```bash
|
||||
|
@ -176,12 +179,12 @@ To check if everything is installed, run the following command:
|
|||
sudo -u www-data php bin/console partdb:check-requirements
|
||||
```
|
||||
|
||||
The most things should be green, and no red ones. Yellow messages means optional dependencies which are not important
|
||||
Most things should be green, and no red ones. Yellow messages mean optional dependencies which are not important
|
||||
but can improve performance and functionality.
|
||||
|
||||
### Create a database for Part-DB
|
||||
|
||||
Part-DB by default uses a file based sqlite database to store the data. Use the following command to create the
|
||||
Part-DB by default uses a file-based SQLite database to store the data. Use the following command to create the
|
||||
database. The database will normally be created at `/var/www/partdb/var/app.db`.
|
||||
|
||||
```bash
|
||||
|
@ -191,8 +194,7 @@ sudo -u www-data php bin/console doctrine:migrations:migrate
|
|||
The command will warn you about schema changes and potential data loss. Continue with typing `yes`.
|
||||
|
||||
The command will output several lines of information. Somewhere should be a yellow background message
|
||||
like `The initial password for the "admin" user is: f502481134`. Write down this password as you will need it later for
|
||||
initial login.
|
||||
like `The initial password for the "admin" user is: f502481134`. Write down this password as you will need it later for the initial login.
|
||||
|
||||
### Configure apache2 to show Part-DB
|
||||
|
||||
|
@ -248,7 +250,7 @@ sudo service apache2 restart
|
|||
```
|
||||
|
||||
and Part-DB should now be available under `http://YourServerIP` (or `http://partdb.lan` if you configured DNS in your
|
||||
network to point on the server).
|
||||
network to point to the server).
|
||||
|
||||
### Login to Part-DB
|
||||
|
||||
|
@ -288,7 +290,7 @@ sudo -u www-data php bin/console cache:clear
|
|||
|
||||
## MySQL/MariaDB database
|
||||
|
||||
To use a MySQL database, follow the steps from above (except the creation of database, we will do this later).
|
||||
To use a MySQL database, follow the steps from above (except the creation of the database, we will do this later).
|
||||
Debian 11 does not ship MySQL in its repositories anymore, so we use the compatible MariaDB instead:
|
||||
|
||||
1. Install maria-db with:
|
||||
|
@ -340,7 +342,7 @@ exit
|
|||
Change it to the following (you have to replace `YOUR_SECRET_PASSWORD` with the password you have chosen in step 3):
|
||||
|
||||
```
|
||||
DATABASE_URL=DATABASE_URL=mysql://partdb:YOUR_SECRET_PASSWORD@127.0.0.1:3306/partdb
|
||||
DATABASE_URL=mysql://partdb:YOUR_SECRET_PASSWORD@127.0.0.1:3306/partdb
|
||||
```
|
||||
|
||||
5. Create the database schema with:
|
||||
|
|
42
docs/installation/kubernetes.md
Normal file
42
docs/installation/kubernetes.md
Normal file
|
@ -0,0 +1,42 @@
|
|||
---
|
||||
title: Kubernetes / Helm
|
||||
layout: default
|
||||
parent: Installation
|
||||
nav_order: 5
|
||||
---
|
||||
|
||||
# Kubernetes / Helm Charts
|
||||
|
||||
If you are using Kubernetes, you can use the [helm charts](https://helm.sh/) provided in this [repository](https://github.com/Part-DB/helm-charts).
|
||||
|
||||
## Usage
|
||||
|
||||
[Helm](https://helm.sh) must be installed to use the charts. Please refer to
|
||||
Helm's [documentation](https://helm.sh/docs) to get started.
|
||||
|
||||
Once Helm has been set up correctly, add the repo as follows:
|
||||
|
||||
`helm repo add part-db https://part-db.github.io/helm-charts`
|
||||
|
||||
If you had already added this repo earlier, run `helm repo update` to retrieve
|
||||
the latest versions of the packages. You can then run `helm search repo
|
||||
part-db` to see the charts.
|
||||
|
||||
To install the part-db chart:
|
||||
|
||||
helm install my-part-db part-db/part-db
|
||||
|
||||
To uninstall the chart:
|
||||
|
||||
helm delete my-part-db
|
||||
|
||||
This repository is also available at [ArtifactHUB](https://artifacthub.io/packages/search?repo=part-db).
|
||||
|
||||
## Configuration
|
||||
|
||||
See the README in the [chart directory](https://github.com/Part-DB/helm-charts/tree/main/charts/part-db) for more
|
||||
information on the available configuration options.
|
||||
|
||||
## Bugreports
|
||||
|
||||
If you find issues related to the helm charts, please open an issue in the [helm-charts repository](https://github.com/Part-DB/helm-charts).
|
|
@ -13,7 +13,7 @@ configured.
|
|||
|
||||
## Setup
|
||||
|
||||
1. Install composer and yarn like described in the [apache guide]({% link installation/installation_guide-debian.md
|
||||
1. Install composer and yarn as described in the [apache guide]({% link installation/installation_guide-debian.md
|
||||
%}#install-composer).
|
||||
2. Create a folder for Part-DB and install and configure it as described
|
||||
3. Instead of creating the config for apache, add the following snippet to your nginx config:
|
||||
|
@ -52,6 +52,11 @@ server {
|
|||
location ~ \.php$ {
|
||||
return 404;
|
||||
}
|
||||
|
||||
# Set Content-Security-Policy for svg files, to block embedded javascript in there
|
||||
location ~* \.svg$ {
|
||||
add_header Content-Security-Policy "default-src 'self'; script-src 'none'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; frame-ancestors 'none';";
|
||||
}
|
||||
|
||||
error_log /var/log/nginx/parts.error.log;
|
||||
access_log /var/log/nginx/parts.access.log;
|
||||
|
|
31
docs/installation/proxmox.md
Normal file
31
docs/installation/proxmox.md
Normal file
|
@ -0,0 +1,31 @@
|
|||
---
|
||||
title: Proxmox VE LXC
|
||||
layout: default
|
||||
parent: Installation
|
||||
nav_order: 6
|
||||
---
|
||||
|
||||
# Proxmox VE LXC
|
||||
|
||||
{: .warning }
|
||||
> The proxmox VE LXC script for Part-DB is developed and maintained by [Proxmox VE Helper-Scripts](https://community-scripts.github.io/ProxmoxVE/)
|
||||
> and not by the Part-DB developers. Keep in mind that the script is not officially supported by the Part-DB developers.
|
||||
|
||||
If you are using Proxmox VE you can use the scripts provided by [Proxmox VE Helper-Scripts community](https://community-scripts.github.io/ProxmoxVE/scripts?id=part-db)
|
||||
to easily install Part-DB in a LXC container.
|
||||
|
||||
## Usage
|
||||
|
||||
To create a new LXC container with Part-DB, you can use the following command in the Proxmox VE shell:
|
||||
|
||||
```bash
|
||||
bash -c "$(wget -qLO - https://github.com/community-scripts/ProxmoxVE/raw/main/ct/part-db.sh)"
|
||||
```
|
||||
|
||||
The same command can be used to update an existing Part-DB container.
|
||||
|
||||
See the [helper script website](https://community-scripts.github.io/ProxmoxVE/scripts?id=part-db) for more information.
|
||||
|
||||
## Bugreports
|
||||
|
||||
If you find issues related to the proxmox VE LXC script, please open an issue in the [Proxmox VE Helper-Scripts repository](https://github.com/community-scripts/ProxmoxVE).
|
|
@ -48,7 +48,7 @@ the [Keycloak Getting Started Guide](https://www.keycloak.org/docs/latest/gettin
|
|||
*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.
|
||||
3. Click on `Save` to create a new client.
|
||||
|
||||
### Configure the SAML client
|
||||
|
||||
|
@ -56,7 +56,7 @@ the [Keycloak Getting Started Guide](https://www.keycloak.org/docs/latest/gettin
|
|||
* 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 `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.
|
||||
|
@ -135,8 +135,8 @@ On the first login of a SAML user, Part-DB will create a new user in the databas
|
|||
as the SAML user, but no password set. The user will be marked as a SAML user, so he can only log in 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.
|
||||
|
||||
For large organizations you maybe want to automatically assign permissions to SAML users based on the roles or
|
||||
|
||||
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.
|
||||
|
||||
|
@ -144,11 +144,11 @@ groups. See the next section for details.
|
|||
|
||||
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
|
||||
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
|
||||
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 on 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,
|
||||
|
@ -158,7 +158,7 @@ you can configure via the `.env.local` or `docker-compose.yml` file. Please note
|
|||
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`,
|
||||
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:
|
||||
|
||||
|
@ -176,9 +176,9 @@ If you want to assign users with a certain role to an empty group, provide the g
|
|||
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
|
||||
to configure your SAML identity provider to provide this attribute. For example, in Keycloak you can configure this
|
||||
attribute on 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
|
||||
|
@ -203,12 +203,12 @@ provide these attributes, you can use to automatically fill the corresponding fi
|
|||
|
||||
## Use SAML Login for existing users
|
||||
|
||||
Part-DB distinguishes between local users and SAML users. Local users are users, which can log in 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
|
||||
Part-DB distinguishes between local users and SAML users. Local users are users, that can log in via the Part-DB login form
|
||||
and 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
|
||||
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 log in 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 log in via SAML in the future.
|
||||
|
|
|
@ -12,34 +12,34 @@ nav_order: 101
|
|||
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.
|
||||
a new Part-DB instance. Most of the data can be migrated, however, there are some limitations, that you can find below.
|
||||
|
||||
## What can be imported
|
||||
|
||||
* Datastructures (Categories, Footprints, Storage Locations, Manufacturers, Distributors, Part Measurement Units)
|
||||
* Basic part information's (Name, Description, Comment, etc.)
|
||||
* Attachments and images of parts, projects, footprints, manufacturers and storage locations
|
||||
* Data structures (Categories, Footprints, Storage Locations, Manufacturers, Distributors, Part Measurement Units)
|
||||
* Basic part information (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
|
||||
* Users (optional): Passwords however will not be 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)
|
||||
* 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
|
||||
* Overage information for project parts (the overage info will be set as a 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
|
||||
* 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.
|
||||
1. Install Part-DB as 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`.
|
||||
|
@ -47,7 +47,7 @@ a new Part-DB instance. Most of the data can be migrated, however there are some
|
|||
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`.
|
||||
3. Go to 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.
|
||||
|
@ -63,5 +63,5 @@ option on the database import command (step 3):
|
|||
|
||||
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 management.
|
||||
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.
|
||||
Passwords can not be imported from PartKeepr and all imported users get marked as disabled. So to allow users to
|
||||
log in, you need to enable them in the user management and assign a password.
|
|
@ -16,7 +16,7 @@ on how to fix the problem. If you have a problem that is not listed here, please
|
|||
|
||||
If you encounter an error, try the following steps:
|
||||
|
||||
* Clear cache of Part-DB with the console command:
|
||||
* Clear the cache of Part-DB with the console command:
|
||||
|
||||
```bash
|
||||
php bin/console cache:clear
|
||||
|
@ -30,7 +30,7 @@ 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:
|
||||
## Search for the user and reset the 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
|
||||
|
|
|
@ -18,33 +18,32 @@ sections carefully before proceeding to upgrade.
|
|||
|
||||
* PHP 8.1 or higher is required now (Part-DB 0.5 required PHP 5.4+, Part-DB 0.6 PHP 7.0).
|
||||
Releases are available for Windows too, so almost everybody should be able to use PHP 8.1
|
||||
* **Console access highly required.** The installation of composer and frontend dependencies require console access,
|
||||
also more sensitive stuff like database migration work via CLI now, so you should have console access on your server.
|
||||
* **Console access is highly recommended.** The installation of composer and frontend dependencies require console access,
|
||||
also more sensitive stuff like database migration works via CLI now, so you should have console access on your server.
|
||||
* Markdown/HTML is now used instead of BBCode for rich text in description and command fields.
|
||||
It is possible to migrate your existing BBCode to Markdown
|
||||
via `php bin/console php bin/console partdb:migrations:convert-bbcode`.
|
||||
* Server exceptions are not logged to event log anymore. For security reasons (exceptions can contain sensitive
|
||||
information)
|
||||
exceptions are only logged to server log (by default under './var/log'), so only the server admins can access it.
|
||||
* Profile labels are now saved in Database (before they were saved in a separate JSON file). **The profiles of legacy
|
||||
* Server exceptions are not logged into event log anymore. For security reasons (exceptions can contain sensitive
|
||||
information) exceptions are only logged to server log (by default under './var/log'), so only the server admins can access it.
|
||||
* Profile labels are now saved in the database (before they were saved in a separate JSON file). **The profiles of legacy
|
||||
Part-DB versions can not be imported into new Part-DB 1.0**
|
||||
* Label placeholders now use the `[[PLACEHOLDER]]` format instead of `%PLACEHOLDER%`. Also, some placeholders has
|
||||
* Label placeholders now use the `[[PLACEHOLDER]]` format instead of `%PLACEHOLDER%`. Also, some placeholders have
|
||||
changed.
|
||||
* Configuration is now done via configuration files / environment variables instead of the WebUI (this maybe change in
|
||||
* Configuration is now done via configuration files/environment variables instead of the WebUI (this may change in
|
||||
the future).
|
||||
* Database updated are now done via console instead of the WebUI
|
||||
* Database updates 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
|
||||
* 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.
|
||||
and you may have to change the header line/field names of your CSV files.
|
||||
|
||||
## Missing features
|
||||
|
||||
* No possibility to mark parts for ordering (yet)
|
||||
* No possibility of marking parts for ordering (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,
|
||||
* 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
|
||||
* No resistor calculator or SMD label tools
|
||||
|
||||
## Upgrade process
|
||||
|
||||
|
@ -56,12 +55,12 @@ sections carefully before proceeding to upgrade.
|
|||
> Beware that all user and group permissions will be reset, and you have to set the permissions again
|
||||
> the new Part-DB as many permissions changed, and automatic migration is not possible.
|
||||
|
||||
1. Upgrade your existing Part-DB version the newest Part-DB 0.5.* version (at the moment Part-DB 0.5.8), like described
|
||||
1. Upgrade your existing Part-DB version the newest Part-DB 0.5.* version (at the moment Part-DB 0.5.8), as described
|
||||
in the old Part-DB's repository.
|
||||
2. Make a backup of your database and attachments. If something goes wrong during migration, you can use this backup to
|
||||
start over. If you have some more complex permission configuration, you maybe want to do screenshots of it, so you
|
||||
can redo it again later.
|
||||
3. Set up the new Part-DB like described in installation section. You will need to do the setup for a MySQL instance (
|
||||
3. Set up the new Part-DB as described in the installation section. You will need to do the setup for a MySQL instance (
|
||||
either via docker or direct installation). Set the `DATABASE_URL` environment variable in your `.env.local` (
|
||||
or `docker-compose.yaml`) to your existing database. (
|
||||
e.g. `DATABASE_URL=mysql://PARTDB_USER:PASSWORD@localhost:3306/DATABASE_NAME`)
|
||||
|
|
|
@ -7,8 +7,8 @@ parent: Usage
|
|||
# Backup and Restore Data
|
||||
|
||||
When working productively you should back up the data and configuration of Part-DB regularly to prevent data loss. This
|
||||
is also useful, if you want to migrate your Part-DB instance from one server to another. In that case you just have to
|
||||
back up the data on server 1, move the backup to server 2, install Part-DB on server 2 and restore the backup.
|
||||
is also useful if you want to migrate your Part-DB instance from one server to another. In that case, you just have to
|
||||
back up the data on server 1, move the backup to server 2, install Part-DB on server 2, and restore the backup.
|
||||
|
||||
## Backup (automatic / Part-DB supported)
|
||||
|
||||
|
@ -23,11 +23,11 @@ To back up all possible data, run the following
|
|||
command: `php bin/console partdb:backup --full /path/to/backup/partdb_backup.zip`.
|
||||
|
||||
It is possible to do only partial backups (config, attachments, or database). See `php bin/console partdb:backup --help`
|
||||
for more infos about these options.
|
||||
for more info about these options.
|
||||
|
||||
## Backup (manual)
|
||||
|
||||
There are 3 parts which have to be backup-ed: The configuration files, which contains the instance specific options, the
|
||||
3 parts have to be backup-ed: The configuration files, which contain the instance-specific options, the
|
||||
uploaded files of attachments, and the database containing the most data of Part-DB.
|
||||
Everything else like thumbnails and cache files, are recreated automatically when needed.
|
||||
|
||||
|
@ -42,7 +42,7 @@ You have to recursively copy the `uploads/` folder and the `public/media` folder
|
|||
|
||||
### Database
|
||||
|
||||
#### Sqlite
|
||||
#### SQLite
|
||||
|
||||
If you are using sqlite, it is sufficient to just copy your `app.db` from your database location (normally `var/app.db`)
|
||||
to your backup location.
|
||||
|
@ -55,8 +55,8 @@ interface (`mysqldump -uBACKUP -pPASSWORD DATABASE`)
|
|||
|
||||
## Restore
|
||||
|
||||
Install Part-DB as usual as described in the installation section, except the database creation / migration part. You
|
||||
have to use the same database type (sqlite or mysql) as on the back-up server instance.
|
||||
Install Part-DB as usual as described in the installation section, except for the database creation/migration part. You
|
||||
have to use the same database type (SQLite or MySQL) as on the backuped server instance.
|
||||
|
||||
### Restore configuration
|
||||
|
||||
|
@ -69,7 +69,7 @@ Copy the `uploads/` and the `public/media/` folder from your backup into your ne
|
|||
|
||||
### Restore database
|
||||
|
||||
#### Sqlite
|
||||
#### SQLite
|
||||
|
||||
Copy the backup-ed `app.db` into the database folder normally `var/app.db` in Part-DB root folder.
|
||||
|
||||
|
|
|
@ -25,6 +25,12 @@ is named `partdb`, you can execute the command `php bin/console cache:clear` wit
|
|||
docker exec --user=www-data partdb php bin/console cache:clear
|
||||
```
|
||||
|
||||
{: .warning }
|
||||
> If you run a root console inside the docker container, and wanna execute commands on the webserver behalf, be sure to use `sudo -E` command (with the `-E` flag) to preserve env variables from the current shell.
|
||||
> Otherwise Part-DB console might use the wrong configuration to execute commands.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
## User management commands
|
||||
|
||||
* `php bin/console partdb:users:list`: List all users of this Part-DB instance
|
||||
|
@ -64,4 +70,10 @@ docker exec --user=www-data partdb php bin/console cache:clear
|
|||
## Database commands
|
||||
|
||||
* `php bin/console doctrine:migrations:migrate`: Migrate the database to the latest version
|
||||
* `php bin/console doctrine:migrations:up-to-date`: Check if the database is up-to-date
|
||||
* `php bin/console doctrine:migrations:up-to-date`: Check if the database is up-to-date
|
||||
|
||||
## Attachment commands
|
||||
|
||||
* `php bin/console partdb:attachments:download`: Download all attachments, which are not already downloaded, to the
|
||||
local filesystem. This is useful to create local backups of the attachments, no matter what happens on the remote and
|
||||
also makes pictures thumbnails available for the frontend for them
|
|
@ -6,7 +6,7 @@ parent: Usage
|
|||
|
||||
# EDA / KiCad integration
|
||||
|
||||
Part-DB can function as central database for [EDA](https://en.wikipedia.org/wiki/Electronic_design_automation) or ECAD software used to design electronic schematics and PCBs.
|
||||
Part-DB can function as a central database for [EDA](https://en.wikipedia.org/wiki/Electronic_design_automation) or ECAD software used to design electronic schematics and PCBs.
|
||||
You can connect your EDA software and can view your available parts, with the data saved from Part-DB directly in your EDA software.
|
||||
Part-DB allows to configure additional metadata for the EDA, to associate symbols and footprints for use inside the EDA software, so the part becomes
|
||||
directly usable inside the EDA software.
|
||||
|
@ -20,12 +20,12 @@ This also allows to configure available and usable parts and their properties in
|
|||
> Part-DB uses the HTTP library feature of KiCad, which is experimental and not part of the stable KiCad 7 releases. If you want to use this feature, you need to install a KiCad nightly build (7.99 version). This feature will most likely also be part of KiCad 8.
|
||||
|
||||
Part-DB should be accessible from the PCs with KiCAD. The URL should be stable (so no dynamically changing IP).
|
||||
You require a user account in Part-DB, which has the permission to access Part-DB API and create API tokens. Every user can has its own account, or you setup a shared read-only account.
|
||||
You require a user account in Part-DB, which has permission to access Part-DB API and create API tokens. Every user can have its own account, or you set up a shared read-only account.
|
||||
|
||||
To connect KiCad with Part-DB do following steps:
|
||||
To connect KiCad with Part-DB do the following steps:
|
||||
|
||||
1. Create an API token on the user settings page for the KiCAD application and copy/save it, when it is shown. Currently KiCAD can only read Part-DB database, so a token with read only scope is enough.
|
||||
2. Add some EDA metadata to parts, categories or footprints. Only parts with useable info will show up in KiCad. See below for more info.
|
||||
1. Create an API token on the user settings page for the KiCAD application and copy/save it, when it is shown. Currently, KiCad can only read Part-DB database, so a token with a read-only scope is enough.
|
||||
2. Add some EDA metadata to parts, categories, or footprints. Only parts with usable info will show up in KiCad. See below for more info.
|
||||
3. Create a file `partd.kicad_httplib` (or similar, only the extension is important) with the following content:
|
||||
```
|
||||
{
|
||||
|
@ -44,36 +44,36 @@ To connect KiCad with Part-DB do following steps:
|
|||
```
|
||||
4. Replace the `root_url` with the URL of your Part-DB instance plus `/en/kicad-api/`. You can find the right value for this in the Part-DB user settings page under "API endpoints" in the "API tokens" panel.
|
||||
5. Replace the `token` field value with the token you have generated in step 1.
|
||||
6. Open KiCad and add this created file as library in the KiCad symbol table under (Preferences --> Manage Symbol Libraries)
|
||||
6. Open KiCad and add this created file as a library in the KiCad symbol table under (Preferences --> Manage Symbol Libraries)
|
||||
|
||||
If you then place a new part, the library dialog opens, and you should be able to see the categories and parts from Part-DB.
|
||||
|
||||
### How to associate footprints and symbols with parts
|
||||
|
||||
Part-DB dont save any concrete footprints or symbols for the part. Instead Part-DB just contains a reference string in the part metadata, which points to a symbol/footprint in KiCads local library.
|
||||
Part-DB doesn't save any concrete footprints or symbols for the part. Instead, Part-DB just contains a reference string in the part metadata, which points to a symbol/footprint in KiCad's local library.
|
||||
|
||||
You can define this on a per-part basis using the KiCad symbol and KiCad footprint field in the EDA tab of the part editor. Or you can define it at a category (symbol) or footprint level, to assign this value to all parts with this category and footprint.
|
||||
|
||||
For example to configure the values for an BC547 transistor you would put `Transistor_BJT:BC547` on the parts Kicad symbol to give it the right schematic symbol in EEschema and `Package_TO_SOT_THT:TO-92` to give it the right footprint in PcbNew.
|
||||
For example, to configure the values for a BC547 transistor you would put `Transistor_BJT:BC547` on the parts Kicad symbol to give it the right schematic symbol in EEschema and `Package_TO_SOT_THT:TO-92` to give it the right footprint in PcbNew.
|
||||
|
||||
If you type in a character, you will get an autocomplete list of all symbols and footprints available in the kicad standard library. You can also input your own value.
|
||||
If you type in a character, you will get an autocomplete list of all symbols and footprints available in the KiCad standard library. You can also input your own value.
|
||||
|
||||
### Parts and category visibility
|
||||
|
||||
Only parts and their categories, on which there is any kind of EDA metadata are defined show up in KiCad. So if you want to see parts in KiCad,
|
||||
you need to define at least a symbol, footprint, reference prefix or value on a part, category or footprint.
|
||||
you need to define at least a symbol, footprint, reference prefix, or value on a part, category or footprint.
|
||||
|
||||
You can use the "Force visibility" checkbox on a part or category to override this behavior and force parts to be visible or hidden in KiCad.
|
||||
|
||||
*Please note that KiCad caches the library categories. So if you change something, which would change the visibile categories in KiCad, you have to reload EEschema to see the changes.*
|
||||
*Please note that KiCad caches the library categories. So if you change something, which would change the visible categories in KiCad, you have to reload EEschema to see the changes.*
|
||||
|
||||
### Category depth in KiCad
|
||||
|
||||
For performance reasons, only the most top level categories of Part-DB are shown as categories in KiCad. All parts in the subcategories are shown in the top level category.
|
||||
For performance reasons, only the most top-level categories of Part-DB are shown as categories in KiCad. All parts in the subcategories are shown in the top-level category.
|
||||
|
||||
You can configure the depth of the categories shown in KiCad, via the `EDA_KICAD_CATEGORY_DEPTH` env option. The default value is 0, which meabs only the top level categories are shown.
|
||||
You can configure the depth of the categories shown in KiCad, via the `EDA_KICAD_CATEGORY_DEPTH` env option. The default value is 0, which means only the top-level categories are shown.
|
||||
To show more levels of categories, you can set this value to a higher number.
|
||||
|
||||
If you set this value to -1, all parts are shown inside a single category in KiCad, without any subcategories.
|
||||
|
||||
You can view the "real" category path of a part in the part details dialog in KiCad.
|
||||
You can view the "real" category path of a part in the part details dialog in KiCad.
|
||||
|
|
|
@ -18,22 +18,22 @@ Before you start creating data structures, you should configure Part-DB to your
|
|||
options.
|
||||
This is done either via changing the `.env.local` file in a direct installation or by changing the env variables in
|
||||
your `docker-compose.yaml` file.
|
||||
A list of possible configuration options, can be found [here]({% link configuration.md %}).
|
||||
A list of possible configuration options can be found [here]({% link configuration.md %}).
|
||||
|
||||
## Change password, Set up Two-Factor-Authentication & Customize User settings
|
||||
|
||||
If you have not already done, you should change your user password. You can do this in the user settings (available in
|
||||
the navigation bar drop down with the user symbol).
|
||||
If you have not already done so, you should change your user password. You can do this in the user settings (available in
|
||||
the navigation bar drop-down with the user symbol).
|
||||
|
||||

|
||||
|
||||
There you can also find the option, to set up Two-Factor Authentication methods like Google Authenticator. Using this is
|
||||
highly recommended (especially if you have admin permissions) to increase the security of your account. (Two-Factor
|
||||
Authentication even can be enforced for all members of a user group)
|
||||
highly recommended (especially if you have admin permissions) to increase the security of your account. (Two-factor authentication
|
||||
even can be enforced for all members of a user group)
|
||||
|
||||
In the user settings panel you can change account infos like your username, your first and last name (which will be
|
||||
shown alongside your username to identify you better), department information and your email address. The email address
|
||||
is used to send password reset mails, if your system is configured to use this.
|
||||
In the user settings panel, you can change account info like your username, your first and last name (which will be
|
||||
shown alongside your username to identify you better), department information, and your email address. The email address
|
||||
is used to send password reset mails if your system is configured to use this.
|
||||
|
||||

|
||||
|
||||
|
@ -46,7 +46,7 @@ used.
|
|||
|
||||
The banner which is shown on the homepage, can be customized/changed by changing the `config/banner.md` file with a text
|
||||
editor. You can use markdown and (safe) HTML here, to style and customize the banner.
|
||||
You can even use Latex style equations by wrapping the expressions into `$` (like `$E=mc^2$`, which is rendered inline:
|
||||
You can even use LaTeX-style equations by wrapping the expressions into `$` (like `$E=mc^2$`, which is rendered inline:
|
||||
$E=mc^2$) or `$$` (like `$$E=mc^2$$`) which will be rendered as a block, like so: $$E=mc^2$$
|
||||
|
||||
## Create groups, users and customize permissions
|
||||
|
@ -55,14 +55,14 @@ $E=mc^2$) or `$$` (like `$$E=mc^2$$`) which will be rendered as a block, like so
|
|||
|
||||
When logged in as administrator, you can open the users menu in the `Tools` section of the sidebar
|
||||
under `System -> Users`.
|
||||
At this page you can create new users, change their passwords and settings and change their permissions.
|
||||
For each user which should use Part-DB you should set up an own account, so that tracking of what user did what works
|
||||
On this page you can create new users, change their passwords and settings, and change their permissions.
|
||||
For each user who should use Part-DB you should set up their own account so that tracking of what user did works
|
||||
properly.
|
||||

|
||||
|
||||
You should check the permissions for every user and ensure that they are in the intended way, and no user has more
|
||||
permissions than he needs.
|
||||
For each capability you can choose between allow, forbid and inherit. In the last case, the permission is determined by
|
||||
For each capability, you can choose between allow, forbid, and inherit. In the last case, the permission is determined by
|
||||
the group a user has (if no group is chosen, it equals forbid)
|
||||
|
||||

|
||||
|
@ -75,35 +75,34 @@ to restrict the permissions.
|
|||
|
||||
### Groups
|
||||
|
||||
If you have many users which should share the same permissions, it is useful to define the permissions using user
|
||||
If you have many users who should share the same permissions, it is useful to define the permissions using user
|
||||
groups, which you can create and edit in the `System -> Groups` menu.
|
||||
|
||||
By default 3 groups are defined:
|
||||
By default, 3 groups are defined:
|
||||
|
||||
* `readonly` which users only have read permissions (like viewing, searching parts, attachments, etc.)
|
||||
* `users` which users also have rights to edit/delete/create elements
|
||||
* `admin` which users can do administrative operations (like creating new users, show global system log, etc.)
|
||||
* `admin` which users can do administrative operations (like creating new users, showing global system log, etc.)
|
||||
|
||||
Users only use the setting of a capability from a group, if the user has a group associated and the capability on the
|
||||
user is set to `inherit` (which is the default if creating a new user). You can override the permissions settings of a
|
||||
group per user by explicitly settings the permission at the user.
|
||||
group per user by explicitly setting the permission of the user.
|
||||
|
||||
Groups are organized as trees, meaning a group can have parent and child permissions and child groups can inherit
|
||||
permissions from their parents.
|
||||
To inherit the permissions from a parent group set the capability to inherit, otherwise set it explicitly to override
|
||||
To inherit the permissions from a parent group set the capability to inherit, otherwise, set it explicitly to override
|
||||
the parents' permission.
|
||||
|
||||
## Create Attachment types
|
||||
|
||||
Every attachment (that is a file associated with a part, data structure, etc.) must have an attachment type. They can
|
||||
be used to group attachments logically, like differentiating between datasheets, pictures and other documents.
|
||||
be used to group attachments logically, like differentiating between datasheets, pictures, and other documents.
|
||||
|
||||
You can create/edit attachment types in the tools sidebar under "Edit -> Attachment types":
|
||||
|
||||

|
||||
|
||||
Depending on your use case different entries here make sense. For part management the following (additional) entries
|
||||
maybe make sense:
|
||||
Depending on your use case different entries here make sense. For part management the following (additional) entries may make sense:
|
||||
|
||||
* Datasheets (restricted to pdfs, Allowed filetypes: `application/pdf`)
|
||||
* Pictures (for generic pictures of components, storage locations, etc., Allowed filetypes: `image/*`
|
||||
|
@ -111,34 +110,34 @@ maybe make sense:
|
|||
For every attachment type a list of allowed file types, which can be uploaded to an attachment with this attachment
|
||||
type, can be defined. You can either pass a list of allowed file extensions (e.g. `.pdf, .zip, .docx`) and/or a list
|
||||
of [Mime Types](https://en.wikipedia.org/wiki/Media_type) (e.g. `application/pdf, image/jpeg`) or a combination of both
|
||||
here. To allow all browser supported images, you can use `image/*` wildcard here.
|
||||
here. To allow all browser-supported images, you can use `image/*` wildcard here.
|
||||
|
||||
## (Optional) Create Currencies
|
||||
|
||||
If you want to save price information for parts in a currency different to your global currency (by default Euro), you
|
||||
If you want to save price information for parts in a currency different from your global currency (by default Euro), you
|
||||
have to define the additional currencies you want to use under `Edit -> Currencies`:
|
||||
|
||||

|
||||
|
||||
You create a new currency, name it however you want (it is recommended to use the official name of the currency) and
|
||||
select the currency ISO code from the list and save it. The currency symbol is determined automatically from chose ISO
|
||||
You create a new currency, name it however you want (it is recommended to use the official name of the currency),
|
||||
select the currency ISO code from the list, and save it. The currency symbol is determined automatically from the chosen ISO
|
||||
code.
|
||||
You can define an exchange rate in terms of your base currency (e.g. how many euros is one unit of your currency worth)
|
||||
to convert the currencies values in your preferred display currency automatically.
|
||||
to convert the currency values in your preferred display currency automatically.
|
||||
|
||||
## (Optional) Create Measurement Units
|
||||
|
||||
By default, Part-DB assumes that the parts in inventory can be counted by individual indivisible pieces, like LEDs in a
|
||||
box or books in a shelf.
|
||||
box or books on a shelf.
|
||||
However, if you want to manage things, that are divisible and the stock is described by a physical quantity, like
|
||||
length for cables, or volumina of a liquid, you have to define additional measurement units.
|
||||
length for cables, or volumes of a liquid, you have to define additional measurement units.
|
||||
|
||||
This is possible under `Edit -> Measurement Units`:
|
||||

|
||||
|
||||
You can give the measurement unit a name and an optional unit symbol (like `m` for meters) which is shown when
|
||||
quantities in this unit are displayed. The option `Use SI prefix` is useful for almost all physical quantities, as big
|
||||
and small numbers are automatically formatted with SI-prefixes (like 1.5kg instead 1500 grams).
|
||||
and small numbers are automatically formatted with SI prefixes (like 1.5kg instead 1500 grams).
|
||||
|
||||
The measurement unit can be selected for each part individually, by setting the option in the advanced tab of a part`s
|
||||
edit menu.
|
||||
|
@ -157,16 +156,16 @@ Every part has to be assigned to a category, so you should create at least one c
|
|||
## (Optional) Create Footprints
|
||||
|
||||
Footprints are used to describe the physical shape of a part, like a resistor or a capacitor.
|
||||
They can be used to group parts by their physical shape and to find parts with in the same package.
|
||||
They can be used to group parts by their physical shape and to find parts within the same package.
|
||||
|
||||
You can create/edit footprints in the tools sidebar under "Edit -> Footprints".
|
||||
|
||||
It is useful to create footprints for the most common packages, like SMD resistors, capacitors, etc. to make it easier
|
||||
to find parts with the same footprint.
|
||||
You should create these as a tree structure, so that you can group footprints by their type.
|
||||
You should create these as a tree structure so that you can group footprints by their type.
|
||||
See [Concepts]({% link concepts.md %}) for an example tree structure.
|
||||
|
||||
You can define attachments here which are associated with the footprint. The attachment set as preview image, will be
|
||||
You can define attachments here which are associated with the footprint. The attachment set as the preview image, will be
|
||||
used whenever a visual representation of the footprint is needed (e.g. in the part list).
|
||||
|
||||
For many common footprints, you can use the built-in footprints, which can be found in the "Builtin footprint image
|
||||
|
|
|
@ -7,7 +7,7 @@ parent: Usage
|
|||
|
||||
# Import & Export data
|
||||
|
||||
Part-DB offers the possibility to import existing data (parts, datastructures, etc.) from existing data sources into
|
||||
Part-DB offers the possibility to import existing data (parts, data structures, etc.) from existing data sources into
|
||||
Part-DB. Data can also be exported from Part-DB into various formats.
|
||||
|
||||
## Import
|
||||
|
@ -34,23 +34,23 @@ find in the "Tools" sidebar panel.
|
|||
> 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:
|
||||
You can upload the file that 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 (`;`).
|
||||
* **CSV delimiter**: If you upload a 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 (`,`) or 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.)
|
||||
* **Create unknown data structures**: If this is selected Part-DB will create new data structures (like categories,
|
||||
manufacturers, etc.) if no data structure(s) with the same name and path already exists. If this is not selected, only
|
||||
existing data structures will be used and if no matching data strucure is found, the imported parts field will be empty.
|
||||
* **Path delimiter**: Part-DB allows you to create/select nested data structures (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.
|
||||
|
@ -59,7 +59,7 @@ You can upload the file which should be imported here and choose various options
|
|||
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
|
||||
finished, you will see the results of the import in the lower half of the page. You can find a table with the imported
|
||||
parts (including links to them) there.
|
||||
|
||||
#### Fields description
|
||||
|
@ -83,14 +83,14 @@ leave them empty or do not include the column in your file.
|
|||
* **`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.
|
||||
* **`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 / quantity 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
|
||||
With the following fields, you can specify storage locations and amount/quantity in stock of the part. A PartLot will
|
||||
be created automatically from the data and assigned to the part. The following fields are helpers for an easy import of
|
||||
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:
|
||||
|
||||
|
@ -99,7 +99,7 @@ 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.
|
||||
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 these 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
|
||||
|
@ -125,31 +125,31 @@ give the user any additional information.
|
|||
|
||||
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 "
|
||||
If you select a certain data structure from your list, you can export it (and optionally all sub data structures) 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 "
|
||||
If you want to export all data structures 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
|
||||
* **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).
|
||||
data structures 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 languages. 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
|
||||
supports nested data structures and sub-data (like parameters, attachments, etc.) very well. However, it is not easy to
|
||||
work with in Excel or LibreOffice Calc and you may 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 use case as JSON and YAML.
|
||||
* **YAML** (Yet Another Markup Language): Very similar to JSON
|
||||
* **XML** (Extensible Markup Language): Good support with nested data structures. Similar use cases 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)
|
||||
* **Extended**: This will export all commonly used information about this data structure (like notes, options, etc.)
|
||||
* **Full**: This will export all available information about this data structure (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
|
||||
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.
|
||||
|
||||
|
@ -158,4 +158,4 @@ information, this can lead to very large export files.
|
|||
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.
|
||||
See the section about exporting data structures for more information about the export formats and levels.
|
|
@ -6,11 +6,11 @@ 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
|
||||
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.
|
||||
This way your Part-DB parts automatically get datasheet links, prices, parameters, and more, with just a few clicks.
|
||||
|
||||
## Usage
|
||||
|
||||
|
@ -45,13 +45,13 @@ part.
|
|||
|
||||
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 an 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,
|
||||
For this, it searches for an 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 the 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
|
||||
For example, if you 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.
|
||||
|
||||
|
@ -72,12 +72,12 @@ add the alternative names "Datasheet" and "Image" to the alternative names field
|
|||
|
||||
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
|
||||
The providers are just a driver that 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 an 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
|
||||
Also, there are limits on how many requests you can do per day or month, depending on the provider and your contract
|
||||
with them.
|
||||
|
||||
The following providers are currently available and shipped with Part-DB:
|
||||
|
@ -86,8 +86,7 @@ The following providers are currently available and shipped with Part-DB:
|
|||
|
||||
### Octopart
|
||||
|
||||
The Octopart provider uses the [Octopart / Nexar API](https://nexar.com/api) to search for parts and getting
|
||||
information.
|
||||
The Octopart provider uses the [Octopart / Nexar API](https://nexar.com/api) to search for parts and get information.
|
||||
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.
|
||||
|
@ -100,7 +99,7 @@ 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:
|
||||
The 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)
|
||||
|
@ -108,19 +107,19 @@ Following env configuration options are available:
|
|||
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_COUNTRY`: The country you want to get prices in if available (optional, 2 letter ISO-code,
|
||||
default: `DE`). To get the 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
|
||||
**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
|
||||
The Digi-Key provider uses the [Digi-Key API](https://developer.digikey.com/) to search for parts and get 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/).
|
||||
|
@ -128,7 +127,7 @@ You must create an organization there and create a "Production app". Most settin
|
|||
grant access to the "Product Information" API.
|
||||
You will get a Client ID and a Client Secret, which you have to put in the Part-DB env configuration (see below).
|
||||
|
||||
Following env configuration options are available:
|
||||
The 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)
|
||||
|
@ -138,7 +137,7 @@ Following env configuration options are available:
|
|||
|
||||
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
|
||||
go to 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 log in 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
|
||||
|
@ -146,13 +145,13 @@ 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
|
||||
The TME provider uses 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:
|
||||
The 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)
|
||||
|
@ -171,7 +170,7 @@ You have to create an account at Farnell and get an API key on the [Farnell API
|
|||
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:
|
||||
The 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
|
||||
|
@ -185,11 +184,11 @@ information from [Mouser](https://www.mouser.com/).
|
|||
You have to create an account at Mouser and register for an API key for the Search API on
|
||||
the [Mouser API page](https://www.mouser.de/api-home/).
|
||||
You will receive an API token, which you have to put in the Part-DB env configuration (see below):
|
||||
At the registration you choose a country, language and currency in which you want to get the results.
|
||||
At the registration you choose a country, language, and currency in which you want to get the results.
|
||||
|
||||
*Attention*: Currently (January 2024) the mouser API seems to be somewhat broken, in the way that it does not return any
|
||||
information about datasheets and part specifications. Therefore Part-DB can not retrieve them, even if they are shown
|
||||
at the mouser page. See [issue #503](https://github.com/Part-DB/Part-DB-server/issues/503) for more infos.
|
||||
at the mouser page. See [issue #503](https://github.com/Part-DB/Part-DB-server/issues/503) for more info.
|
||||
|
||||
Following env configuration options are available:
|
||||
|
||||
|
@ -200,6 +199,59 @@ Following env configuration options are available:
|
|||
* `PROVIDER_MOUSER_SEARCH_WITH_SIGNUP_LANGUAGE`: A bit of an obscure option. The original description of Mouser is: Used
|
||||
when searching for keywords in the language specified when you signed up for Search API.
|
||||
|
||||
### LCSC
|
||||
|
||||
[LCSC](https://www.lcsc.com/) is a Chinese distributor of electronic parts. It does not offer a public API, but the LCSC
|
||||
webshop uses an internal JSON based API to render the page. Part-DB can use this inofficial API to get part information
|
||||
from LCSC.
|
||||
|
||||
**Please note, that the use of this internal API is not intended or endorsed by LCS and it could break at any time. So use it at your own risk.**
|
||||
|
||||
An API key is not required, it is enough to enable the provider using the following env configuration options:
|
||||
|
||||
* `PROVIDER_LCSC_ENABLED`: Set this to `1` to enable the LCSC provider
|
||||
* `PROVIDER_LCSC_CURRENCY`: The currency you want to get prices in (see LCSC webshop for available currencies, default: `EUR`)
|
||||
|
||||
### OEMsecrets
|
||||
|
||||
The oemsecrets provider uses the [oemsecrets API](https://www.oemsecrets.com/) to search for parts and getting shopping
|
||||
information from them. Similar to octopart it aggregates offers from different distributors.
|
||||
|
||||
You can apply for a free API key on the [oemsecrets API page](https://www.oemsecrets.com/api/) and put the key you get
|
||||
in the Part-DB env configuration (see below).
|
||||
|
||||
The following env configuration options are available:
|
||||
|
||||
* `PROVIDER_OEMSECRETS_KEY`: The API key you got from oemsecrets (mandatory)
|
||||
* `PROVIDER_OEMSECRETS_COUNTRY_CODE`: The two-letter code of the country you want to get the prices for
|
||||
* `PROVIDER_OEMSECRETS_CURRENCY`: The currency you want to get prices in (optional, default: `EUR`)
|
||||
* `PROVIDER_OEMSECRETS_ZERO_PRICE`: If set to `1`, parts with a price of 0 will be included in the search results, otherwise
|
||||
they will be excluded (optional, default: `0`)
|
||||
* `PROVIDER_OEMSECRETS_SET_PARAM`: If set to `1`, the provider will try to extract parameters from the part description
|
||||
* `PROVIDER_OEMSECRETS_SORT_CRITERIA`: The criteria to sort the search results by. If set to 'C', it further sorts by
|
||||
completeness (prioritizing items with the most detailed information). If set to 'M', it further sorts by manufacturer name.
|
||||
If set to any other value, no sorting is performed.
|
||||
|
||||
### Reichelt
|
||||
|
||||
The reichelt provider uses webscraping from [reichelt.com](https://reichelt.com/) to get part information.
|
||||
This is not an official API and could break at any time. So use it at your own risk.
|
||||
|
||||
The following env configuration options are available:
|
||||
* `PROVIDER_REICHELT_ENABLED`: Set this to `1` to enable the Reichelt provider
|
||||
* `PROVIDER_REICHELT_CURRENCY`: The currency you want to get prices in. Only possible for countries which use Non-EUR (optional, default: `EUR`)
|
||||
* `PROVIDER_REICHELT_COUNTRY`: The country you want to get the prices for (optional, default: `DE`)
|
||||
* `PROVIDER_REICHELT_LANGUAGE`: The language you want to get the descriptions in (optional, default: `en`)
|
||||
* `PROVIDER_REICHELT_INCLUDE_VAT`: If set to `1`, the prices will be gross prices (including tax), otherwise net prices (optional, default: `1`)
|
||||
|
||||
### Pollin
|
||||
|
||||
The pollin provider uses webscraping from [pollin.de](https://www.pollin.de/) to get part information.
|
||||
This is not an official API and could break at any time. So use it at your own risk.
|
||||
|
||||
The following env configuration options are available:
|
||||
* `PROVIDER_POLLIN_ENABLED`: Set this to `1` to enable the Pollin provider
|
||||
|
||||
### Custom provider
|
||||
|
||||
To create a custom provider, you have to create a new class implementing the `InfoProviderInterface` interface. As long
|
||||
|
|
|
@ -93,7 +93,7 @@ all text and search fields in Part-DB.
|
|||
|
||||
### Currency symbols
|
||||
|
||||
Please not the following keybindings are bound to a specific keycode. The key character is not the same on all
|
||||
Please note, 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.
|
||||
|
||||
|
@ -108,7 +108,7 @@ For a German keyboard layout, replace ; with ö, and ' with ä.
|
|||
|
||||
### Others
|
||||
|
||||
Please not the following keybindings are bound to a specific keycode. The key character is not the same on all
|
||||
Please note 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.
|
||||
|
||||
|
@ -117,6 +117,6 @@ For a German keyboard layout, replace `[` with `0`, and `]` with `´`.
|
|||
| Key | Character |
|
||||
|--------------------------------|--------------------|
|
||||
| **Alt + [** (code 219) | © (Copyright char) |
|
||||
| **Alt + Shift + [** (code 219) | (Registered char) |
|
||||
| **Alt + Shift + [** (code 219) | ® (Registered char) |
|
||||
| **Alt + ]** (code 221) | ™ (Trademark char) |
|
||||
| **Alt + Shift + ]** (code 221) | (Degree char) |
|
||||
| **Alt + Shift + ]** (code 221) | ° (Degree char) |
|
||||
|
|
|
@ -7,12 +7,12 @@ parent: Usage
|
|||
# Labels
|
||||
|
||||
Part-DB support the generation and printing of labels for parts, part lots and storage locations.
|
||||
You can use the "Tools -> Label generator" menu entry to create labels, or click the label generation link on the part.
|
||||
You can use the "Tools -> Label generator" menu entry to create labels or click the label generation link on the part.
|
||||
|
||||
You can define label templates by creating Label profiles. This way you can create many similar looking labels with for
|
||||
You can define label templates by creating Label profiles. This way you can create many similar-looking labels with for
|
||||
many parts.
|
||||
|
||||
The content of the labels is defined by the templates content field. You can use the WYSIWYG editor to create and style
|
||||
The content of the labels is defined by the template's content field. You can use the WYSIWYG editor to create and style
|
||||
the content (or write HTML code).
|
||||
Using the "Label placeholder" menu in the editor, you can insert placeholders for the data of the parts.
|
||||
It will be replaced by the concrete data when the label is generated.
|
||||
|
@ -20,7 +20,7 @@ It will be replaced by the concrete data when the label is generated.
|
|||
## Label placeholders
|
||||
|
||||
A placeholder has the format `[[PLACEHOLDER]]` and will be filled with the concrete data by Part-DB.
|
||||
You can use the "Placeholders" dropdown in content editor, to automatically insert the placeholders.
|
||||
You can use the "Placeholders" dropdown in the content editor, to automatically insert the placeholders.
|
||||
|
||||
### Common
|
||||
|
||||
|
@ -89,15 +89,169 @@ If you select "Twig" in parser mode under advanced settings, you can input a twi
|
|||
source mode). You can use most of the twig tags and filters listed
|
||||
in [official documentation](https://twig.symfony.com/doc/3.x/).
|
||||
|
||||
The following variables are in injected into Twig and can be accessed using `{% raw %}{{ variable }}` (
|
||||
Twig allows you for much more complex and dynamic label generation. You can use loops, conditions, and functions to create
|
||||
the label content and you can access almost all data Part-DB offers. The label templates are evaluated in a special sandboxed environment,
|
||||
where only certain operations are allowed. Only read access to entities is allowed. However as it circumvents Part-DB normal permission system,
|
||||
the twig mode is only available to users with the "Twig mode" permission.
|
||||
|
||||
The following variables are in injected into Twig and can be accessed using `{% raw %}{{ variable }}{% endraw %}` (
|
||||
or `{% raw %}{{ variable.property }}{% endraw %}`):
|
||||
|
||||
| Variable name | Description |
|
||||
|--------------------------------------------|-------------------------------------------------------------------------------------|
|
||||
| `{% 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 |
|
||||
| Variable name | Description |
|
||||
|--------------------------------------------|--------------------------------------------------------------------------------------|
|
||||
| `{% 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 %}{{ last_page }}{% endraw %}` | The page number of the last element. Equals the number of all pages / element labels |
|
||||
| `{% raw %}{{ paper_width }}{% endraw %}` | The width of the label paper in mm |
|
||||
| `{% raw %}{{ paper_height }}{% endraw %}` | The height of the label paper in mm |
|
||||
|
||||
### Use the placeholders in twig mode
|
||||
|
||||
You can use the placeholders described above in the twig mode on `element` using the `{% raw %}{{ placeholder('PLACEHOLDER', element) }}{% endraw %}`
|
||||
function or the ``{{ "[[PLACEHOLDER]]"|placeholders(element) }}`` filter:
|
||||
|
||||
```twig
|
||||
{% raw %}
|
||||
{# The function can be used to get the a single placeholder value of an element, if the placeholder does not exist, null is returned #}
|
||||
{{ placeholder('[[NAME]]', element) }}
|
||||
|
||||
{# The filter can be used to replace all placeholders in a string with the values of the element #}
|
||||
{{ "[[NAME]]: [[DESCRIPTION]]"|placeholders(element) }}
|
||||
|
||||
{# Using the apply environment every placeholder in the apply block will be replaced automatically #}
|
||||
{% apply placeholders(element) %}
|
||||
[[NAME]]: [[DESCRIPTION]]
|
||||
{% endapply %}
|
||||
|
||||
{# If the block contains HTML use placeholders(element)|raw to prevent escaping of the HTML #}
|
||||
{% apply placeholders(element)|raw %}
|
||||
<b>[[NAME]]</b>: [[DESCRIPTION]]
|
||||
{% endapply %}
|
||||
|
||||
{% endraw %}
|
||||
```
|
||||
|
||||
### Important entity fields in twig mode
|
||||
|
||||
In twig mode you have access to many fields of the entity you are generating the label for and their associated entities.
|
||||
Following are some important fields of the entities listed. See the [SandboxedTwigFactory service](https://github.com/Part-DB/Part-DB-server/blob/master/src/Services/LabelSystem/SandboxedTwigFactory.php) for the full list of allowed class methods.
|
||||
|
||||
Please not that the field names might change in the future.
|
||||
|
||||
#### Part
|
||||
|
||||
| Field name | Description |
|
||||
|---------------------|-----------------------------------------------------------------------------------------------|
|
||||
| `id` | The internal ID of the part |
|
||||
| `name` | The name of the part |
|
||||
| `category` | The category of the part |
|
||||
| `manufacturer` | The manufacturer of the part |
|
||||
| `footprint` | The footprint of the part |
|
||||
| `mass` | The mass of the part |
|
||||
| `ManufacturerProductNumber` | The manufacturer product number of the part |
|
||||
| `tags` | The tags of the part |
|
||||
| `description` | The rich text (markdown) description of the part |
|
||||
| `comment` | The rich text (markdown) comment of the part |
|
||||
| `lastModified` | The datetime object when the part was last modified |
|
||||
| `creationDate` | The datetime object when the part was created |
|
||||
| `ipn` | The internal part number of the part |
|
||||
| `partUnit` | The unit of the part |
|
||||
| `amountSum` | The sum of the amount of all part lots of this part |
|
||||
| `amountUnknwon` | Bool: True if there is at least one part lot with unknown amount |
|
||||
| `partLots` | The part lots of the part |
|
||||
| `parameters` | The parameters of the part |
|
||||
| `orderdetails` | The order details of the part as array of Orderdetails |
|
||||
|
||||
#### Part lot
|
||||
|
||||
| Field name | Description |
|
||||
|---------------------|-----------------------------------------------------------------------------------------------|
|
||||
| `id` | The internal ID of the part lot |
|
||||
| `name` | The name of the part lot |
|
||||
| `comment` | The rich text (markdown) comment of the part lot |
|
||||
| `expirationDate` | The expiration date of the part lot (as Datetime object) |
|
||||
| `amount` | The amount of parts in this lot |
|
||||
| `storageLocation` | The storage location of this part lot |
|
||||
| `part` | The part of this part lot |
|
||||
| `needsRefill` | Bool: True if the part lot needs a refill |
|
||||
| `expired` | Bool: True if the part lot is expired |
|
||||
| `vendorBarcode` | The vendor barcode field of the lot |
|
||||
|
||||
#### Structural entities like categories, manufacturers, footprints, and storage locations
|
||||
|
||||
| Field name | Description |
|
||||
|---------------------|-----------------------------------------------------------------------------------------------|
|
||||
| `id` | The internal ID of the entity |
|
||||
| `name` | The name of the entity |
|
||||
| `comment` | The rich text (markdown) comment of the entity |
|
||||
| `parent` | The parent entity of the entity |
|
||||
| `children` | The children entities of the entity |
|
||||
| `lastModified` | The datetime object when the entity was last modified |
|
||||
| `creationDate` | The datetime object when the entity was created |
|
||||
| `level` | The level of the entity in the hierarchy |
|
||||
| `fullPath` | The full path of the entity (you can pass the delimiter as parameter) |
|
||||
| `pathArray` | The path of the entity as array of strings |
|
||||
|
||||
#### Orderdetails
|
||||
|
||||
| Field name | Description |
|
||||
|---------------------|-----------------------------------------------------------------------------------------------|
|
||||
| `id` | The internal ID of the order detail |
|
||||
| `part` | The part of the order detail |
|
||||
| `supplier` | The supplier/distributor of the order detail |
|
||||
| `obsolete` | Bool: True if the order detail is obsolete |
|
||||
| `pricedetails` | The price details of the order detail as array of Pricedetails |
|
||||
|
||||
#### Pricedetails
|
||||
|
||||
| Field name | Description |
|
||||
|---------------------|-----------------------------------------------------------------------------------------------|
|
||||
| `id` | The internal ID of the price detail |
|
||||
| `price` | The price of the price detail |
|
||||
| `currency` | The currency of the price detail |
|
||||
| `currencyIsoCode` | The ISO code of the used currency |
|
||||
| `pricePerUnit` | The price per unit of the price detail |
|
||||
| `priceRelatedQuantity` | The related quantity of the price detail |
|
||||
| `minDiscountQuantity` | The minimum discount quantity of the price detail |
|
||||
|
||||
#### User
|
||||
|
||||
| Field name | Description |
|
||||
|---------------------|-----------------------------------------------------------------------------------------------|
|
||||
| `id` | The internal ID of the user |
|
||||
| `username` | The username of the user |
|
||||
| `email` | The email of the user |
|
||||
| `fullName` | The full name of the user |
|
||||
| `lastName` | The last name of the user |
|
||||
| `firstName` | The first name of the user |
|
||||
| `department` | The department of the user |
|
||||
|
||||
|
||||
### Part-DB specific twig functions and filters
|
||||
|
||||
Part-DB offers some custom twig functions and filters, which can be used in the twig mode and ease the rendering of
|
||||
certain data:
|
||||
|
||||
#### Functions
|
||||
|
||||
| Function name | Description |
|
||||
|----------------------------------------------|-----------------------------------------------------------------------------------------------|
|
||||
| `placeholder(placeholder, element)` | Get the value of a placeholder of an element |
|
||||
| `entity_type(element)` | Get the type of an entity as string |
|
||||
| `entity_url(element, type)` | Get the URL to a specific entity type page (e.g. `info`, `edit`, etc.) |
|
||||
| `barcode_svg(content, type)` | Generate a barcode SVG from the content and type (e.g. `QRCODE`, `CODE128` etc.). A svg string is returned, which you need to data uri encode to inline it. |
|
||||
|
||||
### Filters
|
||||
|
||||
| Filter name | Description |
|
||||
|----------------------------------------------|-----------------------------------------------------------------------------------------------|
|
||||
| `format_bytes` | Format a byte count to a human readable string |
|
||||
| `format_money(price, currency)` | Format a price to a human readable string with the currency |
|
||||
| `format_amount(amount, unit)` | Format an amount to a human readable string with the unit object |
|
||||
| `format_si(value, unit_str)` | Format a value using SI prefixes and the given unit string |
|
||||
| `placeholders(element)` | Replace all placeholders in a string with the values of the element |
|
||||
|
||||
## Use custom fonts for PDF labels
|
||||
|
||||
|
@ -124,12 +278,12 @@ the label generator settings:
|
|||
|
||||
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.
|
||||
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 beautiful Chinese, Japanese
|
||||
For example, you can use [Noto CJK](https://github.com/notofonts/noto-cjk) for more beautiful Chinese, Japanese,
|
||||
and Korean characters.
|
|
@ -8,35 +8,35 @@ parent: Usage
|
|||
|
||||
Following you can find miscellaneous tips and tricks for using Part-DB.
|
||||
|
||||
## Create datastructures directly from part edit page
|
||||
## Create data structures directly from part edit page
|
||||
|
||||
Instead of first creating a category, manufacturer, footprint, etc. and then creating the part, you can create the
|
||||
datastructures directly from the part edit page: Just type the name of the datastructure you want to create into the
|
||||
select field on the part edit page and press "Create new ...". The new datastructure will be created, when you save
|
||||
Instead of first creating a category, manufacturer, footprint, etc., and then creating the part, you can create the
|
||||
data structures directly from the part edit page: Just type the name of the data structure you want to create into the
|
||||
select field on the part edit page and press "Create new ...". The new data structure will be created when you save
|
||||
the part changes.
|
||||
|
||||
You can create also create nested datastructures this way. For example, if you want to create a new category "AVRs",
|
||||
You can create also create nested data structures this way. For example, if you want to create a new category "AVRs",
|
||||
as a subcategory of "MCUs", you can just type "MCUs->AVRs" into the category select field and press "Create new".
|
||||
The new category "AVRs" will be created as a subcategory of "MCUs". If the category "MCUs" does not exist, it will
|
||||
be created too.
|
||||
|
||||
## Builtin footprint images
|
||||
## Built-in footprint images
|
||||
|
||||
Part-DB includes several builtin images for common footprints. You can use these images in your footprint
|
||||
datastructures,
|
||||
by creating an attachment on the datastructure and selecting it as preview image.
|
||||
Part-DB includes several built-in images for common footprints. You can use these images in your footprint
|
||||
data structures,
|
||||
by creating an attachment on the data structure and selecting it as the preview image.
|
||||
Type the name of the footprint image you want to use into the URL field of the attachment and select it from the
|
||||
dropdown menu. You can find a gallery of all builtin footprint images and their names in the "Builtin footprint image
|
||||
gallery",
|
||||
which you can find in the "Tools" menu (you maybe need to give your user the permission to access this tool).
|
||||
which you can find in the "Tools" menu (you may need to give your user the permission to access this tool).
|
||||
|
||||
## Parametric search
|
||||
|
||||
In the "parameters" tab of the filter panel on parts list page, you can define constraints, which parameter values
|
||||
have to fulfill. This allows you to search for parts with specific parameters (or parameter ranges), for example you
|
||||
In the "parameters" tab of the filter panel on parts list page, you can define constraints, and which parameter values
|
||||
have to fulfill. This allows you to search for parts with specific parameters (or parameter ranges), for example, you
|
||||
can search for all parts with a voltage rating of greater than 5 V.
|
||||
|
||||
## View own users permissions
|
||||
## View own user's permissions
|
||||
|
||||
If you want to see which permissions your user has, you can find a list of the permissions in the "Permissions" panel
|
||||
on the user info page.
|
||||
|
@ -49,10 +49,8 @@ part).
|
|||
You can find a list of supported features in the [KaTeX documentation](https://katex.org/docs/supported.html).
|
||||
|
||||
To input a LaTeX equation, you have to wrap it in a pair of dollar signs (`$`). Single dollar signs mark inline
|
||||
equations,
|
||||
double dollar signs mark displayed equations (which will be its own line and centered). For example, the following
|
||||
equation
|
||||
will be rendered as an inline equation:
|
||||
equations, double dollar signs mark displayed equations (which will be their own line and centered).
|
||||
For example, the following equation will be rendered as an inline equation:
|
||||
|
||||
```
|
||||
$E=mc^2$
|
||||
|
@ -77,16 +75,16 @@ 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
|
||||
This comment will be written to changelog and can be viewed later.
|
||||
If you want to force 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
|
||||
For maker spaces 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.
|
||||
the user as "owner" of a part lot. This way, only he is allowed to add or remove parts from this lot.
|
||||
|
||||
## Update notifications
|
||||
|
||||
|
|
|
@ -235,4 +235,14 @@ EOD;
|
|||
{
|
||||
$this->warnIf(true, "Migration not needed for SQLite. Skipping...");
|
||||
}
|
||||
|
||||
public function postgreSQLUp(Schema $schema): void
|
||||
{
|
||||
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||
}
|
||||
|
||||
public function postgreSQLDown(Schema $schema): void
|
||||
{
|
||||
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -380,4 +380,14 @@ final class Version20190902140506 extends AbstractMultiPlatformMigration
|
|||
{
|
||||
$this->warnIf(true, "Migration not needed for SQLite. Skipping...");
|
||||
}
|
||||
|
||||
public function postgreSQLUp(Schema $schema): void
|
||||
{
|
||||
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||
}
|
||||
|
||||
public function postgreSQLDown(Schema $schema): void
|
||||
{
|
||||
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -88,4 +88,14 @@ final class Version20190913141126 extends AbstractMultiPlatformMigration
|
|||
{
|
||||
$this->warnIf(true, "Migration not needed for SQLite. Skipping...");
|
||||
}
|
||||
|
||||
public function postgreSQLUp(Schema $schema): void
|
||||
{
|
||||
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||
}
|
||||
|
||||
public function postgreSQLDown(Schema $schema): void
|
||||
{
|
||||
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -179,4 +179,14 @@ final class Version20190924113252 extends AbstractMultiPlatformMigration
|
|||
{
|
||||
$this->warnIf(true, "Migration not needed for SQLite. Skipping...");
|
||||
}
|
||||
|
||||
public function postgreSQLUp(Schema $schema): void
|
||||
{
|
||||
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||
}
|
||||
|
||||
public function postgreSQLDown(Schema $schema): void
|
||||
{
|
||||
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,4 +65,14 @@ final class Version20191214153125 extends AbstractMultiPlatformMigration
|
|||
{
|
||||
$this->warnIf(true, "Migration not needed for SQLite. Skipping...");
|
||||
}
|
||||
|
||||
public function postgreSQLUp(Schema $schema): void
|
||||
{
|
||||
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||
}
|
||||
|
||||
public function postgreSQLDown(Schema $schema): void
|
||||
{
|
||||
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,4 +68,14 @@ final class Version20200126191823 extends AbstractMultiPlatformMigration
|
|||
{
|
||||
$this->warnIf(true, "Migration not needed for SQLite. Skipping...");
|
||||
}
|
||||
|
||||
public function postgreSQLUp(Schema $schema): void
|
||||
{
|
||||
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||
}
|
||||
|
||||
public function postgreSQLDown(Schema $schema): void
|
||||
{
|
||||
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,4 +56,14 @@ final class Version20200311204104 extends AbstractMultiPlatformMigration
|
|||
{
|
||||
$this->warnIf(true, "Migration not needed for SQLite. Skipping...");
|
||||
}
|
||||
|
||||
public function postgreSQLUp(Schema $schema): void
|
||||
{
|
||||
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||
}
|
||||
|
||||
public function postgreSQLDown(Schema $schema): void
|
||||
{
|
||||
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,4 +42,14 @@ final class Version20200409130946 extends AbstractMultiPlatformMigration
|
|||
{
|
||||
$this->warnIf(true, "Migration not needed for SQLite. Skipping...");
|
||||
}
|
||||
|
||||
public function postgreSQLUp(Schema $schema): void
|
||||
{
|
||||
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||
}
|
||||
|
||||
public function postgreSQLDown(Schema $schema): void
|
||||
{
|
||||
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -163,4 +163,14 @@ EOD;
|
|||
$this->addSql('DROP TABLE u2f_keys');
|
||||
$this->addSql('DROP TABLE "users"');
|
||||
}
|
||||
|
||||
public function postgreSQLUp(Schema $schema): void
|
||||
{
|
||||
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||
}
|
||||
|
||||
public function postgreSQLDown(Schema $schema): void
|
||||
{
|
||||
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -535,4 +535,14 @@ final class Version20220925162725 extends AbstractMultiPlatformMigration
|
|||
$this->addSql('CREATE INDEX IDX_1483A5E938248176 ON "users" (currency_id)');
|
||||
$this->addSql('CREATE INDEX IDX_1483A5E96DEDCEC2 ON "users" (id_preview_attachement)');
|
||||
}
|
||||
|
||||
public function postgreSQLUp(Schema $schema): void
|
||||
{
|
||||
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||
}
|
||||
|
||||
public function postgreSQLDown(Schema $schema): void
|
||||
{
|
||||
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,4 +47,14 @@ final class Version20221003212851 extends AbstractMultiPlatformMigration
|
|||
{
|
||||
$this->addSql('DROP TABLE webauthn_keys');
|
||||
}
|
||||
|
||||
public function postgreSQLUp(Schema $schema): void
|
||||
{
|
||||
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||
}
|
||||
|
||||
public function postgreSQLDown(Schema $schema): void
|
||||
{
|
||||
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,24 +4,20 @@ declare(strict_types=1);
|
|||
|
||||
namespace DoctrineMigrations;
|
||||
|
||||
use App\Entity\UserSystem\PermissionData;
|
||||
use App\Migration\AbstractMultiPlatformMigration;
|
||||
use App\Security\Interfaces\HasPermissionsInterface;
|
||||
use App\Migration\WithPermPresetsTrait;
|
||||
use App\Services\UserSystem\PermissionPresetsHelper;
|
||||
use Doctrine\DBAL\Connection;
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20221114193325 extends AbstractMultiPlatformMigration implements ContainerAwareInterface
|
||||
{
|
||||
private ?ContainerInterface $container = null;
|
||||
private ?PermissionPresetsHelper $permission_presets_helper = null;
|
||||
use WithPermPresetsTrait;
|
||||
|
||||
public function __construct(Connection $connection, LoggerInterface $logger)
|
||||
{
|
||||
|
@ -33,34 +29,6 @@ final class Version20221114193325 extends AbstractMultiPlatformMigration impleme
|
|||
return 'Update the permission system to the new system. Please note that all permissions will be reset!';
|
||||
}
|
||||
|
||||
private function getJSONPermDataFromPreset(string $preset): string
|
||||
{
|
||||
if ($this->permission_presets_helper === null) {
|
||||
throw new \RuntimeException('PermissionPresetsHelper not set! There seems to be some issue with the dependency injection!');
|
||||
}
|
||||
|
||||
//Create a virtual user on which we can apply the preset
|
||||
$user = new class implements HasPermissionsInterface {
|
||||
|
||||
public PermissionData $perm_data;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->perm_data = new PermissionData();
|
||||
}
|
||||
|
||||
public function getPermissions(): PermissionData
|
||||
{
|
||||
return $this->perm_data;
|
||||
}
|
||||
};
|
||||
|
||||
//Apply the preset to the virtual user
|
||||
$this->permission_presets_helper->applyPreset($user, $preset);
|
||||
|
||||
//And return the json data
|
||||
return json_encode($user->getPermissions());
|
||||
}
|
||||
|
||||
private function addDataMigrationAndWarning(): void
|
||||
{
|
||||
|
@ -164,11 +132,15 @@ final class Version20221114193325 extends AbstractMultiPlatformMigration impleme
|
|||
$this->addSql('CREATE INDEX user_idx_username ON "users" (name)');
|
||||
}
|
||||
|
||||
public function setContainer(ContainerInterface $container = null)
|
||||
|
||||
|
||||
public function postgreSQLUp(Schema $schema): void
|
||||
{
|
||||
if ($container) {
|
||||
$this->container = $container;
|
||||
$this->permission_presets_helper = $container->get(PermissionPresetsHelper::class);
|
||||
}
|
||||
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||
}
|
||||
|
||||
public function postgreSQLDown(Schema $schema): void
|
||||
{
|
||||
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,4 +55,14 @@ final class Version20221204004815 extends AbstractMultiPlatformMigration
|
|||
$this->addSql('CREATE INDEX parts_idx_datet_name_last_id_needs ON "parts" (datetime_added, name, last_modified, id, needs_review)');
|
||||
$this->addSql('CREATE INDEX parts_idx_name ON "parts" (name)');
|
||||
}
|
||||
|
||||
public function postgreSQLUp(Schema $schema): void
|
||||
{
|
||||
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||
}
|
||||
|
||||
public function postgreSQLDown(Schema $schema): void
|
||||
{
|
||||
$this->warnIf(true, "Migration not needed for Postgres. Skipping...");
|
||||
}
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue