mirror of
https://github.com/Part-DB/Part-DB-server.git
synced 2026-07-04 16:31:34 +00:00
Compare commits
8 commits
5b86d6f652
...
a82d515034
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a82d515034 | ||
|
|
6a30b41688 | ||
|
|
ec05f9d8ab | ||
|
|
1c3dfa26bb | ||
|
|
766665f9e5 | ||
|
|
29db029d69 | ||
|
|
146e85f84c | ||
|
|
c17cf5e83c |
31 changed files with 9172 additions and 1245 deletions
2
VERSION
2
VERSION
|
|
@ -1 +1 @@
|
|||
2.9.1
|
||||
2.10.0
|
||||
|
|
|
|||
68
composer.lock
generated
68
composer.lock
generated
|
|
@ -13083,7 +13083,7 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/polyfill-ctype",
|
||||
"version": "v1.34.0",
|
||||
"version": "v1.36.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-ctype.git",
|
||||
|
|
@ -13142,7 +13142,7 @@
|
|||
"portable"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.34.0"
|
||||
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.36.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
|
@ -13166,7 +13166,7 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/polyfill-intl-grapheme",
|
||||
"version": "v1.34.0",
|
||||
"version": "v1.36.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-intl-grapheme.git",
|
||||
|
|
@ -13224,7 +13224,7 @@
|
|||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.34.0"
|
||||
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.36.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
|
@ -13248,7 +13248,7 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/polyfill-intl-icu",
|
||||
"version": "v1.34.0",
|
||||
"version": "v1.36.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-intl-icu.git",
|
||||
|
|
@ -13312,7 +13312,7 @@
|
|||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-intl-icu/tree/v1.34.0"
|
||||
"source": "https://github.com/symfony/polyfill-intl-icu/tree/v1.36.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
|
@ -13336,7 +13336,7 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/polyfill-intl-idn",
|
||||
"version": "v1.34.0",
|
||||
"version": "v1.36.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-intl-idn.git",
|
||||
|
|
@ -13399,7 +13399,7 @@
|
|||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.34.0"
|
||||
"source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.36.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
|
@ -13423,7 +13423,7 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/polyfill-intl-normalizer",
|
||||
"version": "v1.34.0",
|
||||
"version": "v1.36.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
|
||||
|
|
@ -13484,7 +13484,7 @@
|
|||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.34.0"
|
||||
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.36.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
|
@ -13508,7 +13508,7 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php83",
|
||||
"version": "v1.34.0",
|
||||
"version": "v1.36.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php83.git",
|
||||
|
|
@ -13564,7 +13564,7 @@
|
|||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-php83/tree/v1.34.0"
|
||||
"source": "https://github.com/symfony/polyfill-php83/tree/v1.36.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
|
@ -13588,7 +13588,7 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php84",
|
||||
"version": "v1.34.0",
|
||||
"version": "v1.36.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php84.git",
|
||||
|
|
@ -13644,7 +13644,7 @@
|
|||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-php84/tree/v1.34.0"
|
||||
"source": "https://github.com/symfony/polyfill-php84/tree/v1.36.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
|
@ -13668,7 +13668,7 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php85",
|
||||
"version": "v1.34.0",
|
||||
"version": "v1.36.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php85.git",
|
||||
|
|
@ -13724,7 +13724,7 @@
|
|||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-php85/tree/v1.34.0"
|
||||
"source": "https://github.com/symfony/polyfill-php85/tree/v1.36.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
|
@ -13748,7 +13748,7 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/polyfill-uuid",
|
||||
"version": "v1.34.0",
|
||||
"version": "v1.36.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-uuid.git",
|
||||
|
|
@ -13807,7 +13807,7 @@
|
|||
"uuid"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-uuid/tree/v1.34.0"
|
||||
"source": "https://github.com/symfony/polyfill-uuid/tree/v1.36.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
|
@ -18469,11 +18469,11 @@
|
|||
},
|
||||
{
|
||||
"name": "phpstan/phpstan",
|
||||
"version": "2.1.47",
|
||||
"version": "2.1.48",
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/79015445d8bd79e62b29140f12e5bfced1dcca65",
|
||||
"reference": "79015445d8bd79e62b29140f12e5bfced1dcca65",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/231397213efb7c0a066ee024b5c3c87f2d3adfa0",
|
||||
"reference": "231397213efb7c0a066ee024b5c3c87f2d3adfa0",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -18518,7 +18518,7 @@
|
|||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2026-04-13T15:49:08+00:00"
|
||||
"time": "2026-04-15T20:24:19+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan-doctrine",
|
||||
|
|
@ -19244,12 +19244,12 @@
|
|||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Roave/SecurityAdvisories.git",
|
||||
"reference": "b0b156ed9d5d2eb313c33f92af3dbc886ba4688a"
|
||||
"reference": "bb550b5adb0d4d74c4f6857c6b3b3638c022e90b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/b0b156ed9d5d2eb313c33f92af3dbc886ba4688a",
|
||||
"reference": "b0b156ed9d5d2eb313c33f92af3dbc886ba4688a",
|
||||
"url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/bb550b5adb0d4d74c4f6857c6b3b3638c022e90b",
|
||||
"reference": "bb550b5adb0d4d74c4f6857c6b3b3638c022e90b",
|
||||
"shasum": ""
|
||||
},
|
||||
"conflict": {
|
||||
|
|
@ -19379,7 +19379,7 @@
|
|||
"codingms/modules": "<4.3.11|>=5,<5.7.4|>=6,<6.4.2|>=7,<7.5.5",
|
||||
"commerceteam/commerce": ">=0.9.6,<0.9.9",
|
||||
"components/jquery": ">=1.0.3,<3.5",
|
||||
"composer/composer": "<1.10.27|>=2,<2.2.26|>=2.3,<2.9.3",
|
||||
"composer/composer": "<2.2.27|>=2.3,<2.9.6",
|
||||
"concrete5/concrete5": "<9.4.8",
|
||||
"concrete5/core": "<8.5.8|>=9,<9.1",
|
||||
"contao-components/mediaelement": ">=2.14.2,<2.21.1",
|
||||
|
|
@ -19396,7 +19396,7 @@
|
|||
"cpsit/typo3-mailqueue": "<0.4.5|>=0.5,<0.5.2",
|
||||
"craftcms/aws-s3": ">=2.0.2,<=2.2.4",
|
||||
"craftcms/azure-blob": ">=2.0.0.0-beta1,<=2.1",
|
||||
"craftcms/cms": "<=4.17.7|>=5,<=5.9.13",
|
||||
"craftcms/cms": "<=4.17.8|>=5,<5.9.15",
|
||||
"craftcms/commerce": ">=4,<4.11|>=5,<5.6",
|
||||
"craftcms/composer": ">=4.0.0.0-RC1-dev,<=4.10|>=5.0.0.0-RC1-dev,<=5.5.1",
|
||||
"craftcms/craft": ">=3.5,<=4.16.17|>=5.0.0.0-RC1-dev,<=5.8.21",
|
||||
|
|
@ -19664,7 +19664,7 @@
|
|||
"kelvinmo/simplexrd": "<3.1.1",
|
||||
"kevinpapst/kimai2": "<1.16.7",
|
||||
"khodakhah/nodcms": "<=3",
|
||||
"kimai/kimai": "<=2.50",
|
||||
"kimai/kimai": "<2.53",
|
||||
"kitodo/presentation": "<3.2.3|>=3.3,<3.3.4",
|
||||
"klaviyo/magento2-extension": ">=1,<3",
|
||||
"knplabs/knp-snappy": "<=1.4.2",
|
||||
|
|
@ -19805,8 +19805,8 @@
|
|||
"october/backend": "<1.1.2",
|
||||
"october/cms": "<1.0.469|==1.0.469|==1.0.471|==1.1.1",
|
||||
"october/october": "<3.7.5",
|
||||
"october/rain": "<1.0.472|>=1.1,<1.1.2",
|
||||
"october/system": "<=3.7.12|>=4,<=4.0.11",
|
||||
"october/rain": "<=3.7.13|>=4,<=4.1.9",
|
||||
"october/system": "<=3.7.13|>=4,<=4.1.9",
|
||||
"oliverklee/phpunit": "<3.5.15",
|
||||
"omeka/omeka-s": "<4.0.3",
|
||||
"onelogin/php-saml": "<2.21.1|>=3,<3.8.1|>=4,<4.3.1",
|
||||
|
|
@ -19885,7 +19885,7 @@
|
|||
"pixelfed/pixelfed": "<0.12.5",
|
||||
"plotly/plotly.js": "<2.25.2",
|
||||
"pocketmine/bedrock-protocol": "<8.0.2",
|
||||
"pocketmine/pocketmine-mp": "<5.41.1",
|
||||
"pocketmine/pocketmine-mp": "<5.42.1",
|
||||
"pocketmine/raklib": ">=0.14,<0.14.6|>=0.15,<0.15.1",
|
||||
"pressbooks/pressbooks": "<5.18",
|
||||
"prestashop/autoupgrade": ">=4,<4.10.1",
|
||||
|
|
@ -19939,6 +19939,7 @@
|
|||
"rudloff/rtmpdump-bin": "<=2.3.1",
|
||||
"s-cart/core": "<=9.0.5",
|
||||
"s-cart/s-cart": "<6.9",
|
||||
"s9y/serendipity": "<2.6",
|
||||
"sabberworm/php-css-parser": ">=1,<1.0.1|>=2,<2.0.1|>=3,<3.0.1|>=4,<4.0.1|>=5,<5.0.9|>=5.1,<5.1.3|>=5.2,<5.2.1|>=6,<6.0.2|>=7,<7.0.4|>=8,<8.0.1|>=8.1,<8.1.1|>=8.2,<8.2.1|>=8.3,<8.3.1",
|
||||
"sabre/dav": ">=1.6,<1.7.11|>=1.8,<1.8.9",
|
||||
"saloonphp/saloon": "<4",
|
||||
|
|
@ -20168,6 +20169,7 @@
|
|||
"webcoast/deferred-image-processing": "<1.0.2",
|
||||
"webklex/laravel-imap": "<5.3",
|
||||
"webklex/php-imap": "<5.3",
|
||||
"webonyx/graphql-php": "<=15.31.4",
|
||||
"webpa/webpa": "<3.1.2",
|
||||
"webreinvent/vaahcms": "<=2.3.1",
|
||||
"wikibase/wikibase": "<=1.39.3",
|
||||
|
|
@ -20187,7 +20189,7 @@
|
|||
"wpcloud/wp-stateless": "<3.2",
|
||||
"wpglobus/wpglobus": "<=1.9.6",
|
||||
"wpmetabox/meta-box": "<5.11.2",
|
||||
"wwbn/avideo": "<=26",
|
||||
"wwbn/avideo": "<=29",
|
||||
"xataface/xataface": "<3",
|
||||
"xpressengine/xpressengine": "<3.0.15",
|
||||
"yab/quarx": "<2.4.5",
|
||||
|
|
@ -20287,7 +20289,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-04-13T18:30:45+00:00"
|
||||
"time": "2026-04-15T20:21:07+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/cli-parser",
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ doctrine:
|
|||
natsort: App\Doctrine\Functions\Natsort
|
||||
array_position: App\Doctrine\Functions\ArrayPosition
|
||||
ilike: App\Doctrine\Functions\ILike
|
||||
si_value_sort: App\Doctrine\Functions\SiValueSort
|
||||
|
||||
when@test:
|
||||
doctrine:
|
||||
|
|
|
|||
|
|
@ -59,6 +59,9 @@ parameters:
|
|||
- '#expects .*PartParameter, .*AbstractParameter given.#'
|
||||
- '#Part::getParameters\(\) should return .*AbstractParameter#'
|
||||
|
||||
# Fix some weird issue with how covariance with collections is solved
|
||||
- '#Method App\\Entity\\Base\\AbstractStructuralDBElement::getParameters\(\) should return Doctrine\\Common\\Collections\\Collection<int, App\\Entity\\Parameters\\AbstractParameter> but returns#'
|
||||
|
||||
# Ignore doctrine type mapping mismatch
|
||||
- '#Property .* type mapping mismatch: property can contain .* but database expects .*#'
|
||||
|
||||
|
|
@ -70,3 +73,6 @@ parameters:
|
|||
|
||||
- message: '#Access to an undefined property Brick\\Schema\\Interfaces\\#'
|
||||
path: src/Services/InfoProviderSystem/Providers/GenericWebProvider.php
|
||||
|
||||
-
|
||||
identifier: nullCoalesce.property
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# Generated on Mon Mar 9 04:23:25 UTC 2026
|
||||
# Generated on Mon Apr 13 05:19:27 UTC 2026
|
||||
# This file contains all footprints available in the offical KiCAD library
|
||||
Audio_Module:Reverb_BTDR-1H
|
||||
Audio_Module:Reverb_BTDR-1V
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# Generated on Mon Mar 9 04:24:12 UTC 2026
|
||||
# Generated on Mon Apr 13 05:20:06 UTC 2026
|
||||
# This file contains all symbols available in the offical KiCAD library
|
||||
4xxx:14528
|
||||
4xxx:14529
|
||||
|
|
@ -899,6 +899,7 @@ Amplifier_Buffer:BUF634AxD
|
|||
Amplifier_Buffer:BUF634AxDDA
|
||||
Amplifier_Buffer:BUF634AxDRB
|
||||
Amplifier_Buffer:BUF634U
|
||||
Amplifier_Buffer:BUF802
|
||||
Amplifier_Buffer:EL2001CN
|
||||
Amplifier_Buffer:LH0002H
|
||||
Amplifier_Buffer:LM6321H
|
||||
|
|
@ -1667,7 +1668,6 @@ Analog_ADC:CA3300
|
|||
Analog_ADC:HX711
|
||||
Analog_ADC:ICL7106CPL
|
||||
Analog_ADC:ICL7107CPL
|
||||
Analog_ADC:INA234AxYBJ
|
||||
Analog_ADC:LTC1406CGN
|
||||
Analog_ADC:LTC1406IGN
|
||||
Analog_ADC:LTC1594CS
|
||||
|
|
@ -2198,6 +2198,7 @@ Audio:WM8731SEDS
|
|||
Audio:YM2149
|
||||
Audio:YM2612
|
||||
Audio:YM3438
|
||||
Auxiliary_Items:Generic_Outline
|
||||
Auxiliary_Items:Jumper_Shunt
|
||||
Auxiliary_Items:MountingScrew
|
||||
Battery_Management:ADP5063
|
||||
|
|
@ -2254,6 +2255,11 @@ Battery_Management:BQ76200PW
|
|||
Battery_Management:BQ76920PW
|
||||
Battery_Management:BQ76930DBT
|
||||
Battery_Management:BQ76940DBT
|
||||
Battery_Management:BQ7695201PFBR
|
||||
Battery_Management:BQ7695202PFBR
|
||||
Battery_Management:BQ7695203PFBR
|
||||
Battery_Management:BQ7695204PFBR
|
||||
Battery_Management:BQ76952PFBR
|
||||
Battery_Management:BQ78350DBT
|
||||
Battery_Management:BQ78350DBT-R1
|
||||
Battery_Management:CN3063
|
||||
|
|
@ -2763,6 +2769,8 @@ Connector:DIN41612_02x32_AC
|
|||
Connector:DIN41612_02x32_AE
|
||||
Connector:DIN41612_02x32_ZB
|
||||
Connector:DIN41612_03x32_C_Split
|
||||
Connector:DP_Sink
|
||||
Connector:DP_Source
|
||||
Connector:DVI-D_Dual_Link
|
||||
Connector:DVI-I_Dual_Link
|
||||
Connector:ExpressCard
|
||||
|
|
@ -2901,6 +2909,7 @@ Connector:TestPoint_Alt
|
|||
Connector:TestPoint_Flag
|
||||
Connector:TestPoint_Probe
|
||||
Connector:TestPoint_Small
|
||||
Connector:TestPoint_Square
|
||||
Connector:UEXT_Host
|
||||
Connector:UEXT_Slave
|
||||
Connector:USB3_A
|
||||
|
|
@ -7772,6 +7781,7 @@ FPGA_Lattice:ICE40HX1K-TQ144
|
|||
FPGA_Lattice:ICE40HX4K-BG121
|
||||
FPGA_Lattice:ICE40HX4K-TQ144
|
||||
FPGA_Lattice:ICE40HX8K-BG121
|
||||
FPGA_Lattice:ICE40LP384-SG32
|
||||
FPGA_Lattice:ICE40UL1K-SWG16
|
||||
FPGA_Lattice:ICE40UP5K-SG48ITR
|
||||
FPGA_Lattice:ICE5LP1K-SG48
|
||||
|
|
@ -15731,6 +15741,7 @@ Power_Management:RT9742AGJ5F
|
|||
Power_Management:RT9742ANGJ5F
|
||||
Power_Management:RT9742BGJ5F
|
||||
Power_Management:RT9742BNGJ5F
|
||||
Power_Management:RT9742SNGV
|
||||
Power_Management:SN6505ADBV
|
||||
Power_Management:SN6505BDBV
|
||||
Power_Management:SN6507DGQ
|
||||
|
|
@ -18692,6 +18703,7 @@ Regulator_Linear:TPS7A0530PDBZ
|
|||
Regulator_Linear:TPS7A0531PDBV
|
||||
Regulator_Linear:TPS7A0533PDBV
|
||||
Regulator_Linear:TPS7A0533PDBZ
|
||||
Regulator_Linear:TPS7A20xxxDBV
|
||||
Regulator_Linear:TPS7A20xxxDQN
|
||||
Regulator_Linear:TPS7A3301RGW
|
||||
Regulator_Linear:TPS7A39
|
||||
|
|
@ -20301,7 +20313,6 @@ Sensor:BME280
|
|||
Sensor:BME680
|
||||
Sensor:CHT11
|
||||
Sensor:DHT11
|
||||
Sensor:INA260
|
||||
Sensor:LTC2990
|
||||
Sensor:MAX30102
|
||||
Sensor:Nuclear-Radiation_Detector
|
||||
|
|
@ -20588,9 +20599,12 @@ Sensor_Energy:INA219BxD
|
|||
Sensor_Energy:INA219BxDCN
|
||||
Sensor_Energy:INA226
|
||||
Sensor_Energy:INA228
|
||||
Sensor_Energy:INA229
|
||||
Sensor_Energy:INA233
|
||||
Sensor_Energy:INA234AxYBJ
|
||||
Sensor_Energy:INA237
|
||||
Sensor_Energy:INA238
|
||||
Sensor_Energy:INA260
|
||||
Sensor_Energy:LTC4151xMS
|
||||
Sensor_Energy:MCP39F521
|
||||
Sensor_Energy:PAC1931x-xJ6CX
|
||||
|
|
@ -20872,6 +20886,7 @@ Sensor_Proximity:BPR-105
|
|||
Sensor_Proximity:BPR-105F
|
||||
Sensor_Proximity:BPR-205
|
||||
Sensor_Proximity:CNY70
|
||||
Sensor_Proximity:FDC1004DGS
|
||||
Sensor_Proximity:GP2S700HCP
|
||||
Sensor_Proximity:ITR1201SR10AR
|
||||
Sensor_Proximity:ITR8307
|
||||
|
|
@ -21791,6 +21806,7 @@ Transistor_BJT:Q_NPN_Darlington_ECBC
|
|||
Transistor_BJT:Q_NPN_EBC
|
||||
Transistor_BJT:Q_NPN_ECB
|
||||
Transistor_BJT:Q_NPN_ECBC
|
||||
Transistor_BJT:Q_PNP_ACAB
|
||||
Transistor_BJT:Q_PNP_BCE
|
||||
Transistor_BJT:Q_PNP_BCEC
|
||||
Transistor_BJT:Q_PNP_BEC
|
||||
|
|
|
|||
|
|
@ -69,10 +69,13 @@ class ProjectController extends AbstractController
|
|||
return $table->getResponse();
|
||||
}
|
||||
|
||||
$number_of_builds = max(1, $request->query->getInt('n', 1));
|
||||
|
||||
return $this->render('projects/info/info.html.twig', [
|
||||
'buildHelper' => $buildHelper,
|
||||
'datatable' => $table,
|
||||
'project' => $project,
|
||||
'number_of_builds' => $number_of_builds,
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ use App\DataTables\Filters\PartFilter;
|
|||
use App\DataTables\Filters\PartSearchFilter;
|
||||
use App\DataTables\Helpers\ColumnSortHelper;
|
||||
use App\DataTables\Helpers\PartDataTableHelper;
|
||||
use App\Doctrine\Functions\SiValueSort;
|
||||
use App\Doctrine\Helpers\FieldHelper;
|
||||
use App\Entity\Parts\ManufacturingStatus;
|
||||
use App\Entity\Parts\Part;
|
||||
|
|
@ -118,6 +119,18 @@ final class PartsDataTable implements DataTableTypeInterface
|
|||
'render' => fn($value, Part $context) => $this->partDataTableHelper->renderName($context),
|
||||
'orderField' => 'NATSORT(part.name)'
|
||||
])
|
||||
->add('si_value', TextColumn::class, [
|
||||
'label' => $this->translator->trans('part.table.si_value'),
|
||||
'render' => function ($value, Part $context): string {
|
||||
$siValue = SiValueSort::sqliteSiValue($context->getName());
|
||||
if ($siValue !== null) {
|
||||
//Output it as scientific number with a big E
|
||||
return htmlspecialchars(sprintf('%G', $siValue));
|
||||
}
|
||||
return '';
|
||||
},
|
||||
'orderField' => 'SI_VALUE_SORT(part.name)',
|
||||
])
|
||||
->add('id', TextColumn::class, [
|
||||
'label' => $this->translator->trans('part.table.id'),
|
||||
])
|
||||
|
|
@ -484,6 +497,19 @@ final class PartsDataTable implements DataTableTypeInterface
|
|||
//$builder->addGroupBy('_bulkImportJob');
|
||||
}
|
||||
|
||||
//When sorting by SI value, add NATSORT as a secondary sort so that parts without
|
||||
//an SI-prefixed value fall back to natural string ordering seamlessly.
|
||||
$orderByParts = $builder->getDQLPart('orderBy');
|
||||
foreach ($orderByParts as $orderBy) {
|
||||
foreach ($orderBy->getParts() as $part) {
|
||||
if (str_contains($part, 'SI_VALUE_SORT')) {
|
||||
$direction = str_contains($part, 'DESC') ? 'DESC' : 'ASC';
|
||||
$builder->addOrderBy('NATSORT(part.name)', $direction);
|
||||
break 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $builder;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,12 +29,15 @@ use App\DataTables\Column\LocaleDateTimeColumn;
|
|||
use App\DataTables\Column\MarkdownColumn;
|
||||
use App\DataTables\Helpers\PartDataTableHelper;
|
||||
use App\Doctrine\Helpers\FieldHelper;
|
||||
use App\Entity\Parts\Part;
|
||||
use App\Entity\Parts\ManufacturingStatus;
|
||||
use App\Entity\Parts\Part;
|
||||
use App\Entity\ProjectSystem\ProjectBOMEntry;
|
||||
use App\Services\ElementTypeNameGenerator;
|
||||
use App\Services\EntityURLGenerator;
|
||||
use App\Services\Formatters\AmountFormatter;
|
||||
use App\Services\Formatters\MoneyFormatter;
|
||||
use App\Services\ProjectSystem\ProjectBuildHelper;
|
||||
use Brick\Math\RoundingMode;
|
||||
use Doctrine\ORM\AbstractQuery;
|
||||
use Doctrine\ORM\Query;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
|
|
@ -50,7 +53,9 @@ class ProjectBomEntriesDataTable implements DataTableTypeInterface
|
|||
protected EntityURLGenerator $entityURLGenerator,
|
||||
protected TranslatorInterface $translator,
|
||||
protected AmountFormatter $amountFormatter,
|
||||
protected PartDataTableHelper $partDataTableHelper
|
||||
protected PartDataTableHelper $partDataTableHelper,
|
||||
protected ProjectBuildHelper $projectBuildHelper,
|
||||
protected MoneyFormatter $moneyFormatter,
|
||||
) {
|
||||
}
|
||||
|
||||
|
|
@ -202,6 +207,27 @@ class ProjectBomEntriesDataTable implements DataTableTypeInterface
|
|||
return '';
|
||||
}
|
||||
])
|
||||
->add('price', TextColumn::class, [
|
||||
'label' => 'project.bom.price',
|
||||
'visible' => false,
|
||||
'render' => function ($value, ProjectBOMEntry $context) {
|
||||
$price = $this->projectBuildHelper->getEntryUnitPrice($context);
|
||||
return $this->moneyFormatter->format($price->toScale(2, RoundingMode::UP)->toFloat(), null, 2, true);
|
||||
},
|
||||
])
|
||||
->add('ext_price', TextColumn::class, [
|
||||
'label' => 'project.bom.ext_price',
|
||||
'visible' => false,
|
||||
'render' => function ($value, ProjectBOMEntry $context) {
|
||||
$price = $this->projectBuildHelper->getEntryUnitPrice($context);
|
||||
return $this->moneyFormatter->format(
|
||||
$price->multipliedBy($context->getQuantity())->toScale(2, RoundingMode::UP)->toFloat(),
|
||||
null,
|
||||
2,
|
||||
true
|
||||
);
|
||||
},
|
||||
])
|
||||
|
||||
->add('addedDate', LocaleDateTimeColumn::class, [
|
||||
'label' => $this->translator->trans('part.table.addedDate'),
|
||||
|
|
|
|||
196
src/Doctrine/Functions/SiValueSort.php
Normal file
196
src/Doctrine/Functions/SiValueSort.php
Normal file
|
|
@ -0,0 +1,196 @@
|
|||
<?php
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Doctrine\Functions;
|
||||
|
||||
use Doctrine\DBAL\Platforms\AbstractMySQLPlatform;
|
||||
use Doctrine\DBAL\Platforms\PostgreSQLPlatform;
|
||||
use Doctrine\DBAL\Platforms\SQLitePlatform;
|
||||
use Doctrine\ORM\Query\AST\Functions\FunctionNode;
|
||||
use Doctrine\ORM\Query\AST\Node;
|
||||
use Doctrine\ORM\Query\Parser;
|
||||
use Doctrine\ORM\Query\SqlWalker;
|
||||
use Doctrine\ORM\Query\TokenType;
|
||||
|
||||
/**
|
||||
* Custom DQL function that extracts the first numeric value with an optional SI prefix
|
||||
* from a string and returns the scaled numeric value for sorting.
|
||||
*
|
||||
* Usage: SI_VALUE_SORT(part.name)
|
||||
*
|
||||
* This enables sorting parts by their physical value. For example, capacitors
|
||||
* named "100nF", "1uF", "10pF" will be sorted by actual value: 10pF < 100nF < 1uF.
|
||||
*
|
||||
* Supported SI prefixes: p (pico, 1e-12), n (nano, 1e-9), u/µ (micro, 1e-6),
|
||||
* m (milli, 1e-3), k/K (kilo, 1e3), M (mega, 1e6), G (giga, 1e9), T (tera, 1e12).
|
||||
*
|
||||
* Only matches numbers at the very beginning of the string (ignoring leading whitespace).
|
||||
* Names like "Crystal 20MHz" will NOT match since the number is not at the start.
|
||||
* Names without a recognizable numeric+prefix pattern return NULL and sort last.
|
||||
*/
|
||||
class SiValueSort extends FunctionNode
|
||||
{
|
||||
private ?Node $field = null;
|
||||
|
||||
/**
|
||||
* SI prefix multipliers. Used by the SQLite PHP callback.
|
||||
*/
|
||||
private const SI_MULTIPLIERS = [
|
||||
'p' => 1e-12,
|
||||
'n' => 1e-9,
|
||||
'u' => 1e-6,
|
||||
'µ' => 1e-6,
|
||||
'm' => 1e-3,
|
||||
'k' => 1e3,
|
||||
'K' => 1e3,
|
||||
'M' => 1e6,
|
||||
'G' => 1e9,
|
||||
'T' => 1e12,
|
||||
];
|
||||
|
||||
public function parse(Parser $parser): void
|
||||
{
|
||||
$parser->match(TokenType::T_IDENTIFIER);
|
||||
$parser->match(TokenType::T_OPEN_PARENTHESIS);
|
||||
|
||||
$this->field = $parser->ArithmeticExpression();
|
||||
|
||||
$parser->match(TokenType::T_CLOSE_PARENTHESIS);
|
||||
}
|
||||
|
||||
public function getSql(SqlWalker $sqlWalker): string
|
||||
{
|
||||
assert($this->field !== null, 'Field is not set');
|
||||
|
||||
$platform = $sqlWalker->getConnection()->getDatabasePlatform();
|
||||
$rawField = $this->field->dispatch($sqlWalker);
|
||||
|
||||
// Normalize comma decimal separator to dot for SQL platforms (European locale support)
|
||||
$fieldSql = "REPLACE({$rawField}, ',', '.')";
|
||||
|
||||
if ($platform instanceof PostgreSQLPlatform) {
|
||||
return $this->getPostgreSQLSql($fieldSql);
|
||||
}
|
||||
|
||||
if ($platform instanceof AbstractMySQLPlatform) {
|
||||
return $this->getMySQLSql($fieldSql);
|
||||
}
|
||||
|
||||
// SQLite: comma normalization is handled in the PHP callback
|
||||
$fieldSql = $rawField;
|
||||
|
||||
if ($platform instanceof SQLitePlatform) {
|
||||
return "SI_VALUE({$fieldSql})";
|
||||
}
|
||||
|
||||
// Fallback: return NULL (no SI sorting available)
|
||||
return 'NULL';
|
||||
}
|
||||
|
||||
/**
|
||||
* PostgreSQL implementation using substring() with POSIX regex.
|
||||
*/
|
||||
private function getPostgreSQLSql(string $field): string
|
||||
{
|
||||
// Extract the numeric part using POSIX regex, anchored at start (with optional leading whitespace)
|
||||
$numericPart = "CAST(substring({$field} FROM '^\\s*(\\d+\\.?\\d*)\\s*[pnuµmkKMGT]?') AS DOUBLE PRECISION)";
|
||||
|
||||
// Extract the SI prefix character
|
||||
$prefixPart = "substring({$field} FROM '^\\s*\\d+\\.?\\d*\\s*([pnuµmkKMGT])')";
|
||||
|
||||
return $this->buildCaseExpression($numericPart, $prefixPart);
|
||||
}
|
||||
|
||||
/**
|
||||
* MySQL/MariaDB implementation using REGEXP_SUBSTR.
|
||||
*/
|
||||
private function getMySQLSql(string $field): string
|
||||
{
|
||||
// Extract the numeric part, anchored at start (with optional leading whitespace)
|
||||
$numericPart = "CAST(REGEXP_SUBSTR({$field}, '^[[:space:]]*[0-9]+\\.?[0-9]*') AS DECIMAL(30,15))";
|
||||
|
||||
// Extract the prefix: get the full number+prefix match anchored at start, then take the last char
|
||||
$fullMatch = "REGEXP_SUBSTR({$field}, '^[[:space:]]*[0-9]+\\.?[0-9]*[[:space:]]*[pnuµmkKMGT]')";
|
||||
$prefixPart = "RIGHT({$fullMatch}, 1)";
|
||||
|
||||
return $this->buildCaseExpression($numericPart, $prefixPart);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a CASE expression that maps an SI prefix character to a multiplier
|
||||
* and multiplies it with the numeric value.
|
||||
*
|
||||
* @param string $numericExpr SQL expression that evaluates to the numeric part
|
||||
* @param string $prefixExpr SQL expression that evaluates to the SI prefix character
|
||||
* @return string SQL CASE expression
|
||||
*/
|
||||
private function buildCaseExpression(string $numericExpr, string $prefixExpr): string
|
||||
{
|
||||
return "(CASE" .
|
||||
" WHEN {$numericExpr} IS NULL THEN NULL" .
|
||||
" WHEN {$prefixExpr} = 'p' THEN {$numericExpr} * 1e-12" .
|
||||
" WHEN {$prefixExpr} = 'n' THEN {$numericExpr} * 1e-9" .
|
||||
" WHEN {$prefixExpr} = 'u' THEN {$numericExpr} * 1e-6" .
|
||||
" WHEN {$prefixExpr} = 'µ' THEN {$numericExpr} * 1e-6" .
|
||||
" WHEN {$prefixExpr} = 'm' THEN {$numericExpr} * 1e-3" .
|
||||
" WHEN {$prefixExpr} = 'k' THEN {$numericExpr} * 1e3" .
|
||||
" WHEN {$prefixExpr} = 'K' THEN {$numericExpr} * 1e3" .
|
||||
" WHEN {$prefixExpr} = 'M' THEN {$numericExpr} * 1e6" .
|
||||
" WHEN {$prefixExpr} = 'G' THEN {$numericExpr} * 1e9" .
|
||||
" WHEN {$prefixExpr} = 'T' THEN {$numericExpr} * 1e12" .
|
||||
" ELSE {$numericExpr} * 1" .
|
||||
" END)";
|
||||
}
|
||||
|
||||
/**
|
||||
* PHP callback for SQLite's SI_VALUE function.
|
||||
* Extracts the first numeric value with an optional SI prefix and returns the scaled value.
|
||||
*
|
||||
* @param string|null $value The input string
|
||||
* @return float|null The scaled numeric value, or null if no number found
|
||||
*/
|
||||
public static function sqliteSiValue(?string $value): ?float
|
||||
{
|
||||
if ($value === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Normalize comma decimal separator to dot (European locale support)
|
||||
$value = str_replace(',', '.', $value);
|
||||
|
||||
// Match a number at the very start (allowing leading whitespace), optionally followed by an SI prefix
|
||||
if (!preg_match('/^\s*(\d+\.?\d*)\s*([pnuµmkKMGT])?/u', $value, $matches)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$number = (float) $matches[1];
|
||||
$prefix = $matches[2] ?? '';
|
||||
|
||||
if ($prefix === '') {
|
||||
return $number;
|
||||
}
|
||||
|
||||
$multiplier = self::SI_MULTIPLIERS[$prefix] ?? 1.0; //@phpstan-ignore-line - fallback to 1.0 if prefix is not recognized (should not happen due to regex)
|
||||
|
||||
return $number * $multiplier;
|
||||
}
|
||||
}
|
||||
|
|
@ -23,6 +23,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Doctrine\Middleware;
|
||||
|
||||
use App\Doctrine\Functions\SiValueSort;
|
||||
use App\Exceptions\InvalidRegexException;
|
||||
use Doctrine\DBAL\Driver\Connection;
|
||||
use Doctrine\DBAL\Driver\Middleware\AbstractDriverMiddleware;
|
||||
|
|
@ -51,6 +52,9 @@ class SQLiteRegexExtensionMiddlewareDriver extends AbstractDriverMiddleware
|
|||
|
||||
//Create a new collation for natural sorting
|
||||
$native_connection->sqliteCreateCollation('NATURAL_CMP', strnatcmp(...));
|
||||
|
||||
//Create a function for SI prefix value sorting
|
||||
$native_connection->sqliteCreateFunction('SI_VALUE', SiValueSort::sqliteSiValue(...), 1, \PDO::SQLITE_DETERMINISTIC);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,16 +25,22 @@ namespace App\Services\ProjectSystem;
|
|||
use App\Entity\Parts\Part;
|
||||
use App\Entity\ProjectSystem\Project;
|
||||
use App\Entity\ProjectSystem\ProjectBOMEntry;
|
||||
use App\Entity\PriceInformations\Currency;
|
||||
use App\Helpers\Projects\ProjectBuildRequest;
|
||||
use App\Services\Parts\PartLotWithdrawAddHelper;
|
||||
use App\Services\Parts\PricedetailHelper;
|
||||
use Brick\Math\BigDecimal;
|
||||
use Brick\Math\RoundingMode;
|
||||
|
||||
/**
|
||||
* @see \App\Tests\Services\ProjectSystem\ProjectBuildHelperTest
|
||||
*/
|
||||
final readonly class ProjectBuildHelper
|
||||
{
|
||||
public function __construct(private PartLotWithdrawAddHelper $withdraw_add_helper)
|
||||
{
|
||||
public function __construct(
|
||||
private PartLotWithdrawAddHelper $withdraw_add_helper,
|
||||
private PricedetailHelper $pricedetailHelper,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -168,4 +174,81 @@ final readonly class ProjectBuildHelper
|
|||
$this->withdraw_add_helper->add($buildRequest->getBuildsPartLot(), $buildRequest->getNumberOfBuilds(), $message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the total price to build the given project N times, taking bulk pricing into account.
|
||||
* Returns null if no BOM entry has any pricing information.
|
||||
*/
|
||||
public function calculateTotalBuildPrice(Project $project, int $number_of_builds = 1, ?Currency $currency = null): ?BigDecimal
|
||||
{
|
||||
$total = BigDecimal::zero();
|
||||
$has_price = false;
|
||||
|
||||
foreach ($project->getBomEntries() as $entry) {
|
||||
$unit_price = $this->getBomEntryUnitPrice($entry, $number_of_builds, $currency);
|
||||
if ($unit_price === null) {
|
||||
continue;
|
||||
}
|
||||
$has_price = true;
|
||||
$total = $total->plus($unit_price->multipliedBy($entry->getQuantity())->multipliedBy($number_of_builds));
|
||||
}
|
||||
|
||||
return $has_price ? $total : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the price to build one unit of the given project when ordering for N builds in total.
|
||||
* Returns null if no BOM entry has any pricing information.
|
||||
*/
|
||||
public function calculateUnitBuildPrice(Project $project, int $number_of_builds = 1, ?Currency $currency = null): ?BigDecimal
|
||||
{
|
||||
$total = $this->calculateTotalBuildPrice($project, $number_of_builds, $currency);
|
||||
if ($total === null) {
|
||||
return null;
|
||||
}
|
||||
return $total->dividedBy($number_of_builds, 10, RoundingMode::HALF_UP);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the total build price rounded up to 2 decimal places, ready for display.
|
||||
*/
|
||||
public function roundedTotalBuildPrice(Project $project, int $number_of_builds = 1, ?Currency $currency = null): ?BigDecimal
|
||||
{
|
||||
return $this->calculateTotalBuildPrice($project, $number_of_builds, $currency)
|
||||
?->toScale(2, RoundingMode::UP);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the unit build price rounded up to 2 decimal places, ready for display.
|
||||
*/
|
||||
public function roundedUnitBuildPrice(Project $project, int $number_of_builds = 1, ?Currency $currency = null): ?BigDecimal
|
||||
{
|
||||
return $this->calculateUnitBuildPrice($project, $number_of_builds, $currency)
|
||||
?->toScale(2, RoundingMode::UP);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the effective unit price for a single piece of the given BOM entry,
|
||||
* taking bulk pricing and minimum order amounts into account for N builds.
|
||||
* Returns BigDecimal::zero() when no pricing data is available.
|
||||
*/
|
||||
public function getEntryUnitPrice(ProjectBOMEntry $entry, int $number_of_builds = 1, ?Currency $currency = null): BigDecimal
|
||||
{
|
||||
return $this->getBomEntryUnitPrice($entry, $number_of_builds, $currency) ?? BigDecimal::zero();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the effective unit price for a single piece of the given BOM entry,
|
||||
* taking bulk pricing into account for N builds.
|
||||
*/
|
||||
private function getBomEntryUnitPrice(ProjectBOMEntry $entry, int $number_of_builds, ?Currency $currency): ?BigDecimal
|
||||
{
|
||||
if ($entry->getPart() instanceof Part) {
|
||||
$total_qty = $entry->getQuantity() * $number_of_builds;
|
||||
$min_order = $this->pricedetailHelper->getMinOrderAmount($entry->getPart());
|
||||
$effective_qty = ($min_order !== null) ? max($total_qty, $min_order) : $total_qty;
|
||||
return $this->pricedetailHelper->calculateAvgPrice($entry->getPart(), $effective_qty, $currency);
|
||||
}
|
||||
return $entry->getPrice();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,6 +52,8 @@ enum PartTableColumns : string implements TranslatableInterface
|
|||
case TAGS = "tags";
|
||||
case ATTACHMENTS = "attachments";
|
||||
|
||||
case SI_VALUE = "si_value";
|
||||
|
||||
case EDA_REFERENCE = "eda_reference";
|
||||
|
||||
case EDA_VALUE = "eda_value";
|
||||
|
|
|
|||
|
|
@ -55,6 +55,32 @@
|
|||
</span>
|
||||
</h6>
|
||||
</div>
|
||||
{% set n = number_of_builds ?? 1 %}
|
||||
{% set total_build_price = buildHelper.roundedTotalBuildPrice(project, n, app.user.currency ?? null) %}
|
||||
{% set unit_build_price = buildHelper.roundedUnitBuildPrice(project, n, app.user.currency ?? null) %}
|
||||
{% if total_build_price is not null %}
|
||||
<div class="mt-1">
|
||||
<h6>
|
||||
<span class="badge badge-primary bg-success">
|
||||
<i class="fa-solid fa-money-bill-wave fa-fw"></i>
|
||||
{% trans %}project.info.total_build_price{% endtrans %}:
|
||||
{{ total_build_price | format_money(app.user.currency ?? null, 2) }}
|
||||
{% if n > 1 and unit_build_price is not null %}
|
||||
<span class="ms-1">
|
||||
({% trans %}project.info.per_unit_price{% endtrans %}: {{ unit_build_price | format_money(app.user.currency ?? null, 2) }})
|
||||
</span>
|
||||
{% endif %}
|
||||
</span>
|
||||
</h6>
|
||||
</div>
|
||||
{% endif %}
|
||||
<form method="get" action="{{ path('project_info', {'id': project.id}) }}" class="mt-2">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="input-group-text">{% trans %}project.builds.number_of_builds{% endtrans %}</span>
|
||||
<input type="number" min="1" class="form-control" name="n" required value="{{ n }}">
|
||||
<button class="btn btn-outline-secondary" type="submit">{% trans %}project.build.btn_build{% endtrans %}</button>
|
||||
</div>
|
||||
</form>
|
||||
{% if project.children is not empty %}
|
||||
<div class="mt-1">
|
||||
<h6>
|
||||
|
|
@ -69,9 +95,9 @@
|
|||
</div>
|
||||
|
||||
{% if project.comment is not empty %}
|
||||
<p>
|
||||
<h5>{% trans %}comment.label{% endtrans %}:</h5>
|
||||
{{ project.comment|format_markdown }}
|
||||
</p>
|
||||
<div class="col-12 mt-2">
|
||||
<h5>{% trans %}comment.label{% endtrans %}:</h5>
|
||||
{{ project.comment|format_markdown }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
193
tests/Doctrine/Functions/SiValueSortTest.php
Normal file
193
tests/Doctrine/Functions/SiValueSortTest.php
Normal file
|
|
@ -0,0 +1,193 @@
|
|||
<?php
|
||||
/*
|
||||
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
|
||||
*
|
||||
* Copyright (C) 2019 - 2026 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/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Doctrine\Functions;
|
||||
|
||||
use App\Doctrine\Functions\SiValueSort;
|
||||
use Doctrine\DBAL\Platforms\MySQLPlatform;
|
||||
use Doctrine\DBAL\Platforms\PostgreSQLPlatform;
|
||||
use Doctrine\DBAL\Platforms\SQLitePlatform;
|
||||
|
||||
final class SiValueSortTest extends AbstractDoctrineFunctionTestCase
|
||||
{
|
||||
public function testPostgreSQLGeneratesCaseExpression(): void
|
||||
{
|
||||
$function = new SiValueSort('SI_VALUE_SORT');
|
||||
$this->setObjectProperty($function, 'field', $this->createNode('part_name'));
|
||||
|
||||
$sql = $function->getSql($this->createSqlWalker(new PostgreSQLPlatform()));
|
||||
|
||||
$this->assertStringContainsString('CASE', $sql);
|
||||
$this->assertStringContainsString("REPLACE(part_name, ',', '.')", $sql);
|
||||
$this->assertStringContainsString('1e-12', $sql);
|
||||
$this->assertStringContainsString('1e-9', $sql);
|
||||
$this->assertStringContainsString('1e-6', $sql);
|
||||
$this->assertStringContainsString('1e-3', $sql);
|
||||
$this->assertStringContainsString('1e3', $sql);
|
||||
$this->assertStringContainsString('1e6', $sql);
|
||||
$this->assertStringContainsString('1e9', $sql);
|
||||
$this->assertStringContainsString('1e12', $sql);
|
||||
}
|
||||
|
||||
public function testMySQLGeneratesCaseExpression(): void
|
||||
{
|
||||
$function = new SiValueSort('SI_VALUE_SORT');
|
||||
$this->setObjectProperty($function, 'field', $this->createNode('part_name'));
|
||||
|
||||
$sql = $function->getSql($this->createSqlWalker(new MySQLPlatform()));
|
||||
|
||||
$this->assertStringContainsString('CASE', $sql);
|
||||
$this->assertStringContainsString("REPLACE(part_name, ',', '.')", $sql);
|
||||
$this->assertStringContainsString('1e-12', $sql);
|
||||
$this->assertStringContainsString('1e6', $sql);
|
||||
}
|
||||
|
||||
public function testSQLiteUsesSiValueFunction(): void
|
||||
{
|
||||
$function = new SiValueSort('SI_VALUE_SORT');
|
||||
$this->setObjectProperty($function, 'field', $this->createNode('part_name'));
|
||||
|
||||
$sql = $function->getSql($this->createSqlWalker(new SQLitePlatform()));
|
||||
|
||||
$this->assertSame('SI_VALUE(part_name)', $sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider sqliteSiValueProvider
|
||||
*/
|
||||
public function testSqliteSiValue(?string $input, ?float $expected): void
|
||||
{
|
||||
$result = SiValueSort::sqliteSiValue($input);
|
||||
|
||||
if ($expected === null) {
|
||||
$this->assertNull($result);
|
||||
} else {
|
||||
$this->assertEqualsWithDelta($expected, $result, $expected * 1e-9);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return iterable<string, array{?string, ?float}>
|
||||
*/
|
||||
public static function sqliteSiValueProvider(): iterable
|
||||
{
|
||||
// Basic SI prefix values
|
||||
yield 'pico' => ['10pF', 10e-12];
|
||||
yield 'nano' => ['100nF', 100e-9];
|
||||
yield 'micro_u' => ['1uF', 1e-6];
|
||||
yield 'micro_µ' => ['1µF', 1e-6];
|
||||
yield 'milli' => ['4.7mH', 4.7e-3];
|
||||
yield 'kilo_lower' => ['4.7k', 4.7e3];
|
||||
yield 'kilo_upper' => ['4.7K', 4.7e3];
|
||||
yield 'mega' => ['1M', 1e6];
|
||||
yield 'giga' => ['2.2G', 2.2e9];
|
||||
yield 'tera' => ['1T', 1e12];
|
||||
|
||||
// No prefix (plain number)
|
||||
yield 'plain_integer' => ['100', 100.0];
|
||||
yield 'plain_decimal' => ['4.7', 4.7];
|
||||
|
||||
// Decimal values with prefix (dot separator)
|
||||
yield 'decimal_nano' => ['4.7nF', 4.7e-9];
|
||||
yield 'decimal_micro' => ['0.1uF', 0.1e-6];
|
||||
yield 'decimal_kilo' => ['2.2k', 2.2e3];
|
||||
|
||||
// Comma decimal separator (European locale)
|
||||
yield 'comma_kilo' => ['4,7k', 4.7e3];
|
||||
yield 'comma_micro' => ['2,2uF', 2.2e-6];
|
||||
yield 'comma_kilo_space' => ['1,2 kΩ', 1.2e3];
|
||||
|
||||
// Number NOT at the start — should return NULL
|
||||
yield 'prefixed_name' => ['CAP-100nF', null];
|
||||
yield 'name_with_number' => ['R 4.7k 1%', null];
|
||||
yield 'crystal' => ['Crystal 20MHz', null];
|
||||
|
||||
// Number at start with trailing text
|
||||
yield 'number_with_suffix' => ['10nF 25V', 10e-9];
|
||||
|
||||
// Space between number and prefix
|
||||
yield 'space_before_prefix' => ['100 nF', 100e-9];
|
||||
|
||||
// Leading whitespace before number
|
||||
yield 'leading_whitespace' => [' 10uF', 10e-6];
|
||||
|
||||
// No number at all
|
||||
yield 'no_number' => ['Connector', null];
|
||||
yield 'text_only' => ['LED red', null];
|
||||
|
||||
// Null input
|
||||
yield 'null' => [null, null];
|
||||
|
||||
// Empty string
|
||||
yield 'empty' => ['', null];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the sort order is correct by comparing sqliteSiValue results.
|
||||
*/
|
||||
public function testSortOrder(): void
|
||||
{
|
||||
$parts = ['1uF', '100nF', '10pF', '10uF', '0.1mF', '1F', '10kF', '1MF'];
|
||||
$expected = ['10pF', '100nF', '1uF', '10uF', '0.1mF', '1F', '10kF', '1MF'];
|
||||
|
||||
// Sort using sqliteSiValue
|
||||
usort($parts, static function (string $a, string $b): int {
|
||||
$va = SiValueSort::sqliteSiValue($a);
|
||||
$vb = SiValueSort::sqliteSiValue($b);
|
||||
return $va <=> $vb;
|
||||
});
|
||||
|
||||
$this->assertSame($expected, $parts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that NULL values sort last (after all numeric values).
|
||||
*/
|
||||
public function testNullSortsLast(): void
|
||||
{
|
||||
$parts = ['Connector', '100nF', 'LED red', '10pF'];
|
||||
|
||||
usort($parts, static function (string $a, string $b): int {
|
||||
$va = SiValueSort::sqliteSiValue($a);
|
||||
$vb = SiValueSort::sqliteSiValue($b);
|
||||
|
||||
// NULL sorts last
|
||||
if ($va === null && $vb === null) {
|
||||
return 0;
|
||||
}
|
||||
if ($va === null) {
|
||||
return 1;
|
||||
}
|
||||
if ($vb === null) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return $va <=> $vb;
|
||||
});
|
||||
|
||||
$this->assertSame('10pF', $parts[0]);
|
||||
$this->assertSame('100nF', $parts[1]);
|
||||
// Last two should be the non-numeric names
|
||||
$this->assertContains('Connector', array_slice($parts, 2));
|
||||
$this->assertContains('LED red', array_slice($parts, 2));
|
||||
}
|
||||
}
|
||||
|
|
@ -26,13 +26,15 @@ use App\Entity\Parts\Part;
|
|||
use App\Entity\Parts\PartLot;
|
||||
use App\Entity\ProjectSystem\Project;
|
||||
use App\Entity\ProjectSystem\ProjectBOMEntry;
|
||||
use App\Entity\PriceInformations\Orderdetail;
|
||||
use App\Entity\PriceInformations\Pricedetail;
|
||||
use App\Services\ProjectSystem\ProjectBuildHelper;
|
||||
use Brick\Math\BigDecimal;
|
||||
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
|
||||
|
||||
final class ProjectBuildHelperTest extends WebTestCase
|
||||
{
|
||||
/** @var ProjectBuildHelper */
|
||||
protected $service;
|
||||
protected ProjectBuildHelper $service;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
|
|
@ -130,6 +132,180 @@ final class ProjectBuildHelperTest extends WebTestCase
|
|||
$project->addBomEntry($bom_entry1);
|
||||
|
||||
$this->assertSame('∞', $this->service->getMaximumBuildableCountAsString($project));
|
||||
}
|
||||
|
||||
// --- Build price tests ---
|
||||
|
||||
private function makePartWithPrice(float $pricePerPiece, float $minQty = 1.0): Part
|
||||
{
|
||||
$part = new Part();
|
||||
$orderdetail = new Orderdetail();
|
||||
$pricedetail = (new Pricedetail())
|
||||
->setMinDiscountQuantity($minQty)
|
||||
->setPrice(BigDecimal::of((string) $pricePerPiece));
|
||||
$orderdetail->addPricedetail($pricedetail);
|
||||
$part->addOrderdetail($orderdetail);
|
||||
return $part;
|
||||
}
|
||||
|
||||
public function testCalculateTotalBuildPriceEmptyProject(): void
|
||||
{
|
||||
$project = new Project();
|
||||
$this->assertNull($this->service->calculateTotalBuildPrice($project));
|
||||
}
|
||||
|
||||
public function testCalculateTotalBuildPriceNoPricingData(): void
|
||||
{
|
||||
$project = new Project();
|
||||
// Part with no orderdetails — no pricing
|
||||
$entry = (new ProjectBOMEntry())->setPart(new Part())->setQuantity(2);
|
||||
$project->addBomEntry($entry);
|
||||
|
||||
$this->assertNull($this->service->calculateTotalBuildPrice($project));
|
||||
}
|
||||
|
||||
public function testCalculateTotalBuildPriceNonPartEntry(): void
|
||||
{
|
||||
$project = new Project();
|
||||
$entry = new ProjectBOMEntry();
|
||||
$entry->setName('Custom wire');
|
||||
$entry->setQuantity(3);
|
||||
$entry->setPrice(BigDecimal::of('2.00'));
|
||||
$project->addBomEntry($entry);
|
||||
|
||||
// 3 × 2.00 = 6.00 for 1 build
|
||||
$result = $this->service->calculateTotalBuildPrice($project, 1);
|
||||
$this->assertNotNull($result);
|
||||
$this->assertTrue(BigDecimal::of('6.00')->isEqualTo($result));
|
||||
}
|
||||
|
||||
public function testCalculateTotalBuildPriceNonPartEntryMultipleBuilds(): void
|
||||
{
|
||||
$project = new Project();
|
||||
$entry = new ProjectBOMEntry();
|
||||
$entry->setName('Custom wire');
|
||||
$entry->setQuantity(3);
|
||||
$entry->setPrice(BigDecimal::of('2.00'));
|
||||
$project->addBomEntry($entry);
|
||||
|
||||
// 3 × 2.00 × 5 = 30.00 for 5 builds
|
||||
$result = $this->service->calculateTotalBuildPrice($project, 5);
|
||||
$this->assertNotNull($result);
|
||||
$this->assertTrue(BigDecimal::of('30.00')->isEqualTo($result));
|
||||
}
|
||||
|
||||
public function testCalculateTotalBuildPriceWithPart(): void
|
||||
{
|
||||
$project = new Project();
|
||||
$entry = new ProjectBOMEntry();
|
||||
$entry->setPart($this->makePartWithPrice(1.50));
|
||||
$entry->setQuantity(4);
|
||||
$project->addBomEntry($entry);
|
||||
|
||||
// 4 × 1.50 = 6.00 for 1 build
|
||||
$result = $this->service->calculateTotalBuildPrice($project, 1);
|
||||
$this->assertNotNull($result);
|
||||
$this->assertTrue(BigDecimal::of('6.00')->isEqualTo($result));
|
||||
}
|
||||
|
||||
public function testCalculateUnitBuildPriceEqualsTotal(): void
|
||||
{
|
||||
$project = new Project();
|
||||
$entry = new ProjectBOMEntry();
|
||||
$entry->setName('Screw');
|
||||
$entry->setQuantity(10);
|
||||
$entry->setPrice(BigDecimal::of('0.10'));
|
||||
$project->addBomEntry($entry);
|
||||
|
||||
// unit = 10 × 0.10 = 1.00; total for 3 builds = 3.00
|
||||
$unit = $this->service->calculateUnitBuildPrice($project, 3);
|
||||
$total = $this->service->calculateTotalBuildPrice($project, 3);
|
||||
$this->assertNotNull($unit);
|
||||
$this->assertNotNull($total);
|
||||
$this->assertTrue($total->isEqualTo($unit->multipliedBy(3)));
|
||||
}
|
||||
|
||||
public function testRoundedTotalBuildPriceRoundsUp(): void
|
||||
{
|
||||
$project = new Project();
|
||||
$entry = new ProjectBOMEntry();
|
||||
$entry->setName('Tiny part');
|
||||
$entry->setQuantity(1);
|
||||
$entry->setPrice(BigDecimal::of('0.001'));
|
||||
$project->addBomEntry($entry);
|
||||
|
||||
// 0.001 rounded up to 2dp = 0.01
|
||||
$result = $this->service->roundedTotalBuildPrice($project, 1);
|
||||
$this->assertNotNull($result);
|
||||
$this->assertTrue(BigDecimal::of('0.01')->isEqualTo($result));
|
||||
}
|
||||
|
||||
public function testCalculateTotalBuildPriceMixedEntries(): void
|
||||
{
|
||||
$project = new Project();
|
||||
|
||||
// Part entry: 2 × 3.00 = 6.00
|
||||
$partEntry = new ProjectBOMEntry();
|
||||
$partEntry->setPart($this->makePartWithPrice(3.00));
|
||||
$partEntry->setQuantity(2);
|
||||
$project->addBomEntry($partEntry);
|
||||
|
||||
// Non-part entry with price: 5 × 1.00 = 5.00
|
||||
$nonPartEntry = new ProjectBOMEntry();
|
||||
$nonPartEntry->setName('Solder');
|
||||
$nonPartEntry->setQuantity(5);
|
||||
$nonPartEntry->setPrice(BigDecimal::of('1.00'));
|
||||
$project->addBomEntry($nonPartEntry);
|
||||
|
||||
// Total = 11.00
|
||||
$result = $this->service->calculateTotalBuildPrice($project, 1);
|
||||
$this->assertNotNull($result);
|
||||
$this->assertTrue(BigDecimal::of('11.00')->isEqualTo($result));
|
||||
}
|
||||
|
||||
public function testGetEntryUnitPriceReturnsZeroForNoPricingData(): void
|
||||
{
|
||||
$entry = new ProjectBOMEntry();
|
||||
$entry->setPart(new Part()); // part with no orderdetails
|
||||
$entry->setQuantity(5);
|
||||
|
||||
$result = $this->service->getEntryUnitPrice($entry);
|
||||
$this->assertTrue(BigDecimal::zero()->isEqualTo($result));
|
||||
}
|
||||
|
||||
public function testGetEntryUnitPriceNonPartEntry(): void
|
||||
{
|
||||
$entry = new ProjectBOMEntry();
|
||||
$entry->setName('Wire');
|
||||
$entry->setQuantity(2);
|
||||
$entry->setPrice(BigDecimal::of('1.25'));
|
||||
|
||||
$result = $this->service->getEntryUnitPrice($entry);
|
||||
$this->assertTrue(BigDecimal::of('1.25')->isEqualTo($result));
|
||||
}
|
||||
|
||||
public function testGetEntryUnitPriceWithPart(): void
|
||||
{
|
||||
$entry = new ProjectBOMEntry();
|
||||
$entry->setPart($this->makePartWithPrice(2.00));
|
||||
$entry->setQuantity(3);
|
||||
|
||||
$result = $this->service->getEntryUnitPrice($entry);
|
||||
$this->assertTrue(BigDecimal::of('2.00')->isEqualTo($result));
|
||||
}
|
||||
|
||||
public function testCalculateTotalBuildPriceRespectsMinOrderAmount(): void
|
||||
{
|
||||
$project = new Project();
|
||||
// Part has a minimum order quantity of 10 at 0.50/piece
|
||||
$entry = new ProjectBOMEntry();
|
||||
$entry->setPart($this->makePartWithPrice(0.50, 10.0));
|
||||
$entry->setQuantity(1); // BOM only needs 1, but MOQ is 10
|
||||
$project->addBomEntry($entry);
|
||||
|
||||
// Price lookup uses qty=10 (MOQ), returns 0.50. Cost = 1 × 0.50 = 0.50
|
||||
$result = $this->service->calculateTotalBuildPrice($project, 1);
|
||||
$this->assertNotNull($result);
|
||||
$this->assertTrue(BigDecimal::of('0.50')->isEqualTo($result));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,8 +28,7 @@ use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
|
|||
|
||||
final class ProjectBuildPartHelperTest extends WebTestCase
|
||||
{
|
||||
/** @var ProjectBuildPartHelper */
|
||||
protected $service;
|
||||
protected ProjectBuildPartHelper $service;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
|
|
|
|||
|
|
@ -7241,6 +7241,12 @@ Element 3</target>
|
|||
<target>Cena</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="bomExPrc" name="project.bom.ext_price">
|
||||
<segment state="initial">
|
||||
<source>project.bom.ext_price</source>
|
||||
<target>Extended Price</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="8tP3lQI" name="part.info.withdraw_modal.title.withdraw">
|
||||
<segment state="translated">
|
||||
<source>part.info.withdraw_modal.title.withdraw</source>
|
||||
|
|
|
|||
|
|
@ -642,6 +642,12 @@ Underelementer vil blive flyttet opad.</target>
|
|||
<target>Gruppe</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="8rz303Z" name="specifications.eda_visibility.help">
|
||||
<segment state="translated">
|
||||
<source>specifications.eda_visibility.help</source>
|
||||
<target>Eksporter denne parameter som et EDA felt</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="XclPxI9" name="specification.create">
|
||||
<segment state="translated">
|
||||
<source>specification.create</source>
|
||||
|
|
@ -2923,6 +2929,42 @@ Bemærk også, at uden to-faktor-godkendelse er din konto ikke længere så godt
|
|||
<target>Bilag</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="f3Dggp6" name="part.table.eda_status">
|
||||
<segment state="translated">
|
||||
<source>part.table.eda_status</source>
|
||||
<target>EDA</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="Q_myBuD" name="eda.status.symbol_set">
|
||||
<segment state="translated">
|
||||
<source>eda.status.symbol_set</source>
|
||||
<target>KiCad symbolsæt</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="QGLfvit" name="eda.status.footprint_set">
|
||||
<segment state="translated">
|
||||
<source>eda.status.footprint_set</source>
|
||||
<target>KiCad footprintsæt</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="hkze9M." name="eda.status.reference_set">
|
||||
<segment state="translated">
|
||||
<source>eda.status.reference_set</source>
|
||||
<target>eda. status.reference_set</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="OTXbAfL" name="eda.status.complete">
|
||||
<segment state="translated">
|
||||
<source>eda.status.complete</source>
|
||||
<target>EDA felter udfyldt (symbol, footprint, reference)</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="z9E5RB." name="eda.status.partial">
|
||||
<segment state="translated">
|
||||
<source>eda.status.partial</source>
|
||||
<target>EDA felter delvist udfyldt</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="bMkafCp" name="flash.login_successful">
|
||||
<segment state="translated">
|
||||
<source>flash.login_successful</source>
|
||||
|
|
@ -3265,6 +3307,12 @@ Bemærk også, at uden to-faktor-godkendelse er din konto ikke længere så godt
|
|||
<target>Ikke længere tilgængelig</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="6H0WQWq" name="orderdetails.edit.eda_visibility">
|
||||
<segment state="translated">
|
||||
<source>orderdetails.edit.eda_visibility</source>
|
||||
<target>Synlige i EDA</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="ZsO5AKM" name="orderdetails.edit.supplierpartnr.placeholder">
|
||||
<segment state="translated">
|
||||
<source>orderdetails.edit.supplierpartnr.placeholder</source>
|
||||
|
|
@ -7184,6 +7232,12 @@ Element 3</target>
|
|||
<target>Pris</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="bomExPrc" name="project.bom.ext_price">
|
||||
<segment state="initial">
|
||||
<source>project.bom.ext_price</source>
|
||||
<target>Extended Price</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="8tP3lQI" name="part.info.withdraw_modal.title.withdraw">
|
||||
<segment state="translated">
|
||||
<source>part.info.withdraw_modal.title.withdraw</source>
|
||||
|
|
@ -9502,6 +9556,12 @@ Bemærk venligst, at du ikke kan kopiere fra deaktiveret bruger. Hvis du prøver
|
|||
<target>EIGP 114 stregkode (f.eks. Datamatrix-kode fra Digikey og Mouser dele)</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="BnqcKWx" name="scan_dialog.mode.lcsc">
|
||||
<segment state="translated">
|
||||
<source>scan_dialog.mode.lcsc</source>
|
||||
<target>LCSC.com barcode</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="QSMS_Bd" name="scan_dialog.info_mode">
|
||||
<segment state="translated">
|
||||
<source>scan_dialog.info_mode</source>
|
||||
|
|
@ -9514,6 +9574,24 @@ Bemærk venligst, at du ikke kan kopiere fra deaktiveret bruger. Hvis du prøver
|
|||
<target>Afkodet information</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="kQnodbA" name="label_scanner.target_found">
|
||||
<segment state="translated">
|
||||
<source>label_scanner.target_found</source>
|
||||
<target>Genstand fundet i database</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="7Arfw2q" name="label_scanner.scan_result.title">
|
||||
<segment state="translated">
|
||||
<source>label_scanner.scan_result.title</source>
|
||||
<target>Scan-resultat</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="PTh4EK_" name="label_scanner.no_locations">
|
||||
<segment state="translated">
|
||||
<source>label_scanner.no_locations</source>
|
||||
<target>Part er ikke gemt på nogen lokation.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="nmXQWcS" name="label_generator.edit_profiles">
|
||||
<segment state="translated">
|
||||
<source>label_generator.edit_profiles</source>
|
||||
|
|
@ -9948,6 +10026,18 @@ Bemærk venligst, at du ikke kan kopiere fra deaktiveret bruger. Hvis du prøver
|
|||
<target>Denne værdi bestemmer dybden af kategoritræet, der er synligt i KiCad. 0 betyder, at kun kategorierne på øverste niveau er synlige. Indstil værdien til > 0 for at vise yderligere niveauer. Indstil værdien til -1 for at vise alle dele af deldatabasen inden for en enkelt kategori i KiCad.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="X5.rQdO" name="settings.misc.kicad_eda.datasheet_link">
|
||||
<segment state="translated">
|
||||
<source>settings.misc.kicad_eda.datasheet_link</source>
|
||||
<target>Databladsfelt linker til PDF</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="Fm1QTCs" name="settings.misc.kicad_eda.datasheet_link.help">
|
||||
<segment state="translated">
|
||||
<source>settings.misc.kicad_eda.datasheet_link.help</source>
|
||||
<target>Når det er aktiveret, vil dataarkfeltet i KiCad linke til den faktiske PDF-fil (hvis den findes). Når det er deaktiveret, vil det i stedet linke til Part-DB-siden. Linket til Part-DB-siden er altid tilgængeligt som et separat felt "Part-DB URL".</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="VwvmcWE" name="settings.behavior.sidebar">
|
||||
<segment state="translated">
|
||||
<source>settings.behavior.sidebar</source>
|
||||
|
|
@ -10290,6 +10380,24 @@ Bemærk venligst, at du ikke kan kopiere fra deaktiveret bruger. Hvis du prøver
|
|||
<target>Vis billedoverlejringen med detaljer om vedhæftet fil, når du holder musen over billedgalleriet med dele.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="0iYdzdk" name="settings.behavior.keybindings">
|
||||
<segment state="translated">
|
||||
<source>settings.behavior.keybindings</source>
|
||||
<target>Tastaturgenveje</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="_x13bMa" name="settings.behavior.keybindings.enable_special_characters">
|
||||
<segment state="translated">
|
||||
<source>settings.behavior.keybindings.enable_special_characters</source>
|
||||
<target>Aktivér tastaturgenveje for specialtegn</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="Af8Zzqr" name="settings.behavior.keybindings.enable_special_characters.help">
|
||||
<segment state="translated">
|
||||
<source>settings.behavior.keybindings.enable_special_characters.help</source>
|
||||
<target>Aktivér genvejstasten Alt+ for at indsætte specialtegn (græske bogstaver, matematiske symboler osv.) i tekstfelter. Deaktiver dette, hvis genvejene er i konflikt med dit tastaturlayout eller systemgenveje.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="ALfPkeR" name="perm.config.change_system_settings">
|
||||
<segment state="translated">
|
||||
<source>perm.config.change_system_settings</source>
|
||||
|
|
@ -10914,6 +11022,84 @@ Bemærk venligst, at du ikke kan kopiere fra deaktiveret bruger. Hvis du prøver
|
|||
<target>Masseimport af datakilder</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="VtS1yT7" name="part_list.action.group.eda">
|
||||
<segment state="translated">
|
||||
<source>part_list.action.group.eda</source>
|
||||
<target>EDA / KiCad</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="swU1Rp2" name="part_list.action.batch_edit_eda">
|
||||
<segment state="translated">
|
||||
<source>part_list.action.batch_edit_eda</source>
|
||||
<target>Batchredigering af EDA-felter</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="ZaS_Hg5" name="batch_eda.title">
|
||||
<segment state="translated">
|
||||
<source>batch_eda.title</source>
|
||||
<target>Batchredigering af EDA-felter</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="k2FDo7A" name="batch_eda.description">
|
||||
<segment state="translated">
|
||||
<source>batch_eda.description</source>
|
||||
<target>Rediger EDA/KiCad-felter for %count% valgte dele. Markér feltet "Anvend" ud for hvert felt, du vil ændre.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="WVHbic3" name="batch_eda.show_parts">
|
||||
<segment state="translated">
|
||||
<source>batch_eda.show_parts</source>
|
||||
<target>Vis valgte dele</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="ubQd6G4" name="batch_eda.apply_hint">
|
||||
<segment state="translated">
|
||||
<source>batch_eda.apply_hint</source>
|
||||
<target>Kun felter, hvor afkrydsningsfeltet "Anvend" er markeret, ændres. Felter, der ikke er markeret, ændres ikke.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="w.5FGYL" name="batch_eda.apply">
|
||||
<segment state="translated">
|
||||
<source>batch_eda.apply</source>
|
||||
<target>Anvend</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="9EmHp5C" name="batch_eda.field">
|
||||
<segment state="translated">
|
||||
<source>batch_eda.field</source>
|
||||
<target>Felt</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="xHaCnEQ" name="batch_eda.value">
|
||||
<segment state="translated">
|
||||
<source>batch_eda.value</source>
|
||||
<target>Værdi</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="PLqIBvC" name="batch_eda.submit">
|
||||
<segment state="translated">
|
||||
<source>batch_eda.submit</source>
|
||||
<target>Anvend på udvalgte dele</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="5nO7Fpq" name="batch_eda.cancel">
|
||||
<segment state="translated">
|
||||
<source>batch_eda.cancel</source>
|
||||
<target>Annullér</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="vhlPBNU" name="batch_eda.success">
|
||||
<segment state="translated">
|
||||
<source>batch_eda.success</source>
|
||||
<target>EDA felter er nu opdateret</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="2fMo760" name="batch_eda.no_parts_selected">
|
||||
<segment state="translated">
|
||||
<source>batch_eda.no_parts_selected</source>
|
||||
<target>Ingen dele blev valgt til batchredigering.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="yzpXFkB" name="info_providers.bulk_import.step1.spn_recommendation">
|
||||
<segment state="translated">
|
||||
<source>info_providers.bulk_import.step1.spn_recommendation</source>
|
||||
|
|
@ -12227,7 +12413,7 @@ Buerklin API-godkendelsesserver: 10 anmodninger/minut pr. IP-adresse</target>
|
|||
<unit id="aSHDhOi" name="update_manager.progress.downgrade_title">
|
||||
<segment state="translated">
|
||||
<source>update_manager.progress.downgrade_title</source>
|
||||
<target>Downgrade fremskridt</target>
|
||||
<target>Downgrade fremskridtPart-DB er blevet nedgraderet! Du skal muligvis opdatere siden for at se den nye version.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="XYR1vvR" name="update_manager.progress.downgrade_completed">
|
||||
|
|
@ -12314,6 +12500,102 @@ Buerklin API-godkendelsesserver: 10 anmodninger/minut pr. IP-adresse</target>
|
|||
<target>Gendannelse af sikkerhedskopi er deaktiveret af serverkonfigurationen.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="oAb35wU" name="update_manager.backup.create">
|
||||
<segment state="translated">
|
||||
<source>update_manager.backup.create</source>
|
||||
<target>Opret sikkerhedskopi</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="ms26oI0" name="update_manager.backup.create.confirm">
|
||||
<segment state="translated">
|
||||
<source>update_manager.backup.create.confirm</source>
|
||||
<target>Vil du lave en fuld sikkerhedskopi nu? Det kan tage et stykke tid.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="H9y0eLa" name="update_manager.backup.created">
|
||||
<segment state="translated">
|
||||
<source>update_manager.backup.created</source>
|
||||
<target>Sikkerhedskopi er oprettet.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="bMhXPVB" name="update_manager.backup.delete.confirm">
|
||||
<segment state="translated">
|
||||
<source>update_manager.backup.delete.confirm</source>
|
||||
<target>Er du sikker på at du vil slette denne backup?</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="8tw67c_" name="update_manager.backup.deleted">
|
||||
<segment state="translated">
|
||||
<source>update_manager.backup.deleted</source>
|
||||
<target>Sikkerhedskopi er slettet.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="BzBBuqk" name="update_manager.backup.delete_error">
|
||||
<segment state="translated">
|
||||
<source>update_manager.backup.delete_error</source>
|
||||
<target>Sikkerhedskopi kunne ikke udføres.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="2olmcSs" name="update_manager.log.delete.confirm">
|
||||
<segment state="translated">
|
||||
<source>update_manager.log.delete.confirm</source>
|
||||
<target>Er du sikker på at du vil slette denne log?</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id=".ZrVHpp" name="update_manager.log.deleted">
|
||||
<segment state="translated">
|
||||
<source>update_manager.log.deleted</source>
|
||||
<target>Log slettet.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="P2JI5Yw" name="update_manager.log.delete_error">
|
||||
<segment state="translated">
|
||||
<source>update_manager.log.delete_error</source>
|
||||
<target>Kunne ikke slette loggen.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="Yos9FWk" name="update_manager.view_log">
|
||||
<segment state="translated">
|
||||
<source>update_manager.view_log</source>
|
||||
<target>Vis log.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="B9uA2va" name="update_manager.delete">
|
||||
<segment state="translated">
|
||||
<source>update_manager.delete</source>
|
||||
<target>Slet</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="ZtgvnXB" name="update_manager.backup.download">
|
||||
<segment state="translated">
|
||||
<source>update_manager.backup.download</source>
|
||||
<target>Download sikkerhedskopi</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="wxtmrnP" name="update_manager.backup.download.password_label">
|
||||
<segment state="translated">
|
||||
<source>update_manager.backup.download.password_label</source>
|
||||
<target>Bekræft password for at downloade</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="MIlTTgL" name="update_manager.backup.download.security_warning">
|
||||
<segment state="translated">
|
||||
<source>update_manager.backup.download.security_warning</source>
|
||||
<target>Sikkerhedskopier indeholder følsomme data, herunder password-hashes og hemmeligheder. Bekræft venligst dit password for at fortsætte med download.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="kZPHBRt" name="update_manager.backup.download.invalid_password">
|
||||
<segment state="translated">
|
||||
<source>update_manager.backup.download.invalid_password</source>
|
||||
<target>Ugyldigt password. Download af sikkerhedskopi er afvist.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="AZOjnE0" name="update_manager.backup.docker_warning">
|
||||
<segment state="translated">
|
||||
<source>update_manager.backup.docker_warning</source>
|
||||
<target>Docker-installation registreret. Sikkerhedskopier gemmes i var/backups/, som ikke er en persistent enhed. Brug downloadknappen til at gemme sikkerhedskopier eksternt, eller montér var/backups/ som en enhed i din docker-compose.yml.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="kHKChQB" name="settings.ips.conrad">
|
||||
<segment state="translated">
|
||||
<source>settings.ips.conrad</source>
|
||||
|
|
@ -12404,5 +12686,281 @@ Buerklin API-godkendelsesserver: 10 anmodninger/minut pr. IP-adresse</target>
|
|||
<target>Opdatér til</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="XPhnMxn" name="part.gtin">
|
||||
<segment state="translated">
|
||||
<source>part.gtin</source>
|
||||
<target>GTIN / EAN</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="TyykD7B" name="info_providers.capabilities.gtin">
|
||||
<segment state="translated">
|
||||
<source>info_providers.capabilities.gtin</source>
|
||||
<target>GTIN / EAN</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="JBGly8p" name="part.table.gtin">
|
||||
<segment state="translated">
|
||||
<source>part.table.gtin</source>
|
||||
<target>GTIN</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="0qHQof." name="scan_dialog.mode.gtin">
|
||||
<segment state="translated">
|
||||
<source>scan_dialog.mode.gtin</source>
|
||||
<target>GTIN / EAN barcode</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="cmchX59" name="attachment_type.edit.allowed_targets">
|
||||
<segment state="translated">
|
||||
<source>attachment_type.edit.allowed_targets</source>
|
||||
<target>Anvend kun til</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="t5R8p1l" name="attachment_type.edit.allowed_targets.help">
|
||||
<segment state="translated">
|
||||
<source>attachment_type.edit.allowed_targets.help</source>
|
||||
<target>Gør kun denne bilagstype tilgængelig for bestemte elementklasser. Lad feltet stå tomt for at vise denne bilagstype for alle elementklasser.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="LvlEUjC" name="orderdetails.edit.prices_includes_vat">
|
||||
<segment state="translated">
|
||||
<source>orderdetails.edit.prices_includes_vat</source>
|
||||
<target>Pris inklusiv moms.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="GUsVh5T" name="prices.incl_vat">
|
||||
<segment state="translated">
|
||||
<source>prices.incl_vat</source>
|
||||
<target>Inkl. moms</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="3ipwaVQ" name="prices.excl_vat">
|
||||
<segment state="translated">
|
||||
<source>prices.excl_vat</source>
|
||||
<target>Ekskl. moms</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="WDJ7EeF" name="settings.system.localization.prices_include_tax_by_default">
|
||||
<segment state="translated">
|
||||
<source>settings.system.localization.prices_include_tax_by_default</source>
|
||||
<target>Priserne er som standard inklusive moms</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="01oGY_r" name="settings.system.localization.prices_include_tax_by_default.description">
|
||||
<segment state="translated">
|
||||
<source>settings.system.localization.prices_include_tax_by_default.description</source>
|
||||
<target>Standardværdien for nyoprettede købsoplysninger, uanset om priserne inkluderer moms eller ej.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="heWSnAH" name="part_lot.edit.last_stocktake_at">
|
||||
<segment state="translated">
|
||||
<source>part_lot.edit.last_stocktake_at</source>
|
||||
<target>Seneste optælling</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id=".LP93kG" name="perm.parts_stock.stocktake">
|
||||
<segment state="translated">
|
||||
<source>perm.parts_stock.stocktake</source>
|
||||
<target>Lageropgørelse</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="Vnhrb5R" name="part.info.stocktake_modal.title">
|
||||
<segment state="translated">
|
||||
<source>part.info.stocktake_modal.title</source>
|
||||
<target>Lagerbeholdning</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="WqOG7RK" name="part.info.stocktake_modal.expected_amount">
|
||||
<segment state="translated">
|
||||
<source>part.info.stocktake_modal.expected_amount</source>
|
||||
<target>Forventet mængde</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="E7IbVN6" name="part.info.stocktake_modal.actual_amount">
|
||||
<segment state="translated">
|
||||
<source>part.info.stocktake_modal.actual_amount</source>
|
||||
<target>Aktuel mængde</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="4GwSma7" name="log.part_stock_changed.stock_take">
|
||||
<segment state="translated">
|
||||
<source>log.part_stock_changed.stock_take</source>
|
||||
<target>Lagerbeholdning</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="aRQPMW7" name="log.element_edited.changed_fields.last_stocktake_at">
|
||||
<segment state="translated">
|
||||
<source>log.element_edited.changed_fields.last_stocktake_at</source>
|
||||
<target>Sidste lagerbeholdning</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="GNWhoTW" name="part.table.eda_reference">
|
||||
<segment state="translated">
|
||||
<source>part.table.eda_reference</source>
|
||||
<target>EDA reference</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="tW4yCbf" name="part.table.eda_value">
|
||||
<segment state="translated">
|
||||
<source>part.table.eda_value</source>
|
||||
<target>EDA-værdi</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="s1pgReC" name="settings.misc.kicad_eda.default_parameter_visibility">
|
||||
<segment state="translated">
|
||||
<source>settings.misc.kicad_eda.default_parameter_visibility</source>
|
||||
<target>Standard EDA-synlighed for parametre</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="Z78QunV" name="settings.misc.kicad_eda.default_parameter_visibility.help">
|
||||
<segment state="translated">
|
||||
<source>settings.misc.kicad_eda.default_parameter_visibility.help</source>
|
||||
<target>EDA-synlighed for alle [Part]-parametre, som ikke har en eksplicit synlighedsindstilling. Når den er aktiveret, vil alle parametre som standard være synlige i EDA-softwaren.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="J6pYnaC" name="settings.misc.kicad_eda.default_orderdetails_visibility">
|
||||
<segment state="translated">
|
||||
<source>settings.misc.kicad_eda.default_orderdetails_visibility</source>
|
||||
<target>Standard EDA-synlighed for købsoplysninger</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="Hiye4C." name="settings.misc.kicad_eda.default_orderdetails_visibility.help">
|
||||
<segment state="translated">
|
||||
<source>settings.misc.kicad_eda.default_orderdetails_visibility.help</source>
|
||||
<target>EDA-synlighed for alle købsoplysninger, som ikke har en eksplicit synlighedsindstilling. Når den er aktiveret, vil alle købsoplysninger som standard være synlige i EDA-softwaren.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="aEgd0if" name="label_scanner.open">
|
||||
<segment state="translated">
|
||||
<source>label_scanner.open</source>
|
||||
<target>Vis detaljer</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="vw_0Qws" name="label_scanner.db_part_found">
|
||||
<segment state="translated">
|
||||
<source>label_scanner.db_part_found</source>
|
||||
<target>Database [part] fundet for barcode</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="zntajcd" name="label_scanner.part_can_be_created">
|
||||
<segment state="translated">
|
||||
<source>label_scanner.part_can_be_created</source>
|
||||
<target>[Part] kan oprettes</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="cLTbd9w" name="label_scanner.part_can_be_created.help">
|
||||
<segment state="translated">
|
||||
<source>label_scanner.part_can_be_created.help</source>
|
||||
<target>Der blev ikke fundet nogen matchende [part] i databasen, men du kan oprette en ny [part] baseret på denne stregkode.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="FfHA3Yf" name="label_scanner.part_create_btn">
|
||||
<segment state="translated">
|
||||
<source>label_scanner.part_create_btn</source>
|
||||
<target>Opret [part] fra barcode</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="xH258F." name="parts.create_from_scan.title">
|
||||
<segment state="translated">
|
||||
<source>parts.create_from_scan.title</source>
|
||||
<target>Opret [part] ud fra labelscanning</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="8WZYwRJ" name="scan_dialog.mode.amazon">
|
||||
<segment state="translated">
|
||||
<source>scan_dialog.mode.amazon</source>
|
||||
<target>Amazon barcode</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="BQWuR_G" name="settings.ips.canopy">
|
||||
<segment state="translated">
|
||||
<source>settings.ips.canopy</source>
|
||||
<target>Canopy</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="44BfYzy" name="settings.ips.canopy.alwaysGetDetails">
|
||||
<segment state="translated">
|
||||
<source>settings.ips.canopy.alwaysGetDetails</source>
|
||||
<target>Hent altid detaljer</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="so_ms3t" name="settings.ips.canopy.alwaysGetDetails.help">
|
||||
<segment state="translated">
|
||||
<source>settings.ips.canopy.alwaysGetDetails.help</source>
|
||||
<target>Når dette er valgt, hentes flere detaljer fra canopy, når en del oprettes. Dette forårsager en yderligere API-anmodning, men giver produktpunkter og kategorioplysninger.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="D055xh8" name="attachment.sandbox.warning">
|
||||
<segment state="translated">
|
||||
<source>attachment.sandbox.warning</source>
|
||||
<target>ADVARSEL: Du ser en brugeruploadet vedhæftet fil. Dette er indhold, der ikke er tillid til. Vær forsigtig.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="bRcdnJK" name="attachment.sandbox.back_to_partdb">
|
||||
<segment state="translated">
|
||||
<source>attachment.sandbox.back_to_partdb</source>
|
||||
<target>Tilbage til Part-DB</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="MzyA7N8" name="settings.system.attachments.showHTMLAttachments">
|
||||
<segment state="translated">
|
||||
<source>settings.system.attachments.showHTMLAttachments</source>
|
||||
<target>Vis uploadede HTML-filvedhæftninger (sandboxed)</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="V_LJkRy" name="settings.system.attachments.showHTMLAttachments.help">
|
||||
<segment state="translated">
|
||||
<source>settings.system.attachments.showHTMLAttachments.help</source>
|
||||
<target>⚠️ Når det er aktiveret, kan brugeruploadede HTML-vedhæftninger ses direkte i browseren. Mange potentielt skadelige funktioner er begrænsede, men dette er stadig en potentiel sikkerhedsrisiko og bør kun aktiveres, hvis du har tillid til de brugere, der kan uploade filer.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="BQo2xWi" name="attachment.sandbox.title">
|
||||
<segment state="translated">
|
||||
<source>attachment.sandbox.title</source>
|
||||
<target>HTML [Vedhæftning]</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="sJ6v9uJ" name="attachment.sandbox.as_plain_text">
|
||||
<segment state="translated">
|
||||
<source>attachment.sandbox.as_plain_text</source>
|
||||
<target>Vis som alm. tekst</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="Ehsj93c" name="modal.cancel">
|
||||
<segment state="translated">
|
||||
<source>modal.cancel</source>
|
||||
<target>Annuller</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="jdpoFf2" name="update_manager.web_updates_allowed">
|
||||
<segment state="translated">
|
||||
<source>update_manager.web_updates_allowed</source>
|
||||
<target>Web-opdateringer tilladt</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="bdWa7is" name="update_manager.backup_restore_allowed">
|
||||
<segment state="translated">
|
||||
<source>update_manager.backup_restore_allowed</source>
|
||||
<target>Indlæsning af sikkerhedskopi (backup) tilladt</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="kllGQEN" name="update_manager.backup_download_allowed">
|
||||
<segment state="translated">
|
||||
<source>update_manager.backup_download_allowed</source>
|
||||
<target>Download af sikkerhedskopi tilladt</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="b8JxfcX" name="part.create_from_info_provider.lot_filled_from_barcode">
|
||||
<segment state="translated">
|
||||
<source>part.create_from_info_provider.lot_filled_from_barcode</source>
|
||||
<target>[Part_lot] oprettet fra stregkode: Kontroller venligst, om dataene er korrekte og ønskede.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="F8pQuL9" name="project.bom_import.field_mapping.error.check_delimiter">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.field_mapping.error.check_delimiter</source>
|
||||
<target>Felttilknytningsfejl: Kontroller, om du har valgt den rigtige tegn-afgrænser!</target>
|
||||
</segment>
|
||||
</unit>
|
||||
</file>
|
||||
</xliff>
|
||||
</xliff>
|
||||
|
|
|
|||
|
|
@ -2779,6 +2779,12 @@ Wenn Sie dies fehlerhafterweise gemacht haben oder ein Computer nicht mehr vertr
|
|||
<target>Name</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="sIvAlUe" name="part.table.si_value">
|
||||
<segment state="translated">
|
||||
<source>part.table.si_value</source>
|
||||
<target>SI-Wert</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="rW_SFJE" name="part.table.id">
|
||||
<segment state="translated">
|
||||
<source>part.table.id</source>
|
||||
|
|
@ -7211,6 +7217,18 @@ Element 1 -> Element 1.2</target>
|
|||
<target>Unterprojekte</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="prjTtlBP" name="project.info.total_build_price">
|
||||
<segment state="translated">
|
||||
<source>project.info.total_build_price</source>
|
||||
<target>Gesamterstellpreis</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="prjUntBP" name="project.info.per_unit_price">
|
||||
<segment state="translated">
|
||||
<source>project.info.per_unit_price</source>
|
||||
<target>pro Einheit</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="7nV.Cmd" name="project.info.bom_add_parts">
|
||||
<segment state="translated">
|
||||
<source>project.info.bom_add_parts</source>
|
||||
|
|
@ -7235,6 +7253,12 @@ Element 1 -> Element 1.2</target>
|
|||
<target>Preis</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="bomExPrc" name="project.bom.ext_price">
|
||||
<segment state="translated">
|
||||
<source>project.bom.ext_price</source>
|
||||
<target>Gesamtpreis</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="8tP3lQI" name="part.info.withdraw_modal.title.withdraw">
|
||||
<segment state="translated">
|
||||
<source>part.info.withdraw_modal.title.withdraw</source>
|
||||
|
|
@ -10028,6 +10052,90 @@ Bitte beachten Sie, dass Sie sich nicht als deaktivierter Benutzer ausgeben kön
|
|||
<target>Wenn aktiviert, verlinkt das Datenblatt-Feld in KiCad auf die tatsächliche PDF-Datei (sofern gefunden). Wenn deaktiviert, führt es stattdessen zur Part-DB-Seite. Der Link zur Part-DB-Seite ist immer als separates "Part-DB URL"-Feld verfügbar.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="e2e7mR1" name="settings.misc.kicad_eda.editor.title">
|
||||
<segment state="translated">
|
||||
<source>settings.misc.kicad_eda.editor.title</source>
|
||||
<target>KiCad Autovervollständigungslisten</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="qjv1VVx" name="settings.misc.kicad_eda.editor.link">
|
||||
<segment state="translated">
|
||||
<source>settings.misc.kicad_eda.editor.link</source>
|
||||
<target>Autovervollständigungseinstellungen</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="f0qkcqg" name="settings.misc.kicad_eda.editor.description">
|
||||
<segment state="translated">
|
||||
<source>settings.misc.kicad_eda.editor.description</source>
|
||||
<target>Konfigurieren Sie, ob KiCad Autovervollständigung die automatisch generierten Standardlisten oder Ihre benutzerdefinierten Überschreibungsdateien verwendet. Die benutzerdefinierten Dateien sind hier bearbeitbar, während die Standarddateien nur lesbar zur Referenz angezeigt werden.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="AS3yDlb" name="settings.misc.kicad_eda.editor.footprints">
|
||||
<segment state="translated">
|
||||
<source>settings.misc.kicad_eda.editor.footprints</source>
|
||||
<target>Footprint-Liste</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="Jj_YR7n" name="settings.misc.kicad_eda.editor.footprints.help">
|
||||
<segment state="translated">
|
||||
<source>settings.misc.kicad_eda.editor.footprints.help</source>
|
||||
<target>Ein Eintrag pro Zeile. Wird als Autovervollständigungsvorschlag für KiCad-Footprintfelder verwendet.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="ELd3KQK" name="settings.misc.kicad_eda.editor.symbols">
|
||||
<segment state="translated">
|
||||
<source>settings.misc.kicad_eda.editor.symbols</source>
|
||||
<target>Symbolliste</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="A9TOJgM" name="settings.misc.kicad_eda.editor.symbols.help">
|
||||
<segment state="translated">
|
||||
<source>settings.misc.kicad_eda.editor.symbols.help</source>
|
||||
<target>Ein Eintrag pro Zeile. Wird als Autovervollständigungsvorschlag für KiCad-Symbolfelder verwendet.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="tWYlL0u" name="settings.misc.kicad_eda.use_custom_list">
|
||||
<segment state="translated">
|
||||
<source>settings.misc.kicad_eda.use_custom_list</source>
|
||||
<target>Benutzerdefinierte Autovervollständigungslisten verwenden</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="v0LK7n6" name="settings.misc.kicad_eda.use_custom_list.help">
|
||||
<segment state="translated">
|
||||
<source>settings.misc.kicad_eda.use_custom_list.help</source>
|
||||
<target>Wenn aktiviert, verwendet die KiCad Autovervollständigung public/kicad/footprints_custom.txt und public/kicad/symbols_custom.txt anstelle der automatisch generierten Standarddateien.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="Yl_fqfV" name="settings.misc.kicad_eda.editor.custom_footprints">
|
||||
<segment state="translated">
|
||||
<source>settings.misc.kicad_eda.editor.custom_footprints</source>
|
||||
<target>Benutzerdefinierte Footprint-Liste</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="GuD2JcQ" name="settings.misc.kicad_eda.editor.custom_symbols">
|
||||
<segment state="translated">
|
||||
<source>settings.misc.kicad_eda.editor.custom_symbols</source>
|
||||
<target>Benutzerdefinierte Symbolliste</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="k6m9b5F" name="settings.misc.kicad_eda.editor.default_footprints">
|
||||
<segment state="translated">
|
||||
<source>settings.misc.kicad_eda.editor.default_footprints</source>
|
||||
<target>Standard Footprint-Liste</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="bKkF8mM" name="settings.misc.kicad_eda.editor.default_symbols">
|
||||
<segment state="translated">
|
||||
<source>settings.misc.kicad_eda.editor.default_symbols</source>
|
||||
<target>Standardsymboliste</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="mIj_i4E" name="settings.misc.kicad_eda.editor.default_files_help">
|
||||
<segment state="translated">
|
||||
<source>settings.misc.kicad_eda.editor.default_files_help</source>
|
||||
<target>Automatisch generierte Datei wird nur zur Referenz angezeigt. Änderungen müssen in der benutzerdefinierten Liste vorgenommen werden.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="VwvmcWE" name="settings.behavior.sidebar">
|
||||
<segment state="translated">
|
||||
<source>settings.behavior.sidebar</source>
|
||||
|
|
|
|||
|
|
@ -2780,6 +2780,12 @@ If you have done this incorrectly or if a computer is no longer trusted, you can
|
|||
<target>Name</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="sIvAlUe" name="part.table.si_value">
|
||||
<segment state="translated">
|
||||
<source>part.table.si_value</source>
|
||||
<target>SI Value</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="rW_SFJE" name="part.table.id">
|
||||
<segment state="translated">
|
||||
<source>part.table.id</source>
|
||||
|
|
@ -7212,6 +7218,18 @@ Element 1 -> Element 1.2</target>
|
|||
<target>Subprojects</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="prjTtlBP" name="project.info.total_build_price">
|
||||
<segment state="translated">
|
||||
<source>project.info.total_build_price</source>
|
||||
<target>Total build price</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="prjUntBP" name="project.info.per_unit_price">
|
||||
<segment state="translated">
|
||||
<source>project.info.per_unit_price</source>
|
||||
<target>per unit</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="7nV.Cmd" name="project.info.bom_add_parts">
|
||||
<segment state="translated">
|
||||
<source>project.info.bom_add_parts</source>
|
||||
|
|
@ -7236,6 +7254,12 @@ Element 1 -> Element 1.2</target>
|
|||
<target>Price</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="bomExPrc" name="project.bom.ext_price">
|
||||
<segment state="translated">
|
||||
<source>project.bom.ext_price</source>
|
||||
<target>Extended Price</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="8tP3lQI" name="part.info.withdraw_modal.title.withdraw">
|
||||
<segment state="translated">
|
||||
<source>part.info.withdraw_modal.title.withdraw</source>
|
||||
|
|
|
|||
|
|
@ -7259,6 +7259,12 @@ Elemento 3</target>
|
|||
<target>Precio</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="bomExPrc" name="project.bom.ext_price">
|
||||
<segment state="initial">
|
||||
<source>project.bom.ext_price</source>
|
||||
<target>Extended Price</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="8tP3lQI" name="part.info.withdraw_modal.title.withdraw">
|
||||
<segment state="translated">
|
||||
<source>part.info.withdraw_modal.title.withdraw</source>
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -7198,6 +7198,12 @@
|
|||
<target>Ár</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="bomExPrc" name="project.bom.ext_price">
|
||||
<segment state="initial">
|
||||
<source>project.bom.ext_price</source>
|
||||
<target>Extended Price</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="8tP3lQI" name="part.info.withdraw_modal.title.withdraw">
|
||||
<segment state="translated">
|
||||
<source>part.info.withdraw_modal.title.withdraw</source>
|
||||
|
|
|
|||
|
|
@ -7186,6 +7186,12 @@ Element 3</target>
|
|||
<target>Prezzo</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="bomExPrc" name="project.bom.ext_price">
|
||||
<segment state="initial">
|
||||
<source>project.bom.ext_price</source>
|
||||
<target>Extended Price</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="8tP3lQI" name="part.info.withdraw_modal.title.withdraw">
|
||||
<segment state="translated">
|
||||
<source>part.info.withdraw_modal.title.withdraw</source>
|
||||
|
|
|
|||
|
|
@ -7256,6 +7256,12 @@ Element 3</target>
|
|||
<target>Cena</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="bomExPrc" name="project.bom.ext_price">
|
||||
<segment state="initial">
|
||||
<source>project.bom.ext_price</source>
|
||||
<target>Extended Price</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="8tP3lQI" name="part.info.withdraw_modal.title.withdraw">
|
||||
<segment state="translated">
|
||||
<source>part.info.withdraw_modal.title.withdraw</source>
|
||||
|
|
|
|||
|
|
@ -7260,6 +7260,12 @@
|
|||
<target>Цена</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="bomExPrc" name="project.bom.ext_price">
|
||||
<segment state="initial">
|
||||
<source>project.bom.ext_price</source>
|
||||
<target>Extended Price</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="8tP3lQI" name="part.info.withdraw_modal.title.withdraw">
|
||||
<segment state="translated">
|
||||
<source>part.info.withdraw_modal.title.withdraw</source>
|
||||
|
|
|
|||
|
|
@ -7259,6 +7259,12 @@ Element 3</target>
|
|||
<target>价格</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="bomExPrc" name="project.bom.ext_price">
|
||||
<segment state="initial">
|
||||
<source>project.bom.ext_price</source>
|
||||
<target>Extended Price</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="hO.xnng" name="part.info.withdraw_modal.title.withdraw">
|
||||
<segment state="translated">
|
||||
<source>part.info.withdraw_modal.title.withdraw</source>
|
||||
|
|
|
|||
|
|
@ -4,31 +4,31 @@
|
|||
<unit id="cRbk.cm" name="part.master_attachment.must_be_picture">
|
||||
<segment state="translated">
|
||||
<source>part.master_attachment.must_be_picture</source>
|
||||
<target>Forhåndsvisnings-bilaget skal være et rigtigt billede!</target>
|
||||
<target>Forhåndsvisningsvedhæftningen skal være et gyldigt billede!</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="v8HkcJB" name="structural.entity.unique_name">
|
||||
<segment state="translated">
|
||||
<source>structural.entity.unique_name</source>
|
||||
<target>Der eksisterer allerede et element med dette navn på dette niveau!</target>
|
||||
<target>Et element med dette navn findes allerede på dette niveau!</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="dW7b2B_" name="parameters.validator.min_lesser_typical">
|
||||
<segment state="translated">
|
||||
<source>parameters.validator.min_lesser_typical</source>
|
||||
<target>Værdi skal være mindre end eller lig med den typiske værdi ({{ compared_value }}).</target>
|
||||
<target>Værdien skal være mindre end eller lig med den typiske værdi ({{ compared_value }}).</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="Yfp2uC5" name="parameters.validator.min_lesser_max">
|
||||
<segment state="translated">
|
||||
<source>parameters.validator.min_lesser_max</source>
|
||||
<target>Værdi skal være mindre end maksumumværdien ({{ compared_value }}).</target>
|
||||
<target>Værdien skal være mindre end den maksimale værdi ({{ compared_value }}).</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="P6b.8Ou" name="parameters.validator.max_greater_typical">
|
||||
<segment state="translated">
|
||||
<source>parameters.validator.max_greater_typical</source>
|
||||
<target>Værdi skal være større eller lig med den typiske værdi ({{ compared_value }}).</target>
|
||||
<target>Værdien skal være større end eller lig med den typiske værdi ({{ compared_value }}).</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="P41193Y" name="validator.user.username_already_used">
|
||||
|
|
@ -247,5 +247,11 @@
|
|||
<target>Der er allerede defineret en oversættelse for denne type og sprog!</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="zT_j_oQ" name="validator.invalid_gtin">
|
||||
<segment state="translated">
|
||||
<source>validator.invalid_gtin</source>
|
||||
<target>Dette er ikke en gyldig GTIN / EAN!</target>
|
||||
</segment>
|
||||
</unit>
|
||||
</file>
|
||||
</xliff>
|
||||
</xliff>
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@
|
|||
<unit id="gZ5FFL1" name="part.ipn.must_be_unique">
|
||||
<segment state="translated">
|
||||
<source>part.ipn.must_be_unique</source>
|
||||
<target>Le numéro de pièce interne doit être unique.{{ value }} est déjà utilisé !</target>
|
||||
<target>Le numéro de pièce interne doit être unique. {{ value }} est déjà utilisé !</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="P31Yg.d" name="validator.project.bom_entry.name_or_part_needed">
|
||||
|
|
@ -223,13 +223,13 @@
|
|||
<target>Suite à des limitations techniques, il n'est pas possible de sélectionner une date après le 19-01-2038 sur les systèmes 32-bit !</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="89nojXY" name="validator.fileSize.invalidFormat">
|
||||
<unit id="iM9yb_p" name="validator.fileSize.invalidFormat">
|
||||
<segment state="translated">
|
||||
<source>validator.fileSize.invalidFormat</source>
|
||||
<target>Taille de fichier invalide. Utilisez un nombre avec le suffixe K, G, M pour Kilo, Mega ou Gigabytes.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="iXcU7ce" name="validator.invalid_range">
|
||||
<unit id="ZFxQ0BZ" name="validator.invalid_range">
|
||||
<segment state="translated">
|
||||
<source>validator.invalid_range</source>
|
||||
<target>L'écart fournit est invalide !</target>
|
||||
|
|
@ -241,5 +241,17 @@
|
|||
<target>Code invalide. Vérifiez que votre application d'authentification est paramétrée correctement que le serveur et périphérique d'authentification ont l'heure correcte.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="I330cr5" name="settings.synonyms.type_synonyms.collection_type.duplicate">
|
||||
<segment state="translated">
|
||||
<source>settings.synonyms.type_synonyms.collection_type.duplicate</source>
|
||||
<target>Il existe déjà une traduction définit pour ce type et langage !</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="zT_j_oQ" name="validator.invalid_gtin">
|
||||
<segment state="translated">
|
||||
<source>validator.invalid_gtin</source>
|
||||
<target>Cela n'est pas un GTIN / EAN valide !</target>
|
||||
</segment>
|
||||
</unit>
|
||||
</file>
|
||||
</xliff>
|
||||
</xliff>
|
||||
|
|
|
|||
85
yarn.lock
85
yarn.lock
|
|
@ -2174,9 +2174,9 @@
|
|||
integrity sha512-ngJMaHlsWDTfjyq9F3VIQ8b7NXbBLq5j9i5bJ6XLYtD6qlDXT7fdKY2KscWWUF8t18xx052Y/PUO1K1TRc9yKA==
|
||||
|
||||
"@simple-git/argv-parser@^1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@simple-git/argv-parser/-/argv-parser-1.1.0.tgz#6680aed3fa68f131ca0d7efa90e52b5b23ca3183"
|
||||
integrity sha512-sUKOu2lb5vGIWADNNLpscyj07DAeQZU3KLbnE2Tj53tW6BbDQKMly2CCfnR4oYzqtRELCPWfwaPg+Q0T8qfKBg==
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@simple-git/argv-parser/-/argv-parser-1.1.1.tgz#275b839c6eeb5030872c73b1ea839a416885da9d"
|
||||
integrity sha512-Q9lBcfQ+VQCpQqGJFHe5yooOS5hGdLFFbJ5R+R5aDsnkPCahtn1hSkMcORX65J2Z5lxSkD0lQorMsncuBQxYUw==
|
||||
dependencies:
|
||||
"@simple-git/args-pathspec" "^1.0.3"
|
||||
|
||||
|
|
@ -2732,9 +2732,9 @@ base64-js@^1.1.2, base64-js@^1.3.0:
|
|||
integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
|
||||
|
||||
baseline-browser-mapping@^2.10.12:
|
||||
version "2.10.18"
|
||||
resolved "https://registry.yarnpkg.com/baseline-browser-mapping/-/baseline-browser-mapping-2.10.18.tgz#565745085ba7743af7d4072707ad132db3a5a42f"
|
||||
integrity sha512-VSnGQAOLtP5mib/DPyg2/t+Tlv65NTBz83BJBJvmLVHHuKJVaDOBvJJykiT5TR++em5nfAySPccDZDa4oSrn8A==
|
||||
version "2.10.19"
|
||||
resolved "https://registry.yarnpkg.com/baseline-browser-mapping/-/baseline-browser-mapping-2.10.19.tgz#7697721c22f94f66195d0c34299b1a91e3299493"
|
||||
integrity sha512-qCkNLi2sfBOn8XhZQ0FXsT1Ki/Yo5P90hrkRamVFRS7/KV9hpfA4HkoWNU152+8w0zPjnxo5psx5NL3PSGgv5g==
|
||||
|
||||
big.js@^5.2.2:
|
||||
version "5.2.2"
|
||||
|
|
@ -2799,6 +2799,13 @@ browser-stdout@^1.3.1:
|
|||
resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60"
|
||||
integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==
|
||||
|
||||
browserify-zlib@^0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f"
|
||||
integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==
|
||||
dependencies:
|
||||
pako "~1.0.5"
|
||||
|
||||
browserslist@^4.0.0, browserslist@^4.24.0, browserslist@^4.28.1, browserslist@^4.28.2:
|
||||
version "4.28.2"
|
||||
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.28.2.tgz#f50b65362ef48974ca9f50b3680566d786b811d2"
|
||||
|
|
@ -2862,9 +2869,9 @@ caniuse-api@^3.0.0:
|
|||
lodash.uniq "^4.5.0"
|
||||
|
||||
caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001782:
|
||||
version "1.0.30001787"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001787.tgz#fd25c5e42e2d35df5c75eddda00d15d9c0c68f81"
|
||||
integrity sha512-mNcrMN9KeI68u7muanUpEejSLghOKlVhRqS/Za2IeyGllJ9I9otGpR9g3nsw7n4W378TE/LyIteA0+/FOZm4Kg==
|
||||
version "1.0.30001788"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001788.tgz#31e97d1bfec332b3f2d7eea7781460c97629b3bf"
|
||||
integrity sha512-6q8HFp+lOQtcf7wBK+uEenxymVWkGKkjFpCvw5W25cmMwEDU45p1xQFBQv8JDlMMry7eNxyBaR+qxgmTUZkIRQ==
|
||||
|
||||
ccount@^2.0.0:
|
||||
version "2.0.1"
|
||||
|
|
@ -3488,9 +3495,9 @@ domhandler@^5.0.2, domhandler@^5.0.3:
|
|||
domelementtype "^2.3.0"
|
||||
|
||||
dompurify@^3.0.3:
|
||||
version "3.3.3"
|
||||
resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-3.3.3.tgz#680cae8af3e61320ddf3666a3bc843f7b291b2b6"
|
||||
integrity sha512-Oj6pzI2+RqBfFG+qOaOLbFXLQ90ARpcGG6UePL82bJLtdsa6CYJD7nmiU8MW9nQNOtCHV3lZ/Bzq1X0QYbBZCA==
|
||||
version "3.4.0"
|
||||
resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-3.4.0.tgz#b1fc33ebdadb373241621e0a30e4ad81573dfd0b"
|
||||
integrity sha512-nolgK9JcaUXMSmW+j1yaSvaEaoXYHwWyGJlkoCTghc97KgGDDSnpoU/PlEnw63Ah+TGKFOyY+X5LnxaWbCSfXg==
|
||||
optionalDependencies:
|
||||
"@types/trusted-types" "^2.0.7"
|
||||
|
||||
|
|
@ -3518,9 +3525,9 @@ eastasianwidth@^0.2.0:
|
|||
integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==
|
||||
|
||||
electron-to-chromium@^1.5.328:
|
||||
version "1.5.335"
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.335.tgz#0b957cea44ef86795c227c616d16b4803d119daa"
|
||||
integrity sha512-q9n5T4BR4Xwa2cwbrwcsDJtHD/enpQ5S1xF1IAtdqf5AAgqDFmR/aakqH3ChFdqd/QXJhS3rnnXFtexU7rax6Q==
|
||||
version "1.5.337"
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.337.tgz#73051b9160d3960eea398d73323184cbdd6914de"
|
||||
integrity sha512-15gKW9mRUNP9RdzhedJNypFUxtYWSXohFz2nTLzM272xbRXHws68kNDzyATG3qej+vUj/7Sn9hf5XTDh0XK6/w==
|
||||
|
||||
emoji-regex@^8.0.0:
|
||||
version "8.0.0"
|
||||
|
|
@ -3854,9 +3861,9 @@ get-stream@^6.0.0:
|
|||
integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==
|
||||
|
||||
get-tsconfig@^4.10.1:
|
||||
version "4.13.7"
|
||||
resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.13.7.tgz#b9d8b199b06033ceeea1a93df7ea5765415089bc"
|
||||
integrity sha512-7tN6rFgBlMgpBML5j8typ92BKFi2sFQvIdpAqLA2beia5avZDrMs0FLZiM5etShWq5irVyGcGMEA1jcDaK7A/Q==
|
||||
version "4.14.0"
|
||||
resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.14.0.tgz#985d85c52a9903864280ccc2448d413fbf1efed8"
|
||||
integrity sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA==
|
||||
dependencies:
|
||||
resolve-pkg-maps "^1.0.0"
|
||||
|
||||
|
|
@ -4406,7 +4413,7 @@ json-formatter-js@^2.3.4:
|
|||
resolved "https://registry.yarnpkg.com/json-formatter-js/-/json-formatter-js-2.5.23.tgz#b7dd0a1da7e6cbea8e76743d7d8dc1238866cc73"
|
||||
integrity sha512-Cbm8wHXjo/C56aCePP1VuKvjxoMEmL7g7Ckss1oWFFlCsvOEEbye1kTeaNNaqba1Cl6YpIOYAnK65pUQ8mDIUQ==
|
||||
|
||||
json-parse-even-better-errors@^2.3.0, json-parse-even-better-errors@^2.3.1:
|
||||
json-parse-even-better-errors@^2.3.0:
|
||||
version "2.3.1"
|
||||
resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d"
|
||||
integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==
|
||||
|
|
@ -5062,17 +5069,10 @@ micromatch@^4.0.0, micromatch@^4.0.8:
|
|||
braces "^3.0.3"
|
||||
picomatch "^2.3.1"
|
||||
|
||||
mime-db@1.52.0:
|
||||
version "1.52.0"
|
||||
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
|
||||
integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
|
||||
|
||||
mime-types@^2.1.27:
|
||||
version "2.1.35"
|
||||
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
|
||||
integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
|
||||
dependencies:
|
||||
mime-db "1.52.0"
|
||||
mime-db@^1.54.0:
|
||||
version "1.54.0"
|
||||
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.54.0.tgz#cddb3ee4f9c64530dff640236661d42cb6a314f5"
|
||||
integrity sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==
|
||||
|
||||
mimic-fn@^2.1.0:
|
||||
version "2.1.0"
|
||||
|
|
@ -5421,7 +5421,7 @@ pako@^0.2.5:
|
|||
resolved "https://registry.yarnpkg.com/pako/-/pako-0.2.9.tgz#f3f7522f4ef782348da8161bad9ecfd51bf83a75"
|
||||
integrity sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==
|
||||
|
||||
pako@~1.0.2:
|
||||
pako@~1.0.2, pako@~1.0.5:
|
||||
version "1.0.11"
|
||||
resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf"
|
||||
integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==
|
||||
|
|
@ -5528,9 +5528,11 @@ plural-forms@^0.5.5:
|
|||
integrity sha512-rJw4xp22izsfJOVqta5Hyvep2lR3xPkFUtj7dyQtpf/FbxUiX7PQCajTn2EHDRylizH5N/Uqqodfdu22I0ju+g==
|
||||
|
||||
png-js@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/png-js/-/png-js-1.0.0.tgz#e5484f1e8156996e383aceebb3789fd75df1874d"
|
||||
integrity sha512-k+YsbhpA9e+EFfKjTCH3VW6aoKlyNYI6NYdTfDL4CIvFnvsuO84ttonmZE7rc+v23SLTH8XX+5w/Ak9v0xGY4g==
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/png-js/-/png-js-1.1.0.tgz#60a135216601f807b88a6d61ac93bd42a32c5ee1"
|
||||
integrity sha512-PM/uYGzGdNSzqeOgly68+6wKQDL1SY0a/N+OEa/+br6LnHWOAJB0Npiamnodfq3jd2LS/i2fMeOKSAILjA+m5Q==
|
||||
dependencies:
|
||||
browserify-zlib "^0.2.0"
|
||||
|
||||
pofile@^1.1.4:
|
||||
version "1.1.4"
|
||||
|
|
@ -5832,9 +5834,9 @@ postcss-value-parser@^4.0.0, postcss-value-parser@^4.1.0, postcss-value-parser@^
|
|||
integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
|
||||
|
||||
postcss@^8.0.0, postcss@^8.2.14, postcss@^8.4.12, postcss@^8.4.40:
|
||||
version "8.5.9"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.9.tgz#f6ee9e0b94f0f19c97d2f172bfbd7fc71fe1cca4"
|
||||
integrity sha512-7a70Nsot+EMX9fFU3064K/kdHWZqGVY+BADLyXc8Dfv+mTLLVl6JzJpPaCZ2kQL9gIJvKXSLMHhqdRRjwQeFtw==
|
||||
version "8.5.10"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.10.tgz#8992d8c30acf3f12169e7c09514a12fed7e48356"
|
||||
integrity sha512-pMMHxBOZKFU6HgAZ4eyGnwXF/EvPGGqUr0MnZ5+99485wwW41kW91A4LOGxSHhgugZmSChL5AlElNdwlNgcnLQ==
|
||||
dependencies:
|
||||
nanoid "^3.3.11"
|
||||
picocolors "^1.1.1"
|
||||
|
|
@ -6938,9 +6940,9 @@ webpack-sources@^3.0.0, webpack-sources@^3.3.4:
|
|||
integrity sha512-7tP1PdV4vF+lYPnkMR0jMY5/la2ub5Fc/8VQrrU+lXkiM6C4TjVfGw7iKfyhnTQOsD+6Q/iKw0eFciziRgD58Q==
|
||||
|
||||
webpack@^5.74.0:
|
||||
version "5.106.1"
|
||||
resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.106.1.tgz#0a3eeb43a50e4f67fbecd206e1e6fc2c89fc2b6f"
|
||||
integrity sha512-EW8af29ak8Oaf4T8k8YsajjrDBDYgnKZ5er6ljWFJsXABfTNowQfvHLftwcepVgdz+IoLSdEAbBiM9DFXoll9w==
|
||||
version "5.106.2"
|
||||
resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.106.2.tgz#ca8174b4fd80f055cc5a45fcc5577d6db76c8ac5"
|
||||
integrity sha512-wGN3qcrBQIFmQ/c0AiOAQBvrZ5lmY8vbbMv4Mxfgzqd/B6+9pXtLo73WuS1dSGXM5QYY3hZnIbvx+K1xxe6FyA==
|
||||
dependencies:
|
||||
"@types/eslint-scope" "^3.7.7"
|
||||
"@types/estree" "^1.0.8"
|
||||
|
|
@ -6958,9 +6960,8 @@ webpack@^5.74.0:
|
|||
events "^3.2.0"
|
||||
glob-to-regexp "^0.4.1"
|
||||
graceful-fs "^4.2.11"
|
||||
json-parse-even-better-errors "^2.3.1"
|
||||
loader-runner "^4.3.1"
|
||||
mime-types "^2.1.27"
|
||||
mime-db "^1.54.0"
|
||||
neo-async "^2.6.2"
|
||||
schema-utils "^4.3.3"
|
||||
tapable "^2.3.0"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue