mirror of
https://github.com/Part-DB/Part-DB-server.git
synced 2026-07-30 21:21:42 +00:00
Compare commits
17 commits
3db982b60e
...
a2307b5b07
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a2307b5b07 | ||
|
|
98df91d785 | ||
|
|
bffb2c1d70 | ||
|
|
d44ce85d89 | ||
|
|
12f4a3606e | ||
|
|
192c5fcaa3 | ||
|
|
63d507b2f3 | ||
|
|
ef7e6d6f3b | ||
|
|
350e5a0245 | ||
|
|
704f7e7645 | ||
|
|
589f420b79 | ||
|
|
dfbdac7688 | ||
|
|
11b41ee66a | ||
|
|
c9dd27712c | ||
|
|
8421636b1c | ||
|
|
b357ee196c | ||
|
|
0c5f8dc9fd |
28 changed files with 540 additions and 348 deletions
10
.env
10
.env
|
|
@ -149,6 +149,16 @@ DISABLE_YEAR2038_BUG_CHECK=0
|
|||
#TRUSTED_PROXIES=127.0.0.0/8,::1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16
|
||||
#TRUSTED_HOSTS='^(localhost|example\.com)$'
|
||||
|
||||
###################################################################################
|
||||
# Logging settings
|
||||
###################################################################################
|
||||
|
||||
# The minimum level a deprecation notice must have to be written to the var/log/<env>_deprecations.log file.
|
||||
# Deprecation notices are logged with level "info", so this disables the deprecation log by default.
|
||||
# Set to debug to log all deprecation notices
|
||||
DEPRECATION_LOG_LEVEL=emergency
|
||||
|
||||
|
||||
|
||||
###> symfony/lock ###
|
||||
# Choose one of the stores below
|
||||
|
|
|
|||
2
.github/workflows/tests.yml
vendored
2
.github/workflows/tests.yml
vendored
|
|
@ -129,7 +129,7 @@ jobs:
|
|||
run: ./bin/phpunit --coverage-clover=coverage.xml
|
||||
|
||||
- name: Upload coverage
|
||||
uses: codecov/codecov-action@v6
|
||||
uses: codecov/codecov-action@v7
|
||||
with:
|
||||
env_vars: PHP_VERSION,DB_TYPE
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
|
|
|||
2
VERSION
2
VERSION
|
|
@ -1 +1 @@
|
|||
2.12.1
|
||||
2.12.2
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ export default class extends Controller {
|
|||
|
||||
//Make the state persistent over reloads
|
||||
if(localStorage.getItem(STORAGE_KEY) === 'true') {
|
||||
sidebarHide();
|
||||
this.hideSidebar();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@
|
|||
"symfony/flex": "^v2.3.1",
|
||||
"symfony/form": "7.4.*",
|
||||
"symfony/framework-bundle": "7.4.*",
|
||||
"symfony/html-sanitizer": "7.4.*",
|
||||
"symfony/http-client": "7.4.*",
|
||||
"symfony/http-kernel": "7.4.*",
|
||||
"symfony/mailer": "7.4.*",
|
||||
|
|
|
|||
424
composer.lock
generated
424
composer.lock
generated
File diff suppressed because it is too large
Load diff
|
|
@ -51,6 +51,7 @@ when@prod:
|
|||
type: stream
|
||||
channels: [deprecation]
|
||||
path: "%kernel.logs_dir%/%kernel.environment%_deprecations.log"
|
||||
level: "%env(DEPRECATION_LOG_LEVEL)%"
|
||||
|
||||
when@docker:
|
||||
monolog:
|
||||
|
|
@ -75,3 +76,4 @@ when@docker:
|
|||
type: stream
|
||||
channels: [deprecation]
|
||||
path: "%kernel.logs_dir%/%kernel.environment%_deprecations.log"
|
||||
level: "%env(DEPRECATION_LOG_LEVEL)%"
|
||||
|
|
|
|||
|
|
@ -653,7 +653,7 @@ use Symfony\Component\Config\Loader\ParamConfigurator as Param;
|
|||
* time_based_uuid_node?: scalar|Param|null,
|
||||
* },
|
||||
* html_sanitizer?: bool|array{ // HtmlSanitizer configuration
|
||||
* enabled?: bool|Param, // Default: false
|
||||
* enabled?: bool|Param, // Default: true
|
||||
* sanitizers?: array<string, array{ // Default: []
|
||||
* allow_safe_elements?: bool|Param, // Allows "safe" elements and attributes. // Default: false
|
||||
* allow_static_elements?: bool|Param, // Allows all static elements and attributes from the W3C Sanitizer API standard. // Default: false
|
||||
|
|
@ -718,7 +718,7 @@ use Symfony\Component\Config\Loader\ParamConfigurator as Param;
|
|||
* servicename?: scalar|Param|null, // Overrules dbname parameter if given and used as SERVICE_NAME or SID connection parameter for Oracle depending on the service parameter.
|
||||
* sessionMode?: scalar|Param|null, // The session mode to use for the oci8 driver
|
||||
* server?: scalar|Param|null, // The name of a running database server to connect to for SQL Anywhere.
|
||||
* default_dbname?: scalar|Param|null, // Override the default database (postgres) to connect to for PostgreSQL connexion.
|
||||
* default_dbname?: scalar|Param|null, // Override the default database (postgres) to connect to for PostgreSQL connection.
|
||||
* sslmode?: scalar|Param|null, // Determines whether or with what priority a SSL TCP/IP connection will be negotiated with the server for PostgreSQL.
|
||||
* sslrootcert?: scalar|Param|null, // The name of a file containing SSL certificate authority (CA) certificate(s). If the file exists, the server's certificate will be verified to be signed by one of these authorities.
|
||||
* sslcert?: scalar|Param|null, // The path to the SSL client certificate file for PostgreSQL.
|
||||
|
|
@ -769,7 +769,7 @@ use Symfony\Component\Config\Loader\ParamConfigurator as Param;
|
|||
* servicename?: scalar|Param|null, // Overrules dbname parameter if given and used as SERVICE_NAME or SID connection parameter for Oracle depending on the service parameter.
|
||||
* sessionMode?: scalar|Param|null, // The session mode to use for the oci8 driver
|
||||
* server?: scalar|Param|null, // The name of a running database server to connect to for SQL Anywhere.
|
||||
* default_dbname?: scalar|Param|null, // Override the default database (postgres) to connect to for PostgreSQL connexion.
|
||||
* default_dbname?: scalar|Param|null, // Override the default database (postgres) to connect to for PostgreSQL connection.
|
||||
* sslmode?: scalar|Param|null, // Determines whether or with what priority a SSL TCP/IP connection will be negotiated with the server for PostgreSQL.
|
||||
* sslrootcert?: scalar|Param|null, // The name of a file containing SSL certificate authority (CA) certificate(s). If the file exists, the server's certificate will be verified to be signed by one of these authorities.
|
||||
* sslcert?: scalar|Param|null, // The path to the SSL client certificate file for PostgreSQL.
|
||||
|
|
@ -801,7 +801,7 @@ use Symfony\Component\Config\Loader\ParamConfigurator as Param;
|
|||
* servicename?: scalar|Param|null, // Overrules dbname parameter if given and used as SERVICE_NAME or SID connection parameter for Oracle depending on the service parameter.
|
||||
* sessionMode?: scalar|Param|null, // The session mode to use for the oci8 driver
|
||||
* server?: scalar|Param|null, // The name of a running database server to connect to for SQL Anywhere.
|
||||
* default_dbname?: scalar|Param|null, // Override the default database (postgres) to connect to for PostgreSQL connexion.
|
||||
* default_dbname?: scalar|Param|null, // Override the default database (postgres) to connect to for PostgreSQL connection.
|
||||
* sslmode?: scalar|Param|null, // Determines whether or with what priority a SSL TCP/IP connection will be negotiated with the server for PostgreSQL.
|
||||
* sslrootcert?: scalar|Param|null, // The name of a file containing SSL certificate authority (CA) certificate(s). If the file exists, the server's certificate will be verified to be signed by one of these authorities.
|
||||
* sslcert?: scalar|Param|null, // The path to the SSL client certificate file for PostgreSQL.
|
||||
|
|
|
|||
|
|
@ -279,9 +279,13 @@ See the [information providers]({% link usage/information_provider_system.md %})
|
|||
* `BANNER`: You can configure the text that should be shown as the banner on the homepage. Useful especially for docker
|
||||
containers. In all other applications you can just change the `config/banner.md` file.
|
||||
* `DISABLE_YEAR2038_BUG_CHECK` (env only): If set to `1`, the year 2038 bug check is disabled on 32-bit systems, and dates after
|
||||
2038 are no longer forbidden. However this will lead to 500 error messages when rendering dates after 2038 as all current
|
||||
2038 are no longer forbidden. However, this will lead to 500 error messages when rendering dates after 2038 as all current
|
||||
32-bit PHP versions can not format these dates correctly. This setting is for the case that future PHP versions will
|
||||
handle this correctly on 32-bit systems. 64-bit systems are not affected by this bug, and the check is always disabled.
|
||||
* `DEPRECATION_LOG_LEVEL` (default `emergency`) (env only): In the `prod` and `docker` environments, PHP/Symfony
|
||||
deprecation notices are written to their own `var/log/<env>_deprecations.log` file. This option sets the minimum log
|
||||
level a deprecation notice must have to be written there. Since deprecation notices are logged with level `info`,
|
||||
the default value of `emergency` effectively disables this dedicated deprecation log. Set it to `debug` to enable it.
|
||||
|
||||
## Banner
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# Generated on Mon Jun 1 07:07:44 UTC 2026
|
||||
# Generated on Mon Jun 15 07:28:00 UTC 2026
|
||||
# This file contains all footprints available in the offical KiCAD library
|
||||
Audio_Module:Reverb_BTDR-1H
|
||||
Audio_Module:Reverb_BTDR-1V
|
||||
|
|
@ -12012,7 +12012,6 @@ Package_DFN_QFN:WDFN-8-1EP_4x3mm_P0.65mm_EP2.4x1.8mm_ThermalVias
|
|||
Package_DFN_QFN:WDFN-8-1EP_6x5mm_P1.27mm_EP3.4x4mm
|
||||
Package_DFN_QFN:WDFN-8-1EP_8x6mm_P1.27mm_EP6x4.8mm
|
||||
Package_DFN_QFN:WDFN-8-1EP_8x6mm_P1.27mm_EP6x4.8mm_ThermalVias
|
||||
Package_DFN_QFN:WDFN-8_2x2mm_P0.5mm
|
||||
Package_DFN_QFN:WFDFPN-8-1EP_3x2mm_P0.5mm_EP1.25x1.35mm
|
||||
Package_DFN_QFN:WQFN-14-1EP_2.5x2.5mm_P0.5mm_EP1.45x1.45mm
|
||||
Package_DFN_QFN:WQFN-14-1EP_2.5x2.5mm_P0.5mm_EP1.45x1.45mm_ThermalVias
|
||||
|
|
@ -12358,7 +12357,6 @@ Package_DirectFET:DirectFET_SQ
|
|||
Package_DirectFET:DirectFET_ST
|
||||
Package_LCC:Analog_LCC-8_5x5mm_P1.27mm
|
||||
Package_LCC:MO047AD_PLCC-52_19.1x19.1mm_P1.27mm
|
||||
Package_LCC:PLCC-20
|
||||
Package_LCC:PLCC-20_9.0x9.0mm_P1.27mm
|
||||
Package_LCC:PLCC-20_SMD-Socket
|
||||
Package_LCC:PLCC-20_THT-Socket
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# Generated on Mon Jun 1 07:08:24 UTC 2026
|
||||
# Generated on Mon Jun 15 07:28:38 UTC 2026
|
||||
# This file contains all symbols available in the offical KiCAD library
|
||||
4xxx:14528
|
||||
4xxx:14529
|
||||
|
|
@ -5300,21 +5300,39 @@ Converter_DCDC:TMR-4812
|
|||
Converter_DCDC:TMR-4821
|
||||
Converter_DCDC:TMR-4822
|
||||
Converter_DCDC:TMR-4823
|
||||
Converter_DCDC:TMR10-1211WI
|
||||
Converter_DCDC:TMR10-1212WI
|
||||
Converter_DCDC:TMR10-1213WI
|
||||
Converter_DCDC:TMR10-1215WI
|
||||
Converter_DCDC:TMR10-1222WI
|
||||
Converter_DCDC:TMR10-1223WI
|
||||
Converter_DCDC:TMR10-2410WIR
|
||||
Converter_DCDC:TMR10-2411WI
|
||||
Converter_DCDC:TMR10-2411WIR
|
||||
Converter_DCDC:TMR10-2412WI
|
||||
Converter_DCDC:TMR10-2412WIR
|
||||
Converter_DCDC:TMR10-2413WI
|
||||
Converter_DCDC:TMR10-2413WIR
|
||||
Converter_DCDC:TMR10-2415WI
|
||||
Converter_DCDC:TMR10-2415WIR
|
||||
Converter_DCDC:TMR10-2421WIR
|
||||
Converter_DCDC:TMR10-2422WI
|
||||
Converter_DCDC:TMR10-2422WIR
|
||||
Converter_DCDC:TMR10-2423WI
|
||||
Converter_DCDC:TMR10-2423WIR
|
||||
Converter_DCDC:TMR10-4810WIR
|
||||
Converter_DCDC:TMR10-4811WI
|
||||
Converter_DCDC:TMR10-4811WIR
|
||||
Converter_DCDC:TMR10-4812WI
|
||||
Converter_DCDC:TMR10-4812WIR
|
||||
Converter_DCDC:TMR10-4813WI
|
||||
Converter_DCDC:TMR10-4813WIR
|
||||
Converter_DCDC:TMR10-4815WI
|
||||
Converter_DCDC:TMR10-4815WIR
|
||||
Converter_DCDC:TMR10-4821WIR
|
||||
Converter_DCDC:TMR10-4822WI
|
||||
Converter_DCDC:TMR10-4822WIR
|
||||
Converter_DCDC:TMR10-4823WI
|
||||
Converter_DCDC:TMR10-4823WIR
|
||||
Converter_DCDC:TMR10-7210WIR
|
||||
Converter_DCDC:TMR10-7211WIR
|
||||
|
|
@ -14593,6 +14611,8 @@ MCU_Texas:LM4F111C4QR
|
|||
MCU_Texas:LM4F111E5QR
|
||||
MCU_Texas:LM4F111H5QR
|
||||
MCU_Texas:MSP432E401Y
|
||||
MCU_Texas:MSPM0C110xSDDF
|
||||
MCU_Texas:MSPM0C110xSDSG
|
||||
MCU_Texas:TM4C1230C3PM
|
||||
MCU_Texas:TM4C1230D5PM
|
||||
MCU_Texas:TM4C1230E6PM
|
||||
|
|
@ -15115,6 +15135,7 @@ Memory_Flash:AM29F400Bx-xxEx
|
|||
Memory_Flash:AM29F400Bx-xxSx
|
||||
Memory_Flash:AM29PDL128G
|
||||
Memory_Flash:AT25DF041x-UxN-x
|
||||
Memory_Flash:AT25SF041B-SSHD-X
|
||||
Memory_Flash:AT25SF081-SSHD-X
|
||||
Memory_Flash:AT25SF081-SSHF-X
|
||||
Memory_Flash:AT25SF081-XMHD-X
|
||||
|
|
@ -15670,6 +15691,7 @@ Power_Management:LM5069MM-1
|
|||
Power_Management:LM5069MM-2
|
||||
Power_Management:LM66100DCK
|
||||
Power_Management:LM74700
|
||||
Power_Management:LM74701-Q1
|
||||
Power_Management:LMG3410
|
||||
Power_Management:LMG5200
|
||||
Power_Management:LT1641-1
|
||||
|
|
@ -15771,6 +15793,7 @@ Power_Management:TPS22810DBV
|
|||
Power_Management:TPS22810DRV
|
||||
Power_Management:TPS22917DBV
|
||||
Power_Management:TPS22917LDBV
|
||||
Power_Management:TPS22919DCK
|
||||
Power_Management:TPS22929D
|
||||
Power_Management:TPS22993
|
||||
Power_Management:TPS2412D
|
||||
|
|
@ -16480,6 +16503,7 @@ RF_Module:DWM3000
|
|||
RF_Module:E18-MS1-PCB
|
||||
RF_Module:E73-2G4M04S-52810
|
||||
RF_Module:E73-2G4M04S-52832
|
||||
RF_Module:ESP-01
|
||||
RF_Module:ESP-07
|
||||
RF_Module:ESP-12E
|
||||
RF_Module:ESP-12F
|
||||
|
|
@ -16681,6 +16705,19 @@ Reference_Voltage:LM4040LP-4.1
|
|||
Reference_Voltage:LM4040LP-5
|
||||
Reference_Voltage:LM4040LP-8.2
|
||||
Reference_Voltage:LM4041LP-ADJ
|
||||
Reference_Voltage:LM4050xEM3-2.1
|
||||
Reference_Voltage:LM4050xEM3-2.5
|
||||
Reference_Voltage:LM4050xEM3-3.0
|
||||
Reference_Voltage:LM4050xEM3-3.3
|
||||
Reference_Voltage:LM4050xEM3-4.1
|
||||
Reference_Voltage:LM4050xEM3-5.0
|
||||
Reference_Voltage:LM4050xEX3-2.1
|
||||
Reference_Voltage:LM4050xEX3-2.5
|
||||
Reference_Voltage:LM4050xEX3-3.3
|
||||
Reference_Voltage:LM4050xEX3-4.1
|
||||
Reference_Voltage:LM4050xEX3-5.0
|
||||
Reference_Voltage:LM4051xEM3-1.2
|
||||
Reference_Voltage:LM4051xEX3-1.2
|
||||
Reference_Voltage:LM4125AIM5-2.5
|
||||
Reference_Voltage:LM4125IM5-2.0
|
||||
Reference_Voltage:LM4125IM5-2.5
|
||||
|
|
@ -16828,7 +16865,6 @@ Reference_Voltage:MCP1501-25xCH
|
|||
Reference_Voltage:MCP1501-25xRW
|
||||
Reference_Voltage:MCP1501-25xSN
|
||||
Reference_Voltage:MCP1501-30xCH
|
||||
Reference_Voltage:MCP1501-30xRW
|
||||
Reference_Voltage:MCP1501-30xSN
|
||||
Reference_Voltage:MCP1501-33xCH
|
||||
Reference_Voltage:MCP1501-33xRW
|
||||
|
|
@ -20989,6 +21025,7 @@ Sensor_Temperature:MCP9501
|
|||
Sensor_Temperature:MCP9502
|
||||
Sensor_Temperature:MCP9503
|
||||
Sensor_Temperature:MCP9504
|
||||
Sensor_Temperature:MCP96xx01x-x-MX
|
||||
Sensor_Temperature:MCP9700Ax-ELT
|
||||
Sensor_Temperature:MCP9700Ax-ETT
|
||||
Sensor_Temperature:MCP9700Ax-HLT
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Controller;
|
||||
|
||||
use Symfony\Bridge\Doctrine\Attribute\MapEntity;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use App\Entity\ProjectSystem\Project;
|
||||
use App\Entity\Parts\Category;
|
||||
|
|
@ -55,7 +56,7 @@ class TreeController extends AbstractController
|
|||
|
||||
#[Route(path: '/category/{id}', name: 'tree_category')]
|
||||
#[Route(path: '/categories', name: 'tree_category_root')]
|
||||
public function categoryTree(?Category $category = null): JsonResponse
|
||||
public function categoryTree(#[MapEntity(id: 'id')] ?Category $category = null): JsonResponse
|
||||
{
|
||||
if ($this->isGranted('@parts.read') && $this->isGranted('@categories.read')) {
|
||||
$tree = $this->treeGenerator->getTreeView(Category::class, $category, 'list_parts_root');
|
||||
|
|
@ -68,7 +69,7 @@ class TreeController extends AbstractController
|
|||
|
||||
#[Route(path: '/footprint/{id}', name: 'tree_footprint')]
|
||||
#[Route(path: '/footprints', name: 'tree_footprint_root')]
|
||||
public function footprintTree(?Footprint $footprint = null): JsonResponse
|
||||
public function footprintTree(#[MapEntity(id: 'id')] ?Footprint $footprint = null): JsonResponse
|
||||
{
|
||||
if ($this->isGranted('@parts.read') && $this->isGranted('@footprints.read')) {
|
||||
$tree = $this->treeGenerator->getTreeView(Footprint::class, $footprint, 'list_parts_root');
|
||||
|
|
@ -80,7 +81,7 @@ class TreeController extends AbstractController
|
|||
|
||||
#[Route(path: '/location/{id}', name: 'tree_location')]
|
||||
#[Route(path: '/locations', name: 'tree_location_root')]
|
||||
public function locationTree(?StorageLocation $location = null): JsonResponse
|
||||
public function locationTree(#[MapEntity(id: 'id')] ?StorageLocation $location = null): JsonResponse
|
||||
{
|
||||
if ($this->isGranted('@parts.read') && $this->isGranted('@storelocations.read')) {
|
||||
$tree = $this->treeGenerator->getTreeView(StorageLocation::class, $location, 'list_parts_root');
|
||||
|
|
@ -93,7 +94,7 @@ class TreeController extends AbstractController
|
|||
|
||||
#[Route(path: '/manufacturer/{id}', name: 'tree_manufacturer')]
|
||||
#[Route(path: '/manufacturers', name: 'tree_manufacturer_root')]
|
||||
public function manufacturerTree(?Manufacturer $manufacturer = null): JsonResponse
|
||||
public function manufacturerTree(#[MapEntity(id: 'id')] ?Manufacturer $manufacturer = null): JsonResponse
|
||||
{
|
||||
if ($this->isGranted('@parts.read') && $this->isGranted('@manufacturers.read')) {
|
||||
$tree = $this->treeGenerator->getTreeView(Manufacturer::class, $manufacturer, 'list_parts_root');
|
||||
|
|
@ -106,7 +107,7 @@ class TreeController extends AbstractController
|
|||
|
||||
#[Route(path: '/supplier/{id}', name: 'tree_supplier')]
|
||||
#[Route(path: '/suppliers', name: 'tree_supplier_root')]
|
||||
public function supplierTree(?Supplier $supplier = null): JsonResponse
|
||||
public function supplierTree(#[MapEntity(id: 'id')] ?Supplier $supplier = null): JsonResponse
|
||||
{
|
||||
if ($this->isGranted('@parts.read') && $this->isGranted('@suppliers.read')) {
|
||||
$tree = $this->treeGenerator->getTreeView(Supplier::class, $supplier, 'list_parts_root');
|
||||
|
|
@ -119,7 +120,7 @@ class TreeController extends AbstractController
|
|||
|
||||
#[Route(path: '/device/{id}', name: 'tree_device')]
|
||||
#[Route(path: '/devices', name: 'tree_device_root')]
|
||||
public function deviceTree(?Project $device = null): JsonResponse
|
||||
public function deviceTree(#[MapEntity(id: 'id')] ?Project $device = null): JsonResponse
|
||||
{
|
||||
if ($this->isGranted('@projects.read')) {
|
||||
$tree = $this->treeGenerator->getTreeView(Project::class, $device, 'devices');
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\DataTables;
|
||||
|
||||
use App\DataTables\Column\HTMLColumn;
|
||||
use App\DataTables\Column\LocaleDateTimeColumn;
|
||||
use App\DataTables\Column\PrettyBoolColumn;
|
||||
use App\DataTables\Column\RowClassColumn;
|
||||
|
|
@ -40,14 +41,19 @@ use Omines\DataTablesBundle\DataTable;
|
|||
use Omines\DataTablesBundle\DataTableTypeInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
final class AttachmentDataTable implements DataTableTypeInterface
|
||||
final readonly class AttachmentDataTable implements DataTableTypeInterface
|
||||
{
|
||||
public function __construct(private readonly TranslatorInterface $translator, private readonly EntityURLGenerator $entityURLGenerator, private readonly AttachmentManager $attachmentHelper, private readonly AttachmentURLGenerator $attachmentURLGenerator, private readonly ElementTypeNameGenerator $elementTypeNameGenerator)
|
||||
public function __construct(private TranslatorInterface $translator, private EntityURLGenerator $entityURLGenerator, private AttachmentManager $attachmentHelper, private AttachmentURLGenerator $attachmentURLGenerator, private ElementTypeNameGenerator $elementTypeNameGenerator)
|
||||
{
|
||||
}
|
||||
|
||||
public function configure(DataTable $dataTable, array $options): void
|
||||
{
|
||||
/*************************************************************************************************************
|
||||
* Avoid using render, as it has no escaping, and is a potential security risk. Use data on TextColumn or the
|
||||
* HTMLColumn, if necessary
|
||||
************************************************************************************************************/
|
||||
|
||||
$dataTable->add('dont_matter', RowClassColumn::class, [
|
||||
'render' => function ($value, Attachment $context): string {
|
||||
//Mark attachments yellow which have an internal file linked that doesn't exist
|
||||
|
|
@ -59,10 +65,10 @@ final class AttachmentDataTable implements DataTableTypeInterface
|
|||
},
|
||||
]);
|
||||
|
||||
$dataTable->add('picture', TextColumn::class, [
|
||||
$dataTable->add('picture', HTMLColumn::class, [
|
||||
'label' => '',
|
||||
'className' => 'no-colvis',
|
||||
'render' => function ($value, Attachment $context): string {
|
||||
'data' => function (Attachment $context): string {
|
||||
if ($context->isPicture()
|
||||
&& $this->attachmentHelper->isInternalFileExisting($context)) {
|
||||
|
||||
|
|
@ -95,65 +101,65 @@ final class AttachmentDataTable implements DataTableTypeInterface
|
|||
'orderField' => 'NATSORT(attachment.name)',
|
||||
]);
|
||||
|
||||
$dataTable->add('attachment_type', TextColumn::class, [
|
||||
$dataTable->add('attachment_type', HTMLColumn::class, [
|
||||
'label' => 'attachment.table.type',
|
||||
'field' => 'attachment_type.name',
|
||||
'orderField' => 'NATSORT(attachment_type.name)',
|
||||
'render' => fn($value, Attachment $context): string => sprintf(
|
||||
'data' => fn(Attachment $context, $value): string => sprintf(
|
||||
'<a href="%s">%s</a>',
|
||||
$this->entityURLGenerator->editURL($context->getAttachmentType()),
|
||||
htmlspecialchars((string) $value)
|
||||
),
|
||||
]);
|
||||
|
||||
$dataTable->add('element', TextColumn::class, [
|
||||
$dataTable->add('element', HTMLColumn::class, [
|
||||
'label' => 'attachment.table.element',
|
||||
//'propertyPath' => 'element.name',
|
||||
'render' => fn($value, Attachment $context): string => sprintf(
|
||||
'data' => fn(Attachment $context): string => sprintf(
|
||||
'<a href="%s">%s</a>',
|
||||
$this->entityURLGenerator->infoURL($context->getElement()),
|
||||
$this->elementTypeNameGenerator->getTypeNameCombination($context->getElement(), true)
|
||||
),
|
||||
]);
|
||||
|
||||
$dataTable->add('internal_link', TextColumn::class, [
|
||||
$dataTable->add('internal_link', HTMLColumn::class, [
|
||||
'label' => 'attachment.table.internal_file',
|
||||
'propertyPath' => 'filename',
|
||||
'orderField' => 'NATSORT(attachment.original_filename)',
|
||||
'render' => function ($value, Attachment $context) {
|
||||
'data' => function (Attachment $context, $value) {
|
||||
if ($this->attachmentHelper->isInternalFileExisting($context)) {
|
||||
return sprintf(
|
||||
'<a href="%s" target="_blank" data-no-ajax>%s</a>',
|
||||
$this->entityURLGenerator->viewURL($context),
|
||||
htmlspecialchars($value)
|
||||
htmlspecialchars((string) $value)
|
||||
);
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
return htmlspecialchars((string) $value);
|
||||
},
|
||||
]);
|
||||
|
||||
$dataTable->add('external_link', TextColumn::class, [
|
||||
$dataTable->add('external_link', HTMLColumn::class, [
|
||||
'label' => 'attachment.table.external_link',
|
||||
'propertyPath' => 'host',
|
||||
'orderField' => 'attachment.external_path',
|
||||
'render' => function ($value, Attachment $context) {
|
||||
'data' => function (Attachment $context, $value) {
|
||||
if ($context->hasExternal()) {
|
||||
return sprintf(
|
||||
'<a href="%s" class="link-external" title="%s" target="_blank" rel="noopener">%s</a>',
|
||||
htmlspecialchars((string) $context->getExternalPath()),
|
||||
htmlspecialchars((string) $context->getExternalPath()),
|
||||
htmlspecialchars($value),
|
||||
htmlspecialchars((string) $value),
|
||||
);
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
return htmlspecialchars((string) $value);
|
||||
},
|
||||
]);
|
||||
|
||||
$dataTable->add('filesize', TextColumn::class, [
|
||||
$dataTable->add('filesize', HTMLColumn::class, [
|
||||
'label' => $this->translator->trans('attachment.table.filesize'),
|
||||
'render' => function ($value, Attachment $context) {
|
||||
'data' => function (Attachment $context) {
|
||||
if (!$context->hasInternal()) {
|
||||
return sprintf(
|
||||
'<span class="badge bg-primary">
|
||||
|
|
@ -168,7 +174,7 @@ final class AttachmentDataTable implements DataTableTypeInterface
|
|||
'<span class="badge bg-secondary">
|
||||
<i class="fas fa-hdd fa-fw"></i> %s
|
||||
</span>',
|
||||
$this->attachmentHelper->getHumanFileSize($context)
|
||||
htmlspecialchars($this->attachmentHelper->getHumanFileSize($context))
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ class EntityColumn extends AbstractColumn
|
|||
);
|
||||
}
|
||||
|
||||
return sprintf('<i>%s</i>', $value);
|
||||
return sprintf('<i>%s</i>', htmlspecialchars($value));
|
||||
}
|
||||
|
||||
return '';
|
||||
|
|
|
|||
37
src/DataTables/Column/HTMLColumn.php
Normal file
37
src/DataTables/Column/HTMLColumn.php
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
namespace App\DataTables\Column;
|
||||
|
||||
use Omines\DataTablesBundle\Column\TextColumn;
|
||||
|
||||
/**
|
||||
* A TextColumn whose value is always treated as raw HTML and therefore never passed through htmlspecialchars().
|
||||
* The value returned by the 'data' option must already contain properly escaped/sanitized HTML, as it is output as-is.
|
||||
*/
|
||||
class HTMLColumn extends TextColumn
|
||||
{
|
||||
public function isRaw(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -87,9 +87,9 @@ class IconLinkColumn extends AbstractColumn
|
|||
return sprintf(
|
||||
'<a class="btn btn-primary btn-sm %s" href="%s" title="%s"><i class="%s"></i></a>',
|
||||
$disabled ? 'disabled' : '',
|
||||
$href,
|
||||
$title,
|
||||
$icon
|
||||
htmlspecialchars($href),
|
||||
htmlspecialchars($title ?? ''),
|
||||
htmlspecialchars($icon ?? '')
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,9 +22,9 @@ declare(strict_types=1);
|
|||
*/
|
||||
namespace App\DataTables;
|
||||
|
||||
use App\DataTables\Column\HTMLColumn;
|
||||
use App\DataTables\Column\RowClassColumn;
|
||||
use Omines\DataTablesBundle\Adapter\ArrayAdapter;
|
||||
use Omines\DataTablesBundle\Column\TextColumn;
|
||||
use Omines\DataTablesBundle\DataTable;
|
||||
use Omines\DataTablesBundle\DataTableFactory;
|
||||
use Omines\DataTablesBundle\DataTableTypeInterface;
|
||||
|
|
@ -32,7 +32,7 @@ use Symfony\Component\HttpFoundation\Request;
|
|||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
class ErrorDataTable implements DataTableTypeInterface
|
||||
final readonly class ErrorDataTable implements DataTableTypeInterface
|
||||
{
|
||||
public function configureOptions(OptionsResolver $optionsResolver): void
|
||||
{
|
||||
|
|
@ -49,6 +49,11 @@ class ErrorDataTable implements DataTableTypeInterface
|
|||
|
||||
public function configure(DataTable $dataTable, array $options): void
|
||||
{
|
||||
/*************************************************************************************************************
|
||||
* Avoid using render, as it has no escaping, and is a potential security risk. Use data on TextColumn or the
|
||||
* HTMLColumn, if necessary
|
||||
************************************************************************************************************/
|
||||
|
||||
$optionsResolver = new OptionsResolver();
|
||||
$this->configureOptions($optionsResolver);
|
||||
$options = $optionsResolver->resolve($options);
|
||||
|
|
@ -58,9 +63,9 @@ class ErrorDataTable implements DataTableTypeInterface
|
|||
'render' => fn($value, $context): string => 'table-warning',
|
||||
])
|
||||
|
||||
->add('error', TextColumn::class, [
|
||||
->add('error', HTMLColumn::class, [
|
||||
'label' => 'error_table.error',
|
||||
'render' => fn($value, $context): string => '<i class="fa-solid fa-triangle-exclamation fa-fw"></i> ' . $value,
|
||||
'data' => fn($context, $value): string => '<i class="fa-solid fa-triangle-exclamation fa-fw"></i> ' . htmlspecialchars((string) $value),
|
||||
])
|
||||
;
|
||||
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ class PartDataTableHelper
|
|||
}
|
||||
if ($context->getBuiltProject() instanceof Project) {
|
||||
$icon = sprintf('<i class="fa-solid fa-box-archive fa-fw me-1" title="%s"></i>',
|
||||
$this->translator->trans('part.info.projectBuildPart.hint').': '.$context->getBuiltProject()->getName());
|
||||
$this->translator->trans('part.info.projectBuildPart.hint').': '.htmlspecialchars($context->getBuiltProject()->getName()));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ namespace App\DataTables;
|
|||
use App\DataTables\Column\EnumColumn;
|
||||
use App\Entity\LogSystem\LogTargetType;
|
||||
use Symfony\Bundle\SecurityBundle\Security;
|
||||
use App\DataTables\Column\HTMLColumn;
|
||||
use App\DataTables\Column\IconLinkColumn;
|
||||
use App\DataTables\Column\LocaleDateTimeColumn;
|
||||
use App\DataTables\Column\LogEntryExtraColumn;
|
||||
|
|
@ -59,7 +60,7 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
|
|||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
class LogDataTable implements DataTableTypeInterface
|
||||
final readonly class LogDataTable implements DataTableTypeInterface
|
||||
{
|
||||
protected LogEntryRepository $logRepo;
|
||||
|
||||
|
|
@ -95,6 +96,11 @@ class LogDataTable implements DataTableTypeInterface
|
|||
|
||||
public function configure(DataTable $dataTable, array $options): void
|
||||
{
|
||||
/*************************************************************************************************************
|
||||
* Avoid using render, as it has no escaping, and is a potential security risk. Use data on TextColumn or the
|
||||
* HTMLColumn, if necessary
|
||||
************************************************************************************************************/
|
||||
|
||||
$resolver = new OptionsResolver();
|
||||
$this->configureOptions($resolver);
|
||||
$options = $resolver->resolve($options);
|
||||
|
|
@ -104,10 +110,10 @@ class LogDataTable implements DataTableTypeInterface
|
|||
'render' => fn($value, AbstractLogEntry $context) => $this->logLevelHelper->logLevelToTableColorClass($context->getLevelString()),
|
||||
]);
|
||||
|
||||
$dataTable->add('symbol', TextColumn::class, [
|
||||
$dataTable->add('symbol', HTMLColumn::class, [
|
||||
'label' => '',
|
||||
'className' => 'no-colvis',
|
||||
'render' => fn($value, AbstractLogEntry $context): string => sprintf(
|
||||
'data' => fn(AbstractLogEntry $context): string => sprintf(
|
||||
'<i class="fas fa-fw %s" title="%s"></i>',
|
||||
$this->logLevelHelper->logLevelToIconClass($context->getLevelString()),
|
||||
$context->getLevelString()
|
||||
|
|
@ -128,10 +134,10 @@ class LogDataTable implements DataTableTypeInterface
|
|||
)
|
||||
]);
|
||||
|
||||
$dataTable->add('type', TextColumn::class, [
|
||||
$dataTable->add('type', HTMLColumn::class, [
|
||||
'label' => 'log.type',
|
||||
'propertyPath' => 'type',
|
||||
'render' => function (string $value, AbstractLogEntry $context) {
|
||||
'data' => function (AbstractLogEntry $context, string $value) {
|
||||
$text = $this->translator->trans('log.type.'.$value);
|
||||
|
||||
if ($context instanceof PartStockChangedLogEntry) {
|
||||
|
|
@ -149,20 +155,20 @@ class LogDataTable implements DataTableTypeInterface
|
|||
'label' => 'log.level',
|
||||
'visible' => 'system_log' === $options['mode'],
|
||||
'propertyPath' => 'levelString',
|
||||
'render' => fn(string $value, AbstractLogEntry $context) => $this->translator->trans('log.level.'.$value),
|
||||
'data' => fn(AbstractLogEntry $context, string $value) => $this->translator->trans('log.level.'.$value),
|
||||
]);
|
||||
|
||||
$dataTable->add('user', TextColumn::class, [
|
||||
$dataTable->add('user', HTMLColumn::class, [
|
||||
'label' => 'log.user',
|
||||
'orderField' => 'NATSORT(user.name)',
|
||||
'render' => function ($value, AbstractLogEntry $context): string {
|
||||
'data' => function (AbstractLogEntry $context): string {
|
||||
$user = $context->getUser();
|
||||
|
||||
//If user was deleted, show the info from the username field
|
||||
if (!$user instanceof User) {
|
||||
if ($context->isCLIEntry()) {
|
||||
return sprintf('%s [%s]',
|
||||
htmlentities((string) $context->getCLIUsername()),
|
||||
htmlspecialchars((string) $context->getCLIUsername()),
|
||||
$this->translator->trans('log.cli_user')
|
||||
);
|
||||
}
|
||||
|
|
@ -170,7 +176,7 @@ class LogDataTable implements DataTableTypeInterface
|
|||
//Else we just deal with a deleted user
|
||||
return sprintf(
|
||||
'@%s [%s]',
|
||||
htmlentities($context->getUsername()),
|
||||
htmlspecialchars($context->getUsername()),
|
||||
$this->translator->trans('log.target_deleted'),
|
||||
);
|
||||
}
|
||||
|
|
@ -182,7 +188,7 @@ class LogDataTable implements DataTableTypeInterface
|
|||
$img_url,
|
||||
$this->userAvatarHelper->getAvatarMdURL($user),
|
||||
$this->urlGenerator->generate('user_info', ['id' => $user->getID()]),
|
||||
htmlentities($user->getFullName(true))
|
||||
htmlspecialchars($user->getFullName(true))
|
||||
);
|
||||
},
|
||||
]);
|
||||
|
|
@ -194,7 +200,7 @@ class LogDataTable implements DataTableTypeInterface
|
|||
'render' => function (LogTargetType $value, AbstractLogEntry $context) {
|
||||
$class = $value->toClass();
|
||||
if (null !== $class) {
|
||||
return $this->elementTypeNameGenerator->getLocalizedTypeLabel($class);
|
||||
return $this->elementTypeNameGenerator->typeLabel($class);
|
||||
}
|
||||
|
||||
return '';
|
||||
|
|
@ -216,9 +222,9 @@ class LogDataTable implements DataTableTypeInterface
|
|||
'icon' => 'fas fa-fw fa-eye',
|
||||
'href' => function ($value, AbstractLogEntry $context) {
|
||||
if (
|
||||
$context instanceof CollectionElementDeleted ||
|
||||
($context instanceof TimeTravelInterface
|
||||
&& $context->hasOldDataInformation())
|
||||
|| $context instanceof CollectionElementDeleted
|
||||
) {
|
||||
try {
|
||||
$target = $this->logRepo->getTargetElement($context);
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ namespace App\DataTables;
|
|||
use App\DataTables\Adapters\TwoStepORMAdapter;
|
||||
use App\DataTables\Column\EntityColumn;
|
||||
use App\DataTables\Column\EnumColumn;
|
||||
use App\DataTables\Column\HTMLColumn;
|
||||
use App\DataTables\Column\IconLinkColumn;
|
||||
use App\DataTables\Column\LocaleDateTimeColumn;
|
||||
use App\DataTables\Column\MarkdownColumn;
|
||||
|
|
@ -58,7 +59,7 @@ use Symfony\Bundle\SecurityBundle\Security;
|
|||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
final class PartsDataTable implements DataTableTypeInterface
|
||||
final readonly class PartsDataTable implements DataTableTypeInterface
|
||||
{
|
||||
public const LENGTH_MENU = [[10, 25, 50, 100, 250, 500, -1], [10, 25, 50, 100, 250, 500, "All"]];
|
||||
|
||||
|
|
@ -94,6 +95,11 @@ final class PartsDataTable implements DataTableTypeInterface
|
|||
* When adding columns here, add them also to PartTableColumns enum, to make them configurable in the settings!
|
||||
*************************************************************************************************************/
|
||||
|
||||
/*************************************************************************************************************
|
||||
* Avoid using render, as it has no escaping, and is a potential security risk. Use data on TextColumn or the
|
||||
* HTMLColumn, if necessary
|
||||
************************************************************************************************************/
|
||||
|
||||
$this->csh
|
||||
//Color the table rows depending on the review and favorite status
|
||||
->add('row_color', RowClassColumn::class, [
|
||||
|
|
@ -109,23 +115,23 @@ final class PartsDataTable implements DataTableTypeInterface
|
|||
},
|
||||
], visibility_configurable: false)
|
||||
->add('select', SelectColumn::class, visibility_configurable: false)
|
||||
->add('picture', TextColumn::class, [
|
||||
->add('picture', HTMLColumn::class, [
|
||||
'label' => '',
|
||||
'className' => 'no-colvis',
|
||||
'render' => fn($value, Part $context) => $this->partDataTableHelper->renderPicture($context),
|
||||
'data' => fn(Part $context) => $this->partDataTableHelper->renderPicture($context),
|
||||
], visibility_configurable: false)
|
||||
->add('name', TextColumn::class, [
|
||||
->add('name', HTMLColumn::class, [
|
||||
'label' => $this->translator->trans('part.table.name'),
|
||||
'render' => fn($value, Part $context) => $this->partDataTableHelper->renderName($context),
|
||||
'data' => fn(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 {
|
||||
'data' => function (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 sprintf('%G', $siValue);
|
||||
}
|
||||
return '';
|
||||
},
|
||||
|
|
@ -156,38 +162,38 @@ final class PartsDataTable implements DataTableTypeInterface
|
|||
'label' => $this->translator->trans('part.table.manufacturer'),
|
||||
'orderField' => 'NATSORT(_manufacturer.name)'
|
||||
])
|
||||
->add('storelocation', TextColumn::class, [
|
||||
->add('storelocation', HTMLColumn::class, [
|
||||
'label' => $this->translator->trans('part.table.storeLocations'),
|
||||
//We need to use a aggregate function to get the first store location, as we have a one-to-many relation
|
||||
'orderField' => 'NATSORT(MIN(_storelocations.name))',
|
||||
'render' => fn($value, Part $context) => $this->partDataTableHelper->renderStorageLocations($context),
|
||||
'data' => fn(Part $context) => $this->partDataTableHelper->renderStorageLocations($context),
|
||||
], alias: 'storage_location')
|
||||
|
||||
->add('amount', TextColumn::class, [
|
||||
->add('amount', HTMLColumn::class, [
|
||||
'label' => $this->translator->trans('part.table.amount'),
|
||||
'render' => fn($value, Part $context) => $this->partDataTableHelper->renderAmount($context),
|
||||
'data' => fn(Part $context) => $this->partDataTableHelper->renderAmount($context),
|
||||
'orderField' => 'amountSum'
|
||||
])
|
||||
->add('minamount', TextColumn::class, [
|
||||
'label' => $this->translator->trans('part.table.minamount'),
|
||||
'render' => fn($value, Part $context): string => htmlspecialchars($this->amountFormatter->format(
|
||||
'data' => fn(Part $context, $value): string => $this->amountFormatter->format(
|
||||
$value,
|
||||
$context->getPartUnit()
|
||||
)),
|
||||
),
|
||||
])
|
||||
->add('partUnit', TextColumn::class, [
|
||||
'label' => $this->translator->trans('part.table.partUnit'),
|
||||
'orderField' => 'NATSORT(_partUnit.name)',
|
||||
'render' => function ($value, Part $context): string {
|
||||
'data' => function (Part $context): string {
|
||||
$partUnit = $context->getPartUnit();
|
||||
if ($partUnit === null) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$tmp = htmlspecialchars($partUnit->getName());
|
||||
$tmp = $partUnit->getName();
|
||||
|
||||
if ($partUnit->getUnit()) {
|
||||
$tmp .= ' (' . htmlspecialchars($partUnit->getUnit()) . ')';
|
||||
$tmp .= ' (' . $partUnit->getUnit() . ')';
|
||||
}
|
||||
return $tmp;
|
||||
}
|
||||
|
|
@ -195,14 +201,14 @@ final class PartsDataTable implements DataTableTypeInterface
|
|||
->add('partCustomState', TextColumn::class, [
|
||||
'label' => $this->translator->trans('part.table.partCustomState'),
|
||||
'orderField' => 'NATSORT(_partCustomState.name)',
|
||||
'render' => function($value, Part $context): string {
|
||||
'data' => function(Part $context): string {
|
||||
$partCustomState = $context->getPartCustomState();
|
||||
|
||||
if ($partCustomState === null) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return htmlspecialchars($partCustomState->getName());
|
||||
return $partCustomState->getName();
|
||||
}
|
||||
])
|
||||
->add('addedDate', LocaleDateTimeColumn::class, [
|
||||
|
|
@ -248,25 +254,25 @@ final class PartsDataTable implements DataTableTypeInterface
|
|||
])
|
||||
->add('eda_reference', TextColumn::class, [
|
||||
'label' => $this->translator->trans('part.table.eda_reference'),
|
||||
'render' => static fn($value, Part $context) => htmlspecialchars($context->getEdaInfo()->getReferencePrefix() ?? ''),
|
||||
'data' => static fn(Part $context) => $context->getEdaInfo()->getReferencePrefix() ?? '',
|
||||
'orderField' => 'NATSORT(part.eda_info.reference_prefix)'
|
||||
])
|
||||
->add('eda_value', TextColumn::class, [
|
||||
'label' => $this->translator->trans('part.table.eda_value'),
|
||||
'render' => static fn($value, Part $context) => htmlspecialchars($context->getEdaInfo()->getValue() ?? ''),
|
||||
'data' => static fn(Part $context) => $context->getEdaInfo()->getValue() ?? '',
|
||||
'orderField' => 'NATSORT(part.eda_info.value)'
|
||||
])
|
||||
->add('eda_status', TextColumn::class, [
|
||||
->add('eda_status', HTMLColumn::class, [
|
||||
'label' => $this->translator->trans('part.table.eda_status'),
|
||||
'render' => fn($value, Part $context) => $this->partDataTableHelper->renderEdaStatus($context),
|
||||
'data' => fn(Part $context) => $this->partDataTableHelper->renderEdaStatus($context),
|
||||
'className' => 'text-center',
|
||||
]);
|
||||
|
||||
//Add a column to list the projects where the part is used, when the user has the permission to see the projects
|
||||
if ($this->security->isGranted('read', Project::class)) {
|
||||
$this->csh->add('projects', TextColumn::class, [
|
||||
$this->csh->add('projects', HTMLColumn::class, [
|
||||
'label' => $this->translator->trans('project.labelp'),
|
||||
'render' => function ($value, Part $context): string {
|
||||
'data' => function (Part $context): string {
|
||||
//Only show the first 5 projects names
|
||||
$projects = $context->getProjects();
|
||||
$tmp = "";
|
||||
|
|
@ -286,7 +292,7 @@ final class PartsDataTable implements DataTableTypeInterface
|
|||
}
|
||||
|
||||
return $tmp;
|
||||
}
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ namespace App\DataTables;
|
|||
use App\DataTables\Adapters\TwoStepORMAdapter;
|
||||
use App\DataTables\Column\EntityColumn;
|
||||
use App\DataTables\Column\EnumColumn;
|
||||
use App\DataTables\Column\HTMLColumn;
|
||||
use App\DataTables\Column\LocaleDateTimeColumn;
|
||||
use App\DataTables\Column\MarkdownColumn;
|
||||
use App\DataTables\Helpers\PartDataTableHelper;
|
||||
|
|
@ -48,7 +49,7 @@ use Omines\DataTablesBundle\DataTable;
|
|||
use Omines\DataTablesBundle\DataTableTypeInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
class ProjectBomEntriesDataTable implements DataTableTypeInterface
|
||||
final readonly class ProjectBomEntriesDataTable implements DataTableTypeInterface
|
||||
{
|
||||
public function __construct(
|
||||
protected EntityURLGenerator $entityURLGenerator,
|
||||
|
|
@ -63,17 +64,22 @@ class ProjectBomEntriesDataTable implements DataTableTypeInterface
|
|||
|
||||
public function configure(DataTable $dataTable, array $options): void
|
||||
{
|
||||
/*************************************************************************************************************
|
||||
* Avoid using render, as it has no escaping, and is a potential security risk. Use data on TextColumn or the
|
||||
* HTMLColumn, if necessary
|
||||
************************************************************************************************************/
|
||||
|
||||
$dataTable
|
||||
//->add('select', SelectColumn::class)
|
||||
->add('picture', TextColumn::class, [
|
||||
->add('picture', HTMLColumn::class, [
|
||||
'label' => '',
|
||||
'className' => 'no-colvis',
|
||||
'render' => function ($value, ProjectBOMEntry $context) {
|
||||
'data' => function (ProjectBOMEntry $context) {
|
||||
if(!$context->getPart() instanceof Part) {
|
||||
return '';
|
||||
}
|
||||
return $this->partDataTableHelper->renderPicture($context->getPart());
|
||||
}
|
||||
},
|
||||
])
|
||||
|
||||
->add('id', TextColumn::class, [
|
||||
|
|
@ -85,27 +91,27 @@ class ProjectBomEntriesDataTable implements DataTableTypeInterface
|
|||
'label' => $this->translator->trans('project.bom.quantity'),
|
||||
'className' => 'text-center',
|
||||
'orderField' => 'bom_entry.quantity',
|
||||
'render' => function ($value, ProjectBOMEntry $context): float|string {
|
||||
'data' => function (ProjectBOMEntry $context): float|string {
|
||||
//If we have a non-part entry, only show the rounded quantity
|
||||
if (!$context->getPart() instanceof Part) {
|
||||
return round($context->getQuantity());
|
||||
}
|
||||
//Otherwise use the unit of the part to format the quantity
|
||||
return htmlspecialchars($this->amountFormatter->format($context->getQuantity(), $context->getPart()->getPartUnit()));
|
||||
return $this->amountFormatter->format($context->getQuantity(), $context->getPart()->getPartUnit());
|
||||
},
|
||||
])
|
||||
->add('partId', TextColumn::class, [
|
||||
'label' => $this->translator->trans('project.bom.part_id'),
|
||||
'visible' => true,
|
||||
'orderField' => 'part.id',
|
||||
'render' => function ($value, ProjectBOMEntry $context) {
|
||||
'data' => function (ProjectBOMEntry $context) {
|
||||
return $context->getPart() instanceof Part ? (string) $context->getPart()->getId() : '';
|
||||
},
|
||||
])
|
||||
->add('name', TextColumn::class, [
|
||||
->add('name', HTMLColumn::class, [
|
||||
'label' => $this->translator->trans('part.table.name'),
|
||||
'orderField' => 'NATSORT(part.name)',
|
||||
'render' => function ($value, ProjectBOMEntry $context) {
|
||||
'data' => function (ProjectBOMEntry $context) {
|
||||
if(!$context->getPart() instanceof Part) {
|
||||
return htmlspecialchars((string) $context->getName());
|
||||
}
|
||||
|
|
@ -123,11 +129,7 @@ class ProjectBomEntriesDataTable implements DataTableTypeInterface
|
|||
'label' => $this->translator->trans('part.table.ipn'),
|
||||
'orderField' => 'NATSORT(part.ipn)',
|
||||
'visible' => false,
|
||||
'render' => function ($value, ProjectBOMEntry $context) {
|
||||
if($context->getPart() instanceof Part) {
|
||||
return $context->getPart()->getIpn();
|
||||
}
|
||||
}
|
||||
'data' => fn (ProjectBOMEntry $context) => $context->getPart()?->getIpn()
|
||||
])
|
||||
->add('description', MarkdownColumn::class, [
|
||||
'label' => $this->translator->trans('part.table.description'),
|
||||
|
|
@ -172,9 +174,9 @@ class ProjectBomEntriesDataTable implements DataTableTypeInterface
|
|||
},
|
||||
])
|
||||
|
||||
->add('mountnames', TextColumn::class, [
|
||||
->add('mountnames', HTMLColumn::class, [
|
||||
'label' => 'project.bom.mountnames',
|
||||
'render' => function ($value, ProjectBOMEntry $context) {
|
||||
'data' => function (ProjectBOMEntry $context) {
|
||||
$html = '';
|
||||
|
||||
foreach (explode(',', $context->getMountnames()) as $mountname) {
|
||||
|
|
@ -184,34 +186,34 @@ class ProjectBomEntriesDataTable implements DataTableTypeInterface
|
|||
},
|
||||
])
|
||||
|
||||
->add('instockAmount', TextColumn::class, [
|
||||
->add('instockAmount', HTMLColumn::class, [
|
||||
'label' => 'project.bom.instockAmount',
|
||||
'visible' => false,
|
||||
'render' => function ($value, ProjectBOMEntry $context) {
|
||||
'data' => function (ProjectBOMEntry $context) {
|
||||
if ($context->getPart() !== null) {
|
||||
return $this->partDataTableHelper->renderAmount($context->getPart());
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
},
|
||||
])
|
||||
->add('storelocation', TextColumn::class, [
|
||||
->add('storelocation', HTMLColumn::class, [
|
||||
'label' => $this->translator->trans('part.table.storeLocations'),
|
||||
//We need to use a aggregate function to get the first store location, as we have a one-to-many relation
|
||||
'orderField' => 'NATSORT(MIN(_storelocations.name))',
|
||||
'visible' => false,
|
||||
'render' => function ($value, ProjectBOMEntry $context) {
|
||||
'data' => function (ProjectBOMEntry $context) {
|
||||
if ($context->getPart() !== null) {
|
||||
return $this->partDataTableHelper->renderStorageLocations($context->getPart());
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
},
|
||||
])
|
||||
->add('price', TextColumn::class, [
|
||||
'label' => 'project.bom.price',
|
||||
'visible' => false,
|
||||
'render' => function ($value, ProjectBOMEntry $context) {
|
||||
'data' => function (ProjectBOMEntry $context) {
|
||||
$price = $this->projectBuildHelper->getEntryUnitPrice($context);
|
||||
return $this->moneyFormatter->format($price->toScale(2, RoundingMode::Up)->toFloat(), null, 2, true);
|
||||
},
|
||||
|
|
@ -219,7 +221,7 @@ class ProjectBomEntriesDataTable implements DataTableTypeInterface
|
|||
->add('ext_price', TextColumn::class, [
|
||||
'label' => 'project.bom.ext_price',
|
||||
'visible' => false,
|
||||
'render' => function ($value, ProjectBOMEntry $context) {
|
||||
'data' => function (ProjectBOMEntry $context) {
|
||||
$price = $this->projectBuildHelper->getEntryUnitPrice($context);
|
||||
return $this->moneyFormatter->format(
|
||||
$price->multipliedBy(BigDecimal::fromFloatShortest($context->getQuantity()))
|
||||
|
|
|
|||
|
|
@ -35,8 +35,10 @@ class SetSQLModeMiddlewareDriver extends AbstractDriverMiddleware
|
|||
{
|
||||
//Only set this on MySQL connections, as other databases don't support this parameter
|
||||
if($params['driver'] === 'pdo_mysql') {
|
||||
//1002 is \PDO::MYSQL_ATTR_INIT_COMMAND constant value
|
||||
$params['driverOptions'][\PDO::MYSQL_ATTR_INIT_COMMAND] = 'SET SESSION sql_mode=(SELECT REPLACE(@@sql_mode, \'ONLY_FULL_GROUP_BY\', \'\'))';
|
||||
//PDO::MYSQL_ATTR_INIT_COMMAND is deprecated since PHP 8.5 in favor of Pdo\Mysql::ATTR_INIT_COMMAND,
|
||||
//but the Pdo\Mysql class only exists since PHP 8.4. Both constants have the same value (1002).
|
||||
$initCommandAttr = class_exists(\Pdo\Mysql::class) ? \Pdo\Mysql::ATTR_INIT_COMMAND : \PDO::MYSQL_ATTR_INIT_COMMAND;
|
||||
$params['driverOptions'][$initCommandAttr] = 'SET SESSION sql_mode=(SELECT REPLACE(@@sql_mode, \'ONLY_FULL_GROUP_BY\', \'\'))';
|
||||
}
|
||||
|
||||
return parent::connect($params);
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ use Symfony\Component\Validator\Constraints as Assert;
|
|||
)
|
||||
],
|
||||
uriVariables: [
|
||||
'id' => new Link(fromProperty: 'children', fromClass: Manufacturer::class)
|
||||
'id' => new Link(fromProperty: 'children', fromClass: StorageLocation::class)
|
||||
],
|
||||
normalizationContext: ['groups' => ['location:read', 'api:basic:read'], 'openapi_definition_name' => 'Read']
|
||||
)]
|
||||
|
|
|
|||
|
|
@ -29,13 +29,13 @@ use Symfony\Contracts\Translation\TranslatorInterface;
|
|||
|
||||
/**
|
||||
* Service for validating BOM import data with comprehensive validation rules
|
||||
* and user-friendly error messages.
|
||||
* and user-friendly error messages. The results are not HTML safe, and must be escaped before display!
|
||||
*/
|
||||
class BOMValidationService
|
||||
readonly class BOMValidationService
|
||||
{
|
||||
public function __construct(
|
||||
private readonly EntityManagerInterface $entityManager,
|
||||
private readonly TranslatorInterface $translator
|
||||
private EntityManagerInterface $entityManager,
|
||||
private TranslatorInterface $translator
|
||||
) {
|
||||
}
|
||||
|
||||
|
|
@ -473,4 +473,4 @@ class BOMValidationService
|
|||
: 0,
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@
|
|||
</tr>
|
||||
<tr>
|
||||
<td>{% trans %}log.target{% endtrans %}</td>
|
||||
<td>{{ target_html|raw }}</td>
|
||||
<td>{{ target_html|sanitize_html }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
|
@ -111,7 +111,7 @@
|
|||
{% elseif log_entry is instanceof('App\\Entity\\LogSystem\\CollectionElementDeleted') %}
|
||||
{% include "log_system/details/_extra_collection_element_deleted.html.twig" %}
|
||||
{% else %}
|
||||
{{ extra_html | raw }}
|
||||
{{ extra_html | sanitize_html }}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@
|
|||
<p class="mb-2">{% trans %}project.bom_import.validation.errors.description{% endtrans %}</p>
|
||||
<ul class="mb-0">
|
||||
{% for error in validation_result.errors %}
|
||||
<li>{{ error|raw }}</li>
|
||||
<li>{{ error }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
|
|
@ -80,7 +80,7 @@
|
|||
<p class="mb-2">{% trans %}project.bom_import.validation.warnings.description{% endtrans %}</p>
|
||||
<ul class="mb-0">
|
||||
{% for warning in validation_result.warnings %}
|
||||
<li>{{ warning|raw }}</li>
|
||||
<li>{{ warning }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
|
|
@ -91,7 +91,7 @@
|
|||
<h4><i class="fa-solid fa-info-circle fa-fw"></i> {% trans %}project.bom_import.validation.info.title{% endtrans %}</h4>
|
||||
<ul class="mb-0">
|
||||
{% for info in validation_result.info %}
|
||||
<li>{{ info|raw }}</li>
|
||||
<li>{{ info }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
|
|
@ -139,21 +139,21 @@
|
|||
{% if line_result.errors is not empty %}
|
||||
<div class="text-danger">
|
||||
{% for error in line_result.errors %}
|
||||
<div><i class="fa-solid fa-exclamation-triangle fa-fw"></i> {{ error|raw }}</div>
|
||||
<div><i class="fa-solid fa-exclamation-triangle fa-fw"></i> {{ error }}</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if line_result.warnings is not empty %}
|
||||
<div class="text-warning">
|
||||
{% for warning in line_result.warnings %}
|
||||
<div><i class="fa-solid fa-exclamation-circle fa-fw"></i> {{ warning|raw }}</div>
|
||||
<div><i class="fa-solid fa-exclamation-circle fa-fw"></i> {{ warning }}</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if line_result.info is not empty %}
|
||||
<div class="text-info">
|
||||
{% for info in line_result.info %}
|
||||
<div><i class="fa-solid fa-info-circle fa-fw"></i> {{ info|raw }}</div>
|
||||
<div><i class="fa-solid fa-info-circle fa-fw"></i> {{ info }}</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
|
|
|||
|
|
@ -132,8 +132,8 @@
|
|||
<script nonce="{{ csp_nonce('script') }}">
|
||||
// Function to initialize the field mapping page
|
||||
function initializeFieldMapping() {
|
||||
const suggestions = {{ suggested_mapping|json_encode|raw }};
|
||||
const fieldNameMapping = {{ field_name_mapping|json_encode|raw }};
|
||||
const suggestions = JSON.parse("{{ suggested_mapping|json_encode|escape('js')}}");
|
||||
const fieldNameMapping = JSON.parse("{{ field_name_mapping|json_encode|escape('js') }}");
|
||||
|
||||
Object.keys(suggestions).forEach(function(field) {
|
||||
// Use the sanitized field name from the server-side mapping
|
||||
|
|
|
|||
87
yarn.lock
87
yarn.lock
|
|
@ -1887,9 +1887,9 @@
|
|||
integrity sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==
|
||||
|
||||
"@types/node@*":
|
||||
version "25.9.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-25.9.2.tgz#fc8958e757994b71fee516f9634bdb03d1b19e9f"
|
||||
integrity sha512-G05zqtJhcDLb8uslf5EjCxXg9G1KQxiV8OS0R26IC//Eoyitzqe8z37I7cqvnZlrlSfgocQRfSn/AHBZJJFyGw==
|
||||
version "25.9.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-25.9.3.tgz#11dfe7a33e68fa5c560f0aa76cc5595621ef26b9"
|
||||
integrity sha512-603BddQMv3pUcr4U2dhujk83N2tTDVr/34wII2B6bJy6g+8WD6yUb11jszNs0gdi4PesVWl7ABt8nYMVpnLUcg==
|
||||
dependencies:
|
||||
undici-types ">=7.24.0 <7.24.7"
|
||||
|
||||
|
|
@ -2116,9 +2116,9 @@ acorn-walk@^8.0.0:
|
|||
acorn "^8.11.0"
|
||||
|
||||
acorn@^8.0.4, acorn@^8.11.0, acorn@^8.15.0, acorn@^8.16.0:
|
||||
version "8.16.0"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.16.0.tgz#4ce79c89be40afe7afe8f3adb902a1f1ce9ac08a"
|
||||
integrity sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==
|
||||
version "8.17.0"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.17.0.tgz#1785adb84faf8d8add10369b93826fc2bd08f1fe"
|
||||
integrity sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==
|
||||
|
||||
adjust-sourcemap-loader@^4.0.0:
|
||||
version "4.0.0"
|
||||
|
|
@ -2223,9 +2223,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.34"
|
||||
resolved "https://registry.yarnpkg.com/baseline-browser-mapping/-/baseline-browser-mapping-2.10.34.tgz#dedb606362446777cfe328d30d4ee15056d06303"
|
||||
integrity sha512-IMDedajPifLnHNY0X9n8hKxRTQ6/eTHwr5bDo04WnuqxyKw6LYtQywCuuqPZwhl3aBXMvQpJov42GLCwRRdQzw==
|
||||
version "2.10.37"
|
||||
resolved "https://registry.yarnpkg.com/baseline-browser-mapping/-/baseline-browser-mapping-2.10.37.tgz#3e636475b6b293244e2b23e2c71a2ab9d9e6ba7d"
|
||||
integrity sha512-girxaJ7WZssDOFhzCGZTDKoTa1gk6A1TbflaYTpykLJ4UU9Fz9kx1aREM8JCuoVHbL8X8T/mJg7w2oYSq72Oig==
|
||||
|
||||
big.js@^5.2.2:
|
||||
version "5.2.2"
|
||||
|
|
@ -2310,9 +2310,9 @@ caniuse-api@^3.0.0:
|
|||
lodash.uniq "^4.5.0"
|
||||
|
||||
caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001782:
|
||||
version "1.0.30001797"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001797.tgz#1332709e1439f01ff92085dd17001e0a45897ec0"
|
||||
integrity sha512-l8xKG+gwAIExZGl9FrF7KUwuOmk6wbEPC9Xoy/RtnWv1XG0Q4LFlagaLpUv3Kiza3W/wm27zy0yWJEieYKAP6w==
|
||||
version "1.0.30001799"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001799.tgz#5c909138c27f1a61219d3e092071c1cc7d32dc55"
|
||||
integrity sha512-hG1bReV+OUU+MOqK4t/ZWI0tZOyz3rqS9XuhOUz1cIcbwBKjOyJEJuw9ER5JuNyqxNk8u/JUVbGibBOL1yrjFw==
|
||||
|
||||
ccount@^2.0.0:
|
||||
version "2.0.1"
|
||||
|
|
@ -2877,9 +2877,9 @@ domhandler@^5.0.2, domhandler@^5.0.3:
|
|||
domelementtype "^2.3.0"
|
||||
|
||||
dompurify@^3.0.3:
|
||||
version "3.4.8"
|
||||
resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-3.4.8.tgz#6c54f8c207160e7f83fcb7f4fd05a82ac36b1cdc"
|
||||
integrity sha512-yb1cEmaOum7wFvOCSQxyfgVlv5D47Rc30iZWoMpbDIWTnJ6grDDQyu2KFJzB2k7u0pMuJcQ1zphH//fFnw2tjQ==
|
||||
version "3.4.10"
|
||||
resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-3.4.10.tgz#96704295b4d8aeefcc8c7a90caa579b0ad69e46a"
|
||||
integrity sha512-0xzNv0e7oYC6yyuOGZIABPM4qtg3QxLFniDNPP4ZP90wR8Yq3zgwpRbrNiT4N3IKqDbbYFEJLV+JWEs19aZ//w==
|
||||
optionalDependencies:
|
||||
"@types/trusted-types" "^2.0.7"
|
||||
|
||||
|
|
@ -2902,9 +2902,9 @@ domutils@^3.0.1:
|
|||
domhandler "^5.0.3"
|
||||
|
||||
electron-to-chromium@^1.5.328:
|
||||
version "1.5.368"
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.368.tgz#8e8d4600c5f5f01e891f8f843b4a941afb640412"
|
||||
integrity sha512-7RckJJK4uESJF9PxvfMWd3TGqIiieUTG4HxnKaKuIpGbcr+r2ZEB3g2gAhCP3Fqm42vJSzLfgab9eva/C4/XVw==
|
||||
version "1.5.372"
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.372.tgz#ae8ac69942a37b231773b8fb01759f73733599e3"
|
||||
integrity sha512-M3yhbAlilnwqC8D21t28UCDGHyitShTmmLRU/H+b74P6Ski16Nb9HONYEaVpMj/pwC7BEo5B95FpjODLCWbtfA==
|
||||
|
||||
emoji-regex@^8.0.0:
|
||||
version "8.0.0"
|
||||
|
|
@ -2917,9 +2917,9 @@ emojis-list@^3.0.0:
|
|||
integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==
|
||||
|
||||
enhanced-resolve@^5.0.0, enhanced-resolve@^5.22.0:
|
||||
version "5.23.0"
|
||||
resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.23.0.tgz#dfdf8d1c9065e4b52f8a598356138931c07305f9"
|
||||
integrity sha512-yJN/BOOLxcOW2aQgeif9mSnaUB8KtvmMMp56oA1kx1CRfBKbhZm2pJ+NBY+3eOboHxix8lfjWpHE0Ei5U8RbSA==
|
||||
version "5.24.0"
|
||||
resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.24.0.tgz#cf14b9768a774cb6a5087220c0dc6e55df6ec35a"
|
||||
integrity sha512-SkE2t82KlkkxQRVMVLAGKxLfORGQfrkx5dkj+vlgXRVNEdPc4eZcR+J/Fvj8C+yKSFH5L0q3NFlyufOVQnCcYQ==
|
||||
dependencies:
|
||||
graceful-fs "^4.2.4"
|
||||
tapable "^2.3.3"
|
||||
|
|
@ -4153,25 +4153,25 @@ path-parse@^1.0.7:
|
|||
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
|
||||
integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
|
||||
|
||||
pdfkit@^0.18.0:
|
||||
version "0.18.0"
|
||||
resolved "https://registry.yarnpkg.com/pdfkit/-/pdfkit-0.18.0.tgz#573efa7f4c78a8ab1362232a05a589b97b292216"
|
||||
integrity sha512-NvUwSDZ0eYEzqAiWwVQkRkjYUkZ48kcsHuCO31ykqPPIVkwoSDjDGiwIgHHNtsiwls3z3P/zy4q00hl2chg2Ug==
|
||||
pdfkit@^0.19.1:
|
||||
version "0.19.1"
|
||||
resolved "https://registry.yarnpkg.com/pdfkit/-/pdfkit-0.19.1.tgz#633d5f031ce6f1ba6ce141325c6cf87fa6acb0a2"
|
||||
integrity sha512-6Gzk+wDwTs4VSxsR5rCMTnIl5nlmkye1oWB0l2hDB1EX6ZNSIBroKQEv+2+fPPn+stVjyqzmsqRJVDfB9fo5DA==
|
||||
dependencies:
|
||||
"@noble/ciphers" "^1.0.0"
|
||||
"@noble/hashes" "^1.6.0"
|
||||
fontkit "^2.0.4"
|
||||
js-md5 "^0.8.3"
|
||||
linebreak "^1.1.0"
|
||||
png-js "^1.0.0"
|
||||
png-js "^1.1.0"
|
||||
|
||||
pdfmake@^0.3.7:
|
||||
version "0.3.9"
|
||||
resolved "https://registry.yarnpkg.com/pdfmake/-/pdfmake-0.3.9.tgz#c837b471aa81ea0797b7cdac2a03db8ba65e1b7f"
|
||||
integrity sha512-V8VIcjMG/yk7oJYhYjtvyLXvop3w3zcIB0bHdG3z1vuW8nVeemzRWu7YrOG7QA9KYaf858MZnCUG6hQ1Bei0vA==
|
||||
version "0.3.11"
|
||||
resolved "https://registry.yarnpkg.com/pdfmake/-/pdfmake-0.3.11.tgz#b4504d19b8f31fa5063dc1b847b060faa4f7c5bb"
|
||||
integrity sha512-Uc49J9hUMyuqJk+U+PxlpBpPr96A4HOOfesGx609EPr2ue82+5/Smq/KTAkEqh0/jUGSi1fumvqZ5yAWijJTJg==
|
||||
dependencies:
|
||||
linebreak "^1.1.0"
|
||||
pdfkit "^0.18.0"
|
||||
pdfkit "^0.19.1"
|
||||
xmldoc "^2.0.3"
|
||||
|
||||
picocolors@^1.0.0, picocolors@^1.1.0, picocolors@^1.1.1:
|
||||
|
|
@ -4196,7 +4196,7 @@ pkg-dir@^4.2.0:
|
|||
dependencies:
|
||||
find-up "^4.0.0"
|
||||
|
||||
png-js@^1.0.0:
|
||||
png-js@^1.1.0:
|
||||
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==
|
||||
|
|
@ -4423,9 +4423,9 @@ postcss-reduce-transforms@^7.0.3:
|
|||
postcss-value-parser "^4.2.0"
|
||||
|
||||
postcss-selector-parser@^7.0.0, postcss-selector-parser@^7.1.1:
|
||||
version "7.1.1"
|
||||
resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz#e75d2e0d843f620e5df69076166f4e16f891cb9f"
|
||||
integrity sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==
|
||||
version "7.1.4"
|
||||
resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-7.1.4.tgz#69dc7a526517572ff6b150e352b36a016017b485"
|
||||
integrity sha512-HeP7D2wyhkR+XaK6v4W8oRF62Dsz4flyuczALJp61GckGm42u1saSSJ/0auvcBqxs3jMRFEcPK34At/0JBKdOg==
|
||||
dependencies:
|
||||
cssesc "^3.0.0"
|
||||
util-deprecate "^1.0.2"
|
||||
|
|
@ -4549,9 +4549,9 @@ regjsgen@^0.8.0:
|
|||
integrity sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==
|
||||
|
||||
regjsparser@^0.13.0:
|
||||
version "0.13.1"
|
||||
resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.13.1.tgz#0593cbacb27527927692030928ae4d3b878d6f8d"
|
||||
integrity sha512-dLsljMd9sqwRkby8zhO1gSg3PnJIBFid8f4CQj/sXx+7cKx+E7u0PKhZ+U4wmhx7EfmtvnA318oVaIkAB1lRJw==
|
||||
version "0.13.2"
|
||||
resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.13.2.tgz#f654734b5c588b22ba3e21693b30523417180808"
|
||||
integrity sha512-NgRBy2Nx/bE+9F27nVHnqcN5HjyLmecqsqx2PJHu3/IEtADD4WuxuXIVExD5PoSDFVrl78dOonfcOe5O+5nbzQ==
|
||||
dependencies:
|
||||
jsesc "~3.1.0"
|
||||
|
||||
|
|
@ -4733,9 +4733,9 @@ semver@^6.3.1:
|
|||
integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
|
||||
|
||||
semver@^7.3.2, semver@^7.3.4, semver@^7.6.3:
|
||||
version "7.8.2"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.8.2.tgz#194bd65723a28cf82542d2bf176b91c26b343be1"
|
||||
integrity sha512-c8jsqUZm3omBOI66G90z1Dyw5z622G8oLG+omfsHBJf3CWQTlOcwOjvOG6wtiNfW6anKm/eA39LMwMtMez2TiQ==
|
||||
version "7.8.4"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.8.4.tgz#c73eceebae0616934be8dff28a7fd70757c8e696"
|
||||
integrity sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==
|
||||
|
||||
serialize-javascript@^6.0.2:
|
||||
version "6.0.2"
|
||||
|
|
@ -5171,11 +5171,10 @@ vfile@^6.0.0:
|
|||
vfile-message "^4.0.0"
|
||||
|
||||
watchpack@^2.5.1:
|
||||
version "2.5.1"
|
||||
resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.5.1.tgz#dd38b601f669e0cbf567cb802e75cead82cde102"
|
||||
integrity sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==
|
||||
version "2.5.2"
|
||||
resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.5.2.tgz#e12e82d84674266fc1c6dbfe38891b92ff0522ec"
|
||||
integrity sha512-6i/00NBjP4yGPs+caKSyRfpTF/8Torsu0MOW3mMzIbhgISFder8i7xbqgHlLMwJrdiN8ndBV3UA1/AfzPSr+jg==
|
||||
dependencies:
|
||||
glob-to-regexp "^0.4.1"
|
||||
graceful-fs "^4.1.2"
|
||||
|
||||
web-namespaces@^2.0.0:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue