mirror of
https://github.com/Part-DB/Part-DB-server.git
synced 2025-07-11 02:44:32 +02:00
Merge master into settings-bundle
This commit is contained in:
commit
9812671a89
13 changed files with 364 additions and 276 deletions
|
@ -47,6 +47,7 @@
|
||||||
PassEnv PROVIDER_REICHELT_ENABLED PROVIDER_REICHELT_CURRENCY PROVIDER_REICHELT_COUNTRY PROVIDER_REICHELT_LANGUAGE PROVIDER_REICHELT_INCLUDE_VAT
|
PassEnv PROVIDER_REICHELT_ENABLED PROVIDER_REICHELT_CURRENCY PROVIDER_REICHELT_COUNTRY PROVIDER_REICHELT_LANGUAGE PROVIDER_REICHELT_INCLUDE_VAT
|
||||||
PassEnv PROVIDER_POLLIN_ENABLED
|
PassEnv PROVIDER_POLLIN_ENABLED
|
||||||
PassEnv EDA_KICAD_CATEGORY_DEPTH
|
PassEnv EDA_KICAD_CATEGORY_DEPTH
|
||||||
|
PassEnv SHOW_PART_IMAGE_OVERLAY
|
||||||
|
|
||||||
# For most configuration files from conf-available/, which are
|
# For most configuration files from conf-available/, which are
|
||||||
# enabled or disabled at a global level, it is possible to
|
# enabled or disabled at a global level, it is possible to
|
||||||
|
|
3
.env
3
.env
|
@ -164,6 +164,9 @@ FIXER_API_KEY=CHANGEME
|
||||||
# When this is empty the content of config/banner.md is used as banner
|
# When this is empty the content of config/banner.md is used as banner
|
||||||
BANNER=""
|
BANNER=""
|
||||||
|
|
||||||
|
# Enable the part image overlay which shows name and filename of the picture
|
||||||
|
SHOW_PART_IMAGE_OVERLAY=1
|
||||||
|
|
||||||
APP_ENV=prod
|
APP_ENV=prod
|
||||||
APP_SECRET=a03498528f5a5fc089273ec9ae5b2849
|
APP_SECRET=a03498528f5a5fc089273ec9ae5b2849
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,10 @@ export default class extends Controller {
|
||||||
{
|
{
|
||||||
let value = "";
|
let value = "";
|
||||||
if (this.unitValue) {
|
if (this.unitValue) {
|
||||||
value = "\\mathrm{" + this.inputTarget.value + "}";
|
//Escape percentage signs
|
||||||
|
value = this.inputTarget.value.replace(/%/g, '\\%');
|
||||||
|
|
||||||
|
value = "\\mathrm{" + value + "}";
|
||||||
} else {
|
} else {
|
||||||
value = this.inputTarget.value;
|
value = this.inputTarget.value;
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,7 +85,9 @@ export default class extends Controller
|
||||||
tmp += '<span>' + katex.renderToString(data.symbol) + '</span>'
|
tmp += '<span>' + katex.renderToString(data.symbol) + '</span>'
|
||||||
}
|
}
|
||||||
if (data.unit) {
|
if (data.unit) {
|
||||||
tmp += '<span class="ms-2">' + katex.renderToString('[' + data.unit + ']') + '</span>'
|
let unit = data.unit.replace(/%/g, '\\%');
|
||||||
|
unit = "\\mathrm{" + unit + "}";
|
||||||
|
tmp += '<span class="ms-2">' + katex.renderToString('[' + unit + ']') + '</span>'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
535
composer.lock
generated
535
composer.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -17,6 +17,7 @@ twig:
|
||||||
available_themes: '%partdb.available_themes%'
|
available_themes: '%partdb.available_themes%'
|
||||||
saml_enabled: '%partdb.saml.enabled%'
|
saml_enabled: '%partdb.saml.enabled%'
|
||||||
part_preview_generator: '@App\Services\Attachments\PartPreviewGenerator'
|
part_preview_generator: '@App\Services\Attachments\PartPreviewGenerator'
|
||||||
|
img_overlay: '%partdb.show_part_image_overlay%'
|
||||||
|
|
||||||
when@test:
|
when@test:
|
||||||
twig:
|
twig:
|
||||||
|
|
|
@ -48,6 +48,7 @@ parameters:
|
||||||
# Miscellaneous
|
# Miscellaneous
|
||||||
######################################################################################################################
|
######################################################################################################################
|
||||||
partdb.demo_mode: '%env(bool:DEMO_MODE)%' # If set to true, all potentially dangerous things are disabled (like changing passwords of the own user)
|
partdb.demo_mode: '%env(bool:DEMO_MODE)%' # If set to true, all potentially dangerous things are disabled (like changing passwords of the own user)
|
||||||
|
partdb.show_part_image_overlay: '%env(bool:SHOW_PART_IMAGE_OVERLAY)%' # If set to false, the filename overlay of the part image will be disabled
|
||||||
|
|
||||||
# Set the themes from which the user can choose from in the settings.
|
# Set the themes from which the user can choose from in the settings.
|
||||||
# Themes commented here by default, are not really usable, because of display problems. Enable them at your own risk!
|
# Themes commented here by default, are not really usable, because of display problems. Enable them at your own risk!
|
||||||
|
|
|
@ -95,6 +95,8 @@ bundled with Part-DB. Set `DATABASE_MYSQL_SSL_VERIFY_CERT` if you want to accept
|
||||||
particularly for securing and protecting various aspects of your application. It's a secret key that is used for
|
particularly for securing and protecting various aspects of your application. It's a secret key that is used for
|
||||||
cryptographic operations and security measures (session management, CSRF protection, etc..). Therefore this
|
cryptographic operations and security measures (session management, CSRF protection, etc..). Therefore this
|
||||||
value should be handled as confidential data and not shared publicly.
|
value should be handled as confidential data and not shared publicly.
|
||||||
|
* `SHOW_PART_IMAGE_OVERLAY`: Set to 0 to disable the part image overlay, which appears if you hover over an image in the
|
||||||
|
part image gallery
|
||||||
|
|
||||||
### E-Mail settings
|
### E-Mail settings
|
||||||
|
|
||||||
|
|
|
@ -217,7 +217,7 @@ abstract class AbstractParameter extends AbstractNamedDBElement implements Uniqu
|
||||||
|
|
||||||
$str = '';
|
$str = '';
|
||||||
$bracket_opened = false;
|
$bracket_opened = false;
|
||||||
if ($this->value_typical) {
|
if ($this->value_typical !== null) {
|
||||||
$str .= $this->getValueTypicalWithUnit($latex_formatted);
|
$str .= $this->getValueTypicalWithUnit($latex_formatted);
|
||||||
if ($this->value_min || $this->value_max) {
|
if ($this->value_min || $this->value_max) {
|
||||||
$bracket_opened = true;
|
$bracket_opened = true;
|
||||||
|
@ -225,11 +225,11 @@ abstract class AbstractParameter extends AbstractNamedDBElement implements Uniqu
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->value_max && $this->value_min) {
|
if ($this->value_max !== null && $this->value_min !== null) {
|
||||||
$str .= $this->getValueMinWithUnit($latex_formatted).' ... '.$this->getValueMaxWithUnit($latex_formatted);
|
$str .= $this->getValueMinWithUnit($latex_formatted).' ... '.$this->getValueMaxWithUnit($latex_formatted);
|
||||||
} elseif ($this->value_max) {
|
} elseif ($this->value_max !== null) {
|
||||||
$str .= 'max. '.$this->getValueMaxWithUnit($latex_formatted);
|
$str .= 'max. '.$this->getValueMaxWithUnit($latex_formatted);
|
||||||
} elseif ($this->value_min) {
|
} elseif ($this->value_min !== null) {
|
||||||
$str .= 'min. '.$this->getValueMinWithUnit($latex_formatted);
|
$str .= 'min. '.$this->getValueMinWithUnit($latex_formatted);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -449,7 +449,10 @@ abstract class AbstractParameter extends AbstractNamedDBElement implements Uniqu
|
||||||
if (!$with_latex) {
|
if (!$with_latex) {
|
||||||
$unit = $this->unit;
|
$unit = $this->unit;
|
||||||
} else {
|
} else {
|
||||||
$unit = '$\mathrm{'.$this->unit.'}$';
|
//Escape the percentage sign for convenience (as latex uses it as comment and it is often used in units)
|
||||||
|
$escaped = preg_replace('/\\\\?%/', "\\\\%", $this->unit);
|
||||||
|
|
||||||
|
$unit = '$\mathrm{'.$escaped.'}$';
|
||||||
}
|
}
|
||||||
|
|
||||||
return $str.' '.$unit;
|
return $str.' '.$unit;
|
||||||
|
@ -457,7 +460,7 @@ abstract class AbstractParameter extends AbstractNamedDBElement implements Uniqu
|
||||||
|
|
||||||
return $str;
|
return $str;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the class of the element that is allowed to be associated with this attachment.
|
* Returns the class of the element that is allowed to be associated with this attachment.
|
||||||
* @return string
|
* @return string
|
||||||
|
|
|
@ -241,6 +241,49 @@ class KiCadHelper
|
||||||
$result["fields"]["Part-DB IPN"] = $this->createField($part->getIpn());
|
$result["fields"]["Part-DB IPN"] = $this->createField($part->getIpn());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add supplier information from orderdetails (include obsolete orderdetails)
|
||||||
|
if ($part->getOrderdetails(false)->count() > 0) {
|
||||||
|
$supplierCounts = [];
|
||||||
|
|
||||||
|
foreach ($part->getOrderdetails(false) as $orderdetail) {
|
||||||
|
if ($orderdetail->getSupplier() !== null && $orderdetail->getSupplierPartNr() !== '') {
|
||||||
|
$supplierName = $orderdetail->getSupplier()->getName();
|
||||||
|
|
||||||
|
$supplierName .= " SPN"; // Append "SPN" to the supplier name to indicate Supplier Part Number
|
||||||
|
|
||||||
|
if (!isset($supplierCounts[$supplierName])) {
|
||||||
|
$supplierCounts[$supplierName] = 0;
|
||||||
|
}
|
||||||
|
$supplierCounts[$supplierName]++;
|
||||||
|
|
||||||
|
// Create field name with sequential number if more than one from same supplier (e.g. "Mouser", "Mouser 2", etc.)
|
||||||
|
$fieldName = $supplierCounts[$supplierName] > 1
|
||||||
|
? $supplierName . ' ' . $supplierCounts[$supplierName]
|
||||||
|
: $supplierName;
|
||||||
|
|
||||||
|
$result["fields"][$fieldName] = $this->createField($orderdetail->getSupplierPartNr());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Add fields for KiCost:
|
||||||
|
if ($part->getManufacturer() !== null) {
|
||||||
|
$result["fields"]["manf"] = $this->createField($part->getManufacturer()->getName());
|
||||||
|
}
|
||||||
|
if ($part->getManufacturerProductNumber() !== "") {
|
||||||
|
$result['fields']['manf#'] = $this->createField($part->getManufacturerProductNumber());
|
||||||
|
}
|
||||||
|
|
||||||
|
//For each supplier, add a field with the supplier name and the supplier part number for KiCost
|
||||||
|
if ($part->getOrderdetails(false)->count() > 0) {
|
||||||
|
foreach ($part->getOrderdetails(false) as $orderdetail) {
|
||||||
|
if ($orderdetail->getSupplier() !== null && $orderdetail->getSupplierPartNr() !== '') {
|
||||||
|
$fieldName = mb_strtolower($orderdetail->getSupplier()->getName()) . '#';
|
||||||
|
|
||||||
|
$result["fields"][$fieldName] = $this->createField($orderdetail->getSupplierPartNr());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -179,10 +179,7 @@ class TreeViewGenerator
|
||||||
}
|
}
|
||||||
|
|
||||||
if (($mode === 'list_parts_root' || $mode === 'devices') && $this->rootNodeEnabled) {
|
if (($mode === 'list_parts_root' || $mode === 'devices') && $this->rootNodeEnabled) {
|
||||||
//We show the root node as a link to the list of all parts
|
$root_node = new TreeViewNode($this->entityClassToRootNodeString($class), $this->entityClassToRootNodeHref($class), $generic);
|
||||||
$show_all_parts_url = $this->router->generate('parts_show_all');
|
|
||||||
|
|
||||||
$root_node = new TreeViewNode($this->entityClassToRootNodeString($class), $show_all_parts_url, $generic);
|
|
||||||
$root_node->setExpanded($this->rootNodeExpandedByDefault);
|
$root_node->setExpanded($this->rootNodeExpandedByDefault);
|
||||||
$root_node->setIcon($this->entityClassToRootNodeIcon($class));
|
$root_node->setIcon($this->entityClassToRootNodeIcon($class));
|
||||||
|
|
||||||
|
@ -192,6 +189,27 @@ class TreeViewGenerator
|
||||||
return array_merge($head, $generic);
|
return array_merge($head, $generic);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function entityClassToRootNodeHref(string $class): ?string
|
||||||
|
{
|
||||||
|
//If the root node should redirect to the new entity page, we return the URL for the new entity.
|
||||||
|
if ($this->sidebarSettings->rootNodeRedirectsToNewEntity) {
|
||||||
|
return match ($class) {
|
||||||
|
Category::class => $this->router->generate('category_new'),
|
||||||
|
StorageLocation::class => $this->router->generate('store_location_new'),
|
||||||
|
Footprint::class => $this->router->generate('footprint_new'),
|
||||||
|
Manufacturer::class => $this->router->generate('manufacturer_new'),
|
||||||
|
Supplier::class => $this->router->generate('supplier_new'),
|
||||||
|
Project::class => $this->router->generate('project_new'),
|
||||||
|
default => null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return match ($class) {
|
||||||
|
Project::class => $this->router->generate('project_new'),
|
||||||
|
default => $this->router->generate('parts_show_all')
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
protected function entityClassToRootNodeString(string $class): string
|
protected function entityClassToRootNodeString(string $class): string
|
||||||
{
|
{
|
||||||
return match ($class) {
|
return match ($class) {
|
||||||
|
|
|
@ -67,4 +67,6 @@ class SidebarSettings
|
||||||
*/
|
*/
|
||||||
#[SettingsParameter(label: new TM("settings.behavior.sidebar.rootNodeExpanded"))]
|
#[SettingsParameter(label: new TM("settings.behavior.sidebar.rootNodeExpanded"))]
|
||||||
public bool $rootNodeExpanded = true;
|
public bool $rootNodeExpanded = true;
|
||||||
|
|
||||||
|
public bool $rootNodeRedirectsToNewEntity = false;
|
||||||
}
|
}
|
|
@ -13,6 +13,7 @@
|
||||||
<div class="carousel-item {% if loop.first %}active{% endif %}">
|
<div class="carousel-item {% if loop.first %}active{% endif %}">
|
||||||
<a href="{{ entity_url(pic, 'file_view') }}" data-turbo="false" target="_blank" rel="noopener">
|
<a href="{{ entity_url(pic, 'file_view') }}" data-turbo="false" target="_blank" rel="noopener">
|
||||||
<img class="d-block w-100 img-fluid img-thumbnail bg-light part-info-image" src="{{ entity_url(pic, 'file_view') }}" alt="">
|
<img class="d-block w-100 img-fluid img-thumbnail bg-light part-info-image" src="{{ entity_url(pic, 'file_view') }}" alt="">
|
||||||
|
{% if img_overlay %}
|
||||||
<div class="mask"></div>
|
<div class="mask"></div>
|
||||||
<div class="carousel-caption-hover">
|
<div class="carousel-caption-hover">
|
||||||
<div class="carousel-caption text-white">
|
<div class="carousel-caption text-white">
|
||||||
|
@ -21,6 +22,7 @@
|
||||||
<div>{{ entity_type_label(pic.element) }}</div>
|
<div>{{ entity_type_label(pic.element) }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{% endif %}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue