mirror of
https://github.com/Part-DB/Part-DB-server.git
synced 2026-03-03 13:59:35 +00:00
Compare commits
12 commits
c5a1df37b9
...
c2cbbee0df
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c2cbbee0df | ||
|
|
e81c8470be | ||
|
|
ecd2abe00e | ||
|
|
0d1ae030be | ||
|
|
1f669a9c53 | ||
|
|
8ff2fc5a82 | ||
|
|
c7ec8adc31 | ||
|
|
cee6d355e8 | ||
|
|
4b00697f02 | ||
|
|
617ae03b48 | ||
|
|
71629a696c | ||
|
|
14cc0b9e9a |
21 changed files with 752 additions and 64 deletions
|
|
@ -45,8 +45,10 @@ export default class extends DatatablesController {
|
|||
//Hide/Unhide panel with the selection tools
|
||||
if (count > 0) {
|
||||
selectPanel.classList.remove('d-none');
|
||||
selectPanel.classList.add('sticky-select-bar');
|
||||
} else {
|
||||
selectPanel.classList.add('d-none');
|
||||
selectPanel.classList.remove('sticky-select-bar');
|
||||
}
|
||||
|
||||
//Update selection count text
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@
|
|||
*/
|
||||
|
||||
.hoverpic {
|
||||
min-width: 10px;
|
||||
max-width: 30px;
|
||||
min-width: var(--table-image-preview-min-size, 20px);
|
||||
max-width: var(--table-image-preview-max-size, 35px);
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
|
|
@ -49,7 +49,7 @@
|
|||
}
|
||||
|
||||
.part-table-image {
|
||||
max-height: 40px;
|
||||
max-height: calc(1.2*var(--table-image-preview-max-size, 35px)); /** Aspect ratio of maximum 1.2 */
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,16 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/****************************************
|
||||
* Action bar
|
||||
****************************************/
|
||||
|
||||
.sticky-select-bar {
|
||||
position: sticky;
|
||||
top: 120px;
|
||||
z-index: 1000; /* Ensure the bar is above other content */
|
||||
}
|
||||
|
||||
/****************************************
|
||||
* Tables
|
||||
****************************************/
|
||||
|
|
@ -109,4 +119,4 @@ Classes for Datatables export
|
|||
#export-messageTop,
|
||||
.export-helper{
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
36
composer.lock
generated
36
composer.lock
generated
|
|
@ -7513,16 +7513,16 @@
|
|||
},
|
||||
{
|
||||
"name": "part-db/label-fonts",
|
||||
"version": "v1.1.0",
|
||||
"version": "v1.2.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Part-DB/label-fonts.git",
|
||||
"reference": "77c84b70ed3bb005df15f30ff835ddec490394b9"
|
||||
"reference": "c85aeb051d6492961a2c59bc291979f15ce60e88"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Part-DB/label-fonts/zipball/77c84b70ed3bb005df15f30ff835ddec490394b9",
|
||||
"reference": "77c84b70ed3bb005df15f30ff835ddec490394b9",
|
||||
"url": "https://api.github.com/repos/Part-DB/label-fonts/zipball/c85aeb051d6492961a2c59bc291979f15ce60e88",
|
||||
"reference": "c85aeb051d6492961a2c59bc291979f15ce60e88",
|
||||
"shasum": ""
|
||||
},
|
||||
"type": "library",
|
||||
|
|
@ -7545,9 +7545,9 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/Part-DB/label-fonts/issues",
|
||||
"source": "https://github.com/Part-DB/label-fonts/tree/v1.1.0"
|
||||
"source": "https://github.com/Part-DB/label-fonts/tree/v1.2.0"
|
||||
},
|
||||
"time": "2024-02-08T21:44:38+00:00"
|
||||
"time": "2025-09-07T15:42:51+00:00"
|
||||
},
|
||||
{
|
||||
"name": "part-db/swap",
|
||||
|
|
@ -17883,16 +17883,16 @@
|
|||
},
|
||||
{
|
||||
"name": "phpstan/phpstan-doctrine",
|
||||
"version": "2.0.4",
|
||||
"version": "2.0.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpstan/phpstan-doctrine.git",
|
||||
"reference": "6271e66ce37545bd2edcddbe6bcbdd3b665ab7b8"
|
||||
"reference": "eeff19808f8ae3a6f7c4e43e388a2848eb2b0865"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan-doctrine/zipball/6271e66ce37545bd2edcddbe6bcbdd3b665ab7b8",
|
||||
"reference": "6271e66ce37545bd2edcddbe6bcbdd3b665ab7b8",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan-doctrine/zipball/eeff19808f8ae3a6f7c4e43e388a2848eb2b0865",
|
||||
"reference": "eeff19808f8ae3a6f7c4e43e388a2848eb2b0865",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -17949,9 +17949,9 @@
|
|||
"description": "Doctrine extensions for PHPStan",
|
||||
"support": {
|
||||
"issues": "https://github.com/phpstan/phpstan-doctrine/issues",
|
||||
"source": "https://github.com/phpstan/phpstan-doctrine/tree/2.0.4"
|
||||
"source": "https://github.com/phpstan/phpstan-doctrine/tree/2.0.5"
|
||||
},
|
||||
"time": "2025-07-17T11:57:55+00:00"
|
||||
"time": "2025-09-07T11:52:30+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan-strict-rules",
|
||||
|
|
@ -18003,16 +18003,16 @@
|
|||
},
|
||||
{
|
||||
"name": "phpstan/phpstan-symfony",
|
||||
"version": "2.0.7",
|
||||
"version": "2.0.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpstan/phpstan-symfony.git",
|
||||
"reference": "392f7ab8f52a0a776977be4e62535358c28e1b15"
|
||||
"reference": "8820c22d785c235f69bb48da3d41e688bc8a1796"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan-symfony/zipball/392f7ab8f52a0a776977be4e62535358c28e1b15",
|
||||
"reference": "392f7ab8f52a0a776977be4e62535358c28e1b15",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan-symfony/zipball/8820c22d785c235f69bb48da3d41e688bc8a1796",
|
||||
"reference": "8820c22d785c235f69bb48da3d41e688bc8a1796",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -18068,9 +18068,9 @@
|
|||
"description": "Symfony Framework extensions and rules for PHPStan",
|
||||
"support": {
|
||||
"issues": "https://github.com/phpstan/phpstan-symfony/issues",
|
||||
"source": "https://github.com/phpstan/phpstan-symfony/tree/2.0.7"
|
||||
"source": "https://github.com/phpstan/phpstan-symfony/tree/2.0.8"
|
||||
},
|
||||
"time": "2025-07-22T09:40:57+00:00"
|
||||
"time": "2025-09-07T06:55:50+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-code-coverage",
|
||||
|
|
|
|||
|
|
@ -5,4 +5,11 @@ jbtronics_settings:
|
|||
default_cacheable: true
|
||||
|
||||
orm_storage:
|
||||
default_entity_class: App\Entity\SettingsEntry
|
||||
default_entity_class: App\Entity\SettingsEntry
|
||||
|
||||
|
||||
# Disable caching for development environment
|
||||
when@dev:
|
||||
jbtronics_settings:
|
||||
cache:
|
||||
default_cacheable: false
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ namespace App\Controller;
|
|||
|
||||
use App\DataTables\AttachmentDataTable;
|
||||
use App\DataTables\Filters\AttachmentFilter;
|
||||
use App\DataTables\PartsDataTable;
|
||||
use App\Entity\Attachments\Attachment;
|
||||
use App\Form\Filters\AttachmentFilterType;
|
||||
use App\Services\Attachments\AttachmentManager;
|
||||
|
|
@ -112,7 +113,7 @@ class AttachmentFileController extends AbstractController
|
|||
|
||||
$filterForm->handleRequest($formRequest);
|
||||
|
||||
$table = $dataTableFactory->createFromType(AttachmentDataTable::class, ['filter' => $filter], ['pageLength' => $tableSettings->fullDefaultPageSize])
|
||||
$table = $dataTableFactory->createFromType(AttachmentDataTable::class, ['filter' => $filter], ['pageLength' => $tableSettings->fullDefaultPageSize, 'lengthMenu' => PartsDataTable::LENGTH_MENU])
|
||||
->handleRequest($request);
|
||||
|
||||
if ($table->isCallback()) {
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ use App\Services\InfoProviderSystem\ExistingPartFinder;
|
|||
use App\Services\InfoProviderSystem\PartInfoRetriever;
|
||||
use App\Services\InfoProviderSystem\ProviderRegistry;
|
||||
use App\Settings\AppSettings;
|
||||
use App\Settings\InfoProviderSystem\InfoProviderGeneralSettings;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Jbtronics\SettingsBundle\Form\SettingsFormFactoryInterface;
|
||||
use Jbtronics\SettingsBundle\Manager\SettingsManagerInterface;
|
||||
|
|
@ -113,7 +114,7 @@ class InfoProviderController extends AbstractController
|
|||
|
||||
#[Route('/search', name: 'info_providers_search')]
|
||||
#[Route('/update/{target}', name: 'info_providers_update_part_search')]
|
||||
public function search(Request $request, #[MapEntity(id: 'target')] ?Part $update_target, LoggerInterface $exceptionLogger): Response
|
||||
public function search(Request $request, #[MapEntity(id: 'target')] ?Part $update_target, LoggerInterface $exceptionLogger, InfoProviderGeneralSettings $infoProviderSettings): Response
|
||||
{
|
||||
$this->denyAccessUnlessGranted('@info_providers.create_parts');
|
||||
|
||||
|
|
@ -144,6 +145,23 @@ class InfoProviderController extends AbstractController
|
|||
}
|
||||
}
|
||||
|
||||
//If the providers form is still empty, use our default value from the settings
|
||||
if (count($form->get('providers')->getData() ?? []) === 0) {
|
||||
$default_providers = $infoProviderSettings->defaultSearchProviders;
|
||||
$provider_objects = [];
|
||||
foreach ($default_providers as $provider_key) {
|
||||
try {
|
||||
$tmp = $this->providerRegistry->getProviderByKey($provider_key);
|
||||
if ($tmp->isActive()) {
|
||||
$provider_objects[] = $tmp;
|
||||
}
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
//If the provider is not found, just ignore it
|
||||
}
|
||||
}
|
||||
$form->get('providers')->setData($provider_objects);
|
||||
}
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
$keyword = $form->get('keyword')->getData();
|
||||
$providers = $form->get('providers')->getData();
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ use App\Services\Parameters\ParameterExtractor;
|
|||
use App\Services\Parts\PartLotWithdrawAddHelper;
|
||||
use App\Services\Parts\PricedetailHelper;
|
||||
use App\Services\ProjectSystem\ProjectBuildPartHelper;
|
||||
use App\Settings\BehaviorSettings\PartInfoSettings;
|
||||
use DateTime;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Exception;
|
||||
|
|
@ -69,7 +70,7 @@ class PartController extends AbstractController
|
|||
protected PartPreviewGenerator $partPreviewGenerator,
|
||||
private readonly TranslatorInterface $translator,
|
||||
private readonly AttachmentSubmitHandler $attachmentSubmitHandler, private readonly EntityManagerInterface $em,
|
||||
protected EventCommentHelper $commentHelper)
|
||||
protected EventCommentHelper $commentHelper, private readonly PartInfoSettings $partInfoSettings)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -119,8 +120,8 @@ class PartController extends AbstractController
|
|||
'pricedetail_helper' => $this->pricedetailHelper,
|
||||
'pictures' => $this->partPreviewGenerator->getPreviewAttachments($part),
|
||||
'timeTravel' => $timeTravel_timestamp,
|
||||
'description_params' => $parameterExtractor->extractParameters($part->getDescription()),
|
||||
'comment_params' => $parameterExtractor->extractParameters($part->getComment()),
|
||||
'description_params' => $this->partInfoSettings->extractParamsFromDescription ? $parameterExtractor->extractParameters($part->getDescription()) : [],
|
||||
'comment_params' => $this->partInfoSettings->extractParamsFromNotes ? $parameterExtractor->extractParameters($part->getComment()) : [],
|
||||
'withdraw_add_helper' => $withdrawAddHelper,
|
||||
]
|
||||
);
|
||||
|
|
|
|||
|
|
@ -161,7 +161,9 @@ class PartListsController extends AbstractController
|
|||
|
||||
$filterForm->handleRequest($formRequest);
|
||||
|
||||
$table = $this->dataTableFactory->createFromType(PartsDataTable::class, array_merge(['filter' => $filter], $additional_table_vars), ['pageLength' => $this->tableSettings->fullDefaultPageSize])
|
||||
$table = $this->dataTableFactory->createFromType(PartsDataTable::class, array_merge(
|
||||
['filter' => $filter], $additional_table_vars),
|
||||
['pageLength' => $this->tableSettings->fullDefaultPageSize, 'lengthMenu' => PartsDataTable::LENGTH_MENU])
|
||||
->handleRequest($request);
|
||||
|
||||
if ($table->isCallback()) {
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ use App\Services\InfoProviderSystem\Providers\InfoProviderInterface;
|
|||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\ChoiceList\ChoiceList;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\OptionsResolver\Options;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
class ProviderSelectType extends AbstractType
|
||||
|
|
@ -44,13 +45,43 @@ class ProviderSelectType extends AbstractType
|
|||
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
{
|
||||
$resolver->setDefaults([
|
||||
'choices' => $this->providerRegistry->getActiveProviders(),
|
||||
'choice_label' => ChoiceList::label($this, static fn (?InfoProviderInterface $choice) => $choice?->getProviderInfo()['name']),
|
||||
'choice_value' => ChoiceList::value($this, static fn(?InfoProviderInterface $choice) => $choice?->getProviderKey()),
|
||||
$providers = $this->providerRegistry->getActiveProviders();
|
||||
|
||||
'multiple' => true,
|
||||
]);
|
||||
$resolver->setDefault('input', 'object');
|
||||
$resolver->setAllowedTypes('input', 'string');
|
||||
//Either the form returns the provider objects or their keys
|
||||
$resolver->setAllowedValues('input', ['object', 'string']);
|
||||
$resolver->setDefault('multiple', true);
|
||||
|
||||
$resolver->setDefault('choices', function (Options $options) use ($providers) {
|
||||
if ('object' === $options['input']) {
|
||||
return $this->providerRegistry->getActiveProviders();
|
||||
}
|
||||
|
||||
$tmp = [];
|
||||
foreach ($providers as $provider) {
|
||||
$name = $provider->getProviderInfo()['name'];
|
||||
$tmp[$name] = $provider->getProviderKey();
|
||||
}
|
||||
|
||||
return $tmp;
|
||||
});
|
||||
|
||||
//The choice_label and choice_value only needs to be set if we want the objects
|
||||
$resolver->setDefault('choice_label', function (Options $options){
|
||||
if ('object' === $options['input']) {
|
||||
return ChoiceList::label($this, static fn (?InfoProviderInterface $choice) => $choice?->getProviderInfo()['name']);
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
$resolver->setDefault('choice_value', function (Options $options) {
|
||||
if ('object' === $options['input']) {
|
||||
return ChoiceList::value($this, static fn(?InfoProviderInterface $choice) => $choice?->getProviderKey());
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,4 +40,10 @@ class PartInfoSettings
|
|||
#[SettingsParameter(label: new TM("settings.behavior.part_info.show_part_image_overlay"), description: new TM("settings.behavior.part_info.show_part_image_overlay.help"),
|
||||
envVar: "bool:SHOW_PART_IMAGE_OVERLAY", envVarMode: EnvVarMode::OVERWRITE)]
|
||||
public bool $showPartImageOverlay = true;
|
||||
}
|
||||
|
||||
#[SettingsParameter(label: new TM("settings.behavior.part_info.extract_params_from_description"))]
|
||||
public bool $extractParamsFromDescription = true;
|
||||
|
||||
#[SettingsParameter(label: new TM("settings.behavior.part_info.extract_params_from_notes"))]
|
||||
public bool $extractParamsFromNotes = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,6 +70,20 @@ class TableSettings
|
|||
PartTableColumns::CATEGORY, PartTableColumns::FOOTPRINT, PartTableColumns::MANUFACTURER,
|
||||
PartTableColumns::LOCATION, PartTableColumns::AMOUNT];
|
||||
|
||||
#[SettingsParameter(label: new TM("settings.behavior.table.preview_image_min_width"),
|
||||
formOptions: ['attr' => ['min' => 1, 'max' => 100]],
|
||||
envVar: "int:TABLE_IMAGE_PREVIEW_MIN_SIZE", envVarMode: EnvVarMode::OVERWRITE
|
||||
)]
|
||||
#[Assert\Range(min: 1, max: 100)]
|
||||
public int $previewImageMinWidth = 20;
|
||||
|
||||
#[SettingsParameter(label: new TM("settings.behavior.table.preview_image_max_width"),
|
||||
formOptions: ['attr' => ['min' => 1, 'max' => 100]],
|
||||
envVar: "int:TABLE_IMAGE_PREVIEW_MAX_SIZE", envVarMode: EnvVarMode::OVERWRITE
|
||||
)]
|
||||
#[Assert\Range(min: 1, max: 100)]
|
||||
#[Assert\GreaterThanOrEqual(propertyPath: 'previewImageMinWidth')]
|
||||
public int $previewImageMaxWidth = 35;
|
||||
|
||||
public static function mapPartsDefaultColumnsEnv(string $columns): array
|
||||
{
|
||||
|
|
@ -87,4 +101,4 @@ class TableSettings
|
|||
return $ret;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,45 @@
|
|||
<?php
|
||||
/*
|
||||
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
|
||||
*
|
||||
* Copyright (C) 2019 - 2025 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\Settings\InfoProviderSystem;
|
||||
|
||||
use App\Form\InfoProviderSystem\ProviderSelectType;
|
||||
use App\Settings\SettingsIcon;
|
||||
use Jbtronics\SettingsBundle\ParameterTypes\ArrayType;
|
||||
use Jbtronics\SettingsBundle\ParameterTypes\StringType;
|
||||
use Jbtronics\SettingsBundle\Settings\Settings;
|
||||
use Jbtronics\SettingsBundle\Settings\SettingsParameter;
|
||||
use Symfony\Component\Translation\TranslatableMessage as TM;
|
||||
|
||||
#[Settings(label: new TM("settings.ips.general"))]
|
||||
#[SettingsIcon("fa-magnifying-glass")]
|
||||
class InfoProviderGeneralSettings
|
||||
{
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
#[SettingsParameter(type: ArrayType::class, label: new TM("settings.ips.default_providers"),
|
||||
description: new TM("settings.ips.default_providers.help"), options: ['type' => StringType::class],
|
||||
formType: ProviderSelectType::class, formOptions: ['input' => 'string'])]
|
||||
public array $defaultSearchProviders = [];
|
||||
}
|
||||
|
|
@ -25,6 +25,7 @@ namespace App\Settings\InfoProviderSystem;
|
|||
|
||||
use Jbtronics\SettingsBundle\Settings\EmbeddedSettings;
|
||||
use Jbtronics\SettingsBundle\Settings\Settings;
|
||||
use Jbtronics\SettingsBundle\Settings\SettingsParameter;
|
||||
use Jbtronics\SettingsBundle\Settings\SettingsTrait;
|
||||
|
||||
#[Settings()]
|
||||
|
|
@ -32,6 +33,9 @@ class InfoProviderSettings
|
|||
{
|
||||
use SettingsTrait;
|
||||
|
||||
#[EmbeddedSettings]
|
||||
public ?InfoProviderGeneralSettings $general = null;
|
||||
|
||||
#[EmbeddedSettings]
|
||||
public ?DigikeySettings $digikey = null;
|
||||
|
||||
|
|
@ -58,4 +62,4 @@ class InfoProviderSettings
|
|||
|
||||
#[EmbeddedSettings]
|
||||
public ?PollinSettings $pollin = null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,10 +28,13 @@ use App\Form\Type\ThemeChoiceType;
|
|||
use App\Settings\SettingsIcon;
|
||||
use App\Validator\Constraints\ValidTheme;
|
||||
use Jbtronics\SettingsBundle\Metadata\EnvVarMode;
|
||||
use Jbtronics\SettingsBundle\ParameterTypes\ArrayType;
|
||||
use Jbtronics\SettingsBundle\ParameterTypes\EnumType;
|
||||
use Jbtronics\SettingsBundle\Settings\Settings;
|
||||
use Jbtronics\SettingsBundle\Settings\SettingsParameter;
|
||||
use Jbtronics\SettingsBundle\Settings\SettingsTrait;
|
||||
use Symfony\Component\Translation\TranslatableMessage as TM;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
#[Settings(name: "customization", label: new TM("settings.system.customization"))]
|
||||
#[SettingsIcon("fa-paint-roller")]
|
||||
|
|
@ -46,6 +49,13 @@ class CustomizationSettings
|
|||
)]
|
||||
public string $instanceName = "Part-DB";
|
||||
|
||||
#[SettingsParameter(
|
||||
label: new TM("settings.system.customization.theme"),
|
||||
formType: ThemeChoiceType::class, formOptions: ['placeholder' => false]
|
||||
)]
|
||||
#[ValidTheme]
|
||||
public string $theme = 'bootstrap';
|
||||
|
||||
#[SettingsParameter(
|
||||
label: new TM("settings.system.customization.banner"),
|
||||
formType: RichTextEditorType::class, formOptions: ['mode' => 'markdown-full'],
|
||||
|
|
@ -53,10 +63,22 @@ class CustomizationSettings
|
|||
)]
|
||||
public ?string $banner = null;
|
||||
|
||||
#[SettingsParameter(
|
||||
label: new TM("settings.system.customization.theme"),
|
||||
formType: ThemeChoiceType::class, formOptions: ['placeholder' => false]
|
||||
/**
|
||||
* @var HomepageItems[] The items to show in the sidebar.
|
||||
*/
|
||||
#[SettingsParameter(ArrayType::class,
|
||||
label: new TM("settings.behavior.hompepage.items"),
|
||||
description: new TM("settings.behavior.homepage.items.help"),
|
||||
options: ['type' => EnumType::class, 'options' => ['class' => HomepageItems::class]],
|
||||
formType: \Symfony\Component\Form\Extension\Core\Type\EnumType::class,
|
||||
formOptions: ['class' => HomepageItems::class, 'multiple' => true, 'ordered' => true]
|
||||
)]
|
||||
#[ValidTheme]
|
||||
public string $theme = 'bootstrap';
|
||||
#[Assert\NotBlank()]
|
||||
#[Assert\Unique()]
|
||||
public array $homepageitems = [HomepageItems::SEARCH, HomepageItems::BANNER, HomepageItems::FIRST_STEPS, HomepageItems::LICENSE, HomepageItems::LAST_ACTIVITY];
|
||||
|
||||
#[SettingsParameter(
|
||||
label: new TM("settings.system.customization.showVersionOnHomepage")
|
||||
)]
|
||||
public bool $showVersionOnHomepage = true;
|
||||
}
|
||||
|
|
|
|||
51
src/Settings/SystemSettings/HomepageItems.php
Normal file
51
src/Settings/SystemSettings/HomepageItems.php
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
/*
|
||||
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
|
||||
*
|
||||
* Copyright (C) 2019 - 2025 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\Settings\SystemSettings;
|
||||
|
||||
use Symfony\Contracts\Translation\TranslatableInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
use function Symfony\Component\Translation\t;
|
||||
|
||||
enum HomepageItems: string implements TranslatableInterface
|
||||
{
|
||||
case SEARCH = 'search';
|
||||
case BANNER = 'banner';
|
||||
case LICENSE = 'license';
|
||||
case FIRST_STEPS = 'first_steps';
|
||||
case LAST_ACTIVITY = 'last_activity';
|
||||
|
||||
public function trans(TranslatorInterface $translator, ?string $locale = null): string
|
||||
{
|
||||
$key = match($this) {
|
||||
self::SEARCH => 'search.placeholder',
|
||||
self::BANNER => 'settings.system.customization.banner',
|
||||
self::LICENSE => 'homepage.license',
|
||||
self::FIRST_STEPS => 'homepage.first_steps.title',
|
||||
self::LAST_ACTIVITY => 'homepage.last_activity',
|
||||
};
|
||||
|
||||
return $translator->trans($key, locale: $locale);
|
||||
}
|
||||
}
|
||||
|
|
@ -53,6 +53,14 @@
|
|||
{% endif %}
|
||||
|
||||
{{ encore_entry_link_tags('app') }}
|
||||
|
||||
{% set table_settings = settings_instance('table') %}
|
||||
<style nonce="{{ csp_nonce('style') }}">
|
||||
:root {
|
||||
--table-image-preview-min-size: {{ table_settings.previewImageMinWidth }}px;
|
||||
--table-image-preview-max-size: {{ table_settings.previewImageMaxWidth }}px;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block javascripts %}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
<input type="hidden" name="ids" {{ stimulus_target('elements/datatables/parts', 'selectIDs') }} value="">
|
||||
|
||||
<div class="d-none mb-2" {{ stimulus_target('elements/datatables/parts', 'selectPanel') }}>
|
||||
<div class="d-none mb-2 bg-body-tertiary shadow-sm border border-secondary rounded mx-2 p-2" {{ stimulus_target('elements/datatables/parts', 'selectPanel') }}>
|
||||
{# <span id="select_count"></span> #}
|
||||
|
||||
<div class="input-group">
|
||||
|
|
@ -95,4 +95,4 @@
|
|||
</div>
|
||||
</form>
|
||||
|
||||
{% endmacro %}
|
||||
{% endmacro %}
|
||||
|
|
|
|||
|
|
@ -4,26 +4,23 @@
|
|||
{% import "components/search.macro.html.twig" as search %}
|
||||
{% import "vars.macro.twig" as vars %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
{% if is_granted('@system.show_updates') %}
|
||||
{{ nv.new_version_alert(new_version_available, new_version, new_version_url) }}
|
||||
{% endif %}
|
||||
|
||||
{% block item_search %}
|
||||
{% if is_granted('@parts.read') %}
|
||||
{{ search.search_form("standalone") }}
|
||||
<div class="mb-2"></div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block item_banner %}
|
||||
<div class="rounded p-4 bg-body-secondary">
|
||||
<h1 class="display-3">{{ vars.partdb_title() }}</h1>
|
||||
<h4>
|
||||
{% trans %}version.caption{% endtrans %}: {{ shivas_app_version }}
|
||||
{% if git_branch is not empty or git_commit is not empty %}
|
||||
({{ git_branch ?? '' }}/{{ git_commit ?? '' }})
|
||||
{% endif %}
|
||||
</h4>
|
||||
{% if settings_instance('customization').showVersionOnHomepage %}
|
||||
<h4>
|
||||
{% trans %}version.caption{% endtrans %}: {{ shivas_app_version }}
|
||||
{% if git_branch is not empty or git_commit is not empty %}
|
||||
({{ git_branch ?? '' }}/{{ git_commit ?? '' }})
|
||||
{% endif %}
|
||||
</h4>
|
||||
{% endif %}
|
||||
{% if banner is not empty %}
|
||||
<hr>
|
||||
<div class="latex" data-controller="common--latex">
|
||||
|
|
@ -31,9 +28,11 @@
|
|||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block item_first_steps %}
|
||||
{% if show_first_steps %}
|
||||
<div class="card border-info mt-3">
|
||||
<div class="card border-info">
|
||||
<div class="card-header bg-info ">
|
||||
<h4><i class="fa fa-circle-play fa-fw " aria-hidden="true"></i> {% trans %}homepage.first_steps.title{% endtrans %}</h4>
|
||||
</div>
|
||||
|
|
@ -51,8 +50,10 @@
|
|||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
<div class="card border-primary mt-3">
|
||||
{% block item_license %}
|
||||
<div class="card border-primary">
|
||||
<div class="card-header bg-primary text-white">
|
||||
<h4><i class="fa fa-book fa-fw" aria-hidden="true"></i> {% trans %}homepage.license{% endtrans %}</h4>
|
||||
</div>
|
||||
|
|
@ -68,9 +69,11 @@
|
|||
<strong><i class="fas fa-comments fa-fw"></i> {% trans %}homepage.forum.caption{% endtrans %}:</strong> {% trans with {'%href%': 'https://github.com/Part-DB/Part-DB-server/discussions'}%}homepage.forum.text{% endtrans %}<br>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block item_last_activity %}
|
||||
{% if datatable is not null %}
|
||||
<div class="card mt-3">
|
||||
<div class="card">
|
||||
<div class="card-header"><i class="fas fa-fw fa-history"></i> {% trans %}homepage.last_activity{% endtrans %}</div>
|
||||
<div class="card-body">
|
||||
{% import "components/history_log_macros.html.twig" as log %}
|
||||
|
|
@ -78,4 +81,23 @@
|
|||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
{% if is_granted('@system.show_updates') %}
|
||||
{{ nv.new_version_alert(new_version_available, new_version, new_version_url) }}
|
||||
{% endif %}
|
||||
|
||||
{% for item in settings_instance('customization').homepageitems %}
|
||||
{% if block('item_' ~ item.value) is defined %}
|
||||
{{ block('item_' ~ item.value) }}
|
||||
<div class="mb-2"></div>
|
||||
{% else %}
|
||||
<div class="alert alert-warning mt-3" role="alert">
|
||||
Alert: The homepage item "{{ item.value }}" is not defined!
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% endblock %}
|
||||
|
|
|
|||
|
|
@ -13056,5 +13056,389 @@ Bitte beachten Sie, dass Sie sich nicht als deaktivierter Benutzer ausgeben kön
|
|||
<target>Aus Sicherheitsgründen ausgeblendet</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="J716Oh4" name="project.bom_import.map_fields">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.map_fields</source>
|
||||
<target>Spalten zuordnen</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="wvT5Xvn" name="project.bom_import.map_fields.help">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.map_fields.help</source>
|
||||
<target>Wählen Sie aus, wie CSV Spalten auf BOM Felder gemappt werden</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="nh7uLPe" name="project.bom_import.delimiter">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.delimiter</source>
|
||||
<target>Trennzeichen</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="MSlSeE4" name="project.bom_import.delimiter.comma">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.delimiter.comma</source>
|
||||
<target>Komma (,)</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="UdDSB0h" name="project.bom_import.delimiter.semicolon">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.delimiter.semicolon</source>
|
||||
<target>Semikolon (;)</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="Wpa4Gmf" name="project.bom_import.delimiter.tab">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.delimiter.tab</source>
|
||||
<target>Tab</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="tjrG_vU" name="project.bom_import.field_mapping.title">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.field_mapping.title</source>
|
||||
<target>Spaltenzuordnung</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="nWu8B7R" name="project.bom_import.field_mapping.csv_field">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.field_mapping.csv_field</source>
|
||||
<target>CSV Spalte</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="D0KlFqm" name="project.bom_import.field_mapping.maps_to">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.field_mapping.maps_to</source>
|
||||
<target>Mappt auf</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="rhUpmxC" name="project.bom_import.field_mapping.suggestion">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.field_mapping.suggestion</source>
|
||||
<target>Vorschlag</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="TM0mgKr" name="project.bom_import.field_mapping.priority">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.field_mapping.priority</source>
|
||||
<target>Priorität</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="xY8NSRr" name="project.bom_import.field_mapping.priority_help">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.field_mapping.priority_help</source>
|
||||
<target>Priorität (kleinere Nummer = höhere Priorität)</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="CuXg8WU" name="project.bom_import.field_mapping.priority_short">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.field_mapping.priority_short</source>
|
||||
<target>P</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="jOHOShN" name="project.bom_import.field_mapping.priority_note">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.field_mapping.priority_note</source>
|
||||
<target>Prioritätstipp: Niedrigere Zahlen = höhere Priorität. Die Standardpriorität ist 10. Verwenden Sie die Prioritäten 1–9 für die wichtigsten Felder und 10+ für normale Priorität.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="pvmv3OT" name="project.bom_import.field_mapping.summary">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.field_mapping.summary</source>
|
||||
<target>Zusammenfassung der Zuordnung</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="VjLf1Pf" name="project.bom_import.field_mapping.select_to_see_summary">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.field_mapping.select_to_see_summary</source>
|
||||
<target>Wählen Sie Zuordnungen aus, um eine Zusammenfassung anzuzeigen.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="JOPny6T" name="project.bom_import.field_mapping.no_suggestion">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.field_mapping.no_suggestion</source>
|
||||
<target>Kein Vorschlag</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="1LWEtqL" name="project.bom_import.preview">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.preview</source>
|
||||
<target>Vorschau</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="1CJA0aY" name="project.bom_import.flash.session_expired">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.flash.session_expired</source>
|
||||
<target>Die Import-Sitzung ist abgelaufen. Bitte laden Sie Ihre Datei erneut hoch.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="BLN7XRN" name="project.bom_import.field_mapping.ignore">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.field_mapping.ignore</source>
|
||||
<target>Ignorieren</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="yiIB3yV" name="project.bom_import.type.kicad_schematic">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.type.kicad_schematic</source>
|
||||
<target>KiCAD Schaltplaneditor BOM (CSV Datei)</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="ltE6xPP" name="common.back">
|
||||
<segment state="translated">
|
||||
<source>common.back</source>
|
||||
<target>Zurück</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="HCTqjZO" name="project.bom_import.validation.errors.required_field_missing">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.validation.errors.required_field_missing</source>
|
||||
<target>Zeile %line%: Das Pflichtfeld „%field%“ fehlt oder ist leer. Bitte stellen Sie sicher, dass dieses Feld zugeordnet ist und Daten enthält.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="_ua5YM7" name="project.bom_import.validation.errors.no_valid_designators">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.validation.errors.no_valid_designators</source>
|
||||
<target>Zeile %line%: Das Bezeichnungsfeld enthält keine gültigen Komponentenreferenzen. Erwartetes Format: „R1,C2,U3“ oder „R1, C2, U3“.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="xpkq3rW" name="project.bom_import.validation.warnings.unusual_designator_format">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.validation.warnings.unusual_designator_format</source>
|
||||
<target>Zeile %line%: Einige Komponentenreferenzen haben möglicherweise ein ungewöhnliches Format: %designators%. Erwartetes Format: „R1“, „C2“, „U3“ usw.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="M54Ud5d" name="project.bom_import.validation.errors.duplicate_designators">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.validation.errors.duplicate_designators</source>
|
||||
<target>Zeile %line%: Doppelte Komponentenreferenzen gefunden: %designators%. Jede Komponente sollte nur einmal pro Zeile referenziert werden.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="ZULFZh2" name="project.bom_import.validation.errors.invalid_quantity">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.validation.errors.invalid_quantity</source>
|
||||
<target>Zeile %line%: Die Menge „%quantity%“ ist keine gültige Zahl. Bitte geben Sie einen numerischen Wert ein (z. B. 1, 2,5, 10).</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="3WbRgsl" name="project.bom_import.validation.errors.quantity_zero_or_negative">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.validation.errors.quantity_zero_or_negative</source>
|
||||
<target>Zeile %line%: Die Menge muss größer als 0 sein, erhaltene Menge %quantity%.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="_nWGsSU" name="project.bom_import.validation.warnings.quantity_unusually_high">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.validation.warnings.quantity_unusually_high</source>
|
||||
<target>Zeile %line%: Die Menge %quantity% erscheint ungewöhnlich hoch. Bitte überprüfen Sie, ob dies korrekt ist.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="iJWw39f" name="project.bom_import.validation.warnings.quantity_not_whole_number">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.validation.warnings.quantity_not_whole_number</source>
|
||||
<target>Zeile %line%: Die Menge %quantity% ist keine ganze Zahl, aber Sie haben %count% Komponentenreferenzen. Dies kann auf eine Nichtübereinstimmung hindeuten.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="Zffmgvv" name="project.bom_import.validation.errors.quantity_designator_mismatch">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.validation.errors.quantity_designator_mismatch</source>
|
||||
<target>Zeile %line%: Diskrepanz zwischen Menge und Komponentenreferenzen. Menge: %quantity%, Referenzen: %count% (%designators%). Diese sollten übereinstimmen. Passen Sie entweder die Menge an oder überprüfen Sie Ihre Komponentenreferenzen.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="JqHpDIo" name="project.bom_import.validation.errors.invalid_partdb_id">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.validation.errors.invalid_partdb_id</source>
|
||||
<target>Zeile %line%: Part-DB ID „%id%“ ist keine gültige Zahl. Bitte geben Sie eine numerische ID ein.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="Mr7W6r0" name="project.bom_import.validation.errors.partdb_id_zero_or_negative">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.validation.errors.partdb_id_zero_or_negative</source>
|
||||
<target>Zeile %line%: Die Part-DB ID muss größer als 0 sein, erhaltene ID lautet %id%.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="gRH6IeR" name="project.bom_import.validation.warnings.partdb_id_not_found">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.validation.warnings.partdb_id_not_found</source>
|
||||
<target>Zeile %line%: Teil-DB-ID %id% nicht in der Datenbank gefunden. Die Komponente wird ohne Verknüpfung mit einem vorhandenen Teil importiert.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="eMfaBYo" name="project.bom_import.validation.info.partdb_link_success">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.validation.info.partdb_link_success</source>
|
||||
<target>Zeile %line%: Erfolgreich mit dem Bauteil „%name%“ (ID: %id%) verknüpft.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="b_m9p.f" name="project.bom_import.validation.warnings.no_component_name">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.validation.warnings.no_component_name</source>
|
||||
<target>Zeile %line%: Kein Komponentenname/keine Komponentenbezeichnung angegeben (MPN, Bezeichnung oder Wert). Die Komponente wird als „Unbekanntes Bauteil” bezeichnet.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id=".LAGdMe" name="project.bom_import.validation.warnings.package_name_too_long">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.validation.warnings.package_name_too_long</source>
|
||||
<target>Zeile %line%: Der Footprintname „%package%“ ist ungewöhnlich lang. Bitte überprüfen Sie, ob er korrekt ist.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="wFF49kl" name="project.bom_import.validation.info.library_prefix_detected">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.validation.info.library_prefix_detected</source>
|
||||
<target>Zeile %line%: Das Footprint „%package%“ enthält ein Bibliothekspräfix. Dieses wird beim Import automatisch entfernt.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="hEO2sxC" name="project.bom_import.validation.errors.non_numeric_field">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.validation.errors.non_numeric_field</source>
|
||||
<target>Zeile %line%: Das Feld „%field%“ enthält den nicht numerischen Wert „%value%“. Bitte geben Sie eine gültige Zahl ein.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="Ear_sUX" name="project.bom_import.validation.info.import_summary">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.validation.info.import_summary</source>
|
||||
<target>Importübersicht: %total% Einträge insgesamt, %valid% gültig, %invalid% mit Problemen.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="SqJZ97A" name="project.bom_import.validation.errors.summary">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.validation.errors.summary</source>
|
||||
<target>Es wurden %count% Validierungsfehler gefunden, die behoben werden müssen, bevor der Import fortgesetzt werden kann.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="s7dzFnp" name="project.bom_import.validation.warnings.summary">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.validation.warnings.summary</source>
|
||||
<target>Es wurden %count% Warnungen gefunden. Bitte überprüfen Sie diese Probleme, bevor Sie fortfahren.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="2KaAHmS" name="project.bom_import.validation.info.all_valid">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.validation.info.all_valid</source>
|
||||
<target>Alle Einträge haben die Validierung erfolgreich bestanden!</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="Lyb3BjK" name="project.bom_import.validation.summary">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.validation.summary</source>
|
||||
<target>Validierungsübersicht</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="DUM8GoE" name="project.bom_import.validation.total_entries">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.validation.total_entries</source>
|
||||
<target>Gesamtzahl der Einträge</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="AtLGGU2" name="project.bom_import.validation.valid_entries">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.validation.valid_entries</source>
|
||||
<target>Gültige Einträge</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="mgdn5v3" name="project.bom_import.validation.invalid_entries">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.validation.invalid_entries</source>
|
||||
<target>Ungültige Einträge</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="qmJ5BfF" name="project.bom_import.validation.success_rate">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.validation.success_rate</source>
|
||||
<target>Erfolgsquote</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="QyDsrFV" name="project.bom_import.validation.errors.title">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.validation.errors.title</source>
|
||||
<target>Validierungsfehler</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="d.Mvu0a" name="project.bom_import.validation.errors.description">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.validation.errors.description</source>
|
||||
<target>Die folgenden Fehler müssen behoben werden, bevor der Import fortgesetzt werden kann:</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="MGFfKr." name="project.bom_import.validation.warnings.title">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.validation.warnings.title</source>
|
||||
<target>Validierungswarnungen</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="tt4VxY6" name="project.bom_import.validation.warnings.description">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.validation.warnings.description</source>
|
||||
<target>Die folgenden Warnhinweise sollten vor dem Fortfahren gelesen werden:</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="YuAdYeh" name="project.bom_import.validation.info.title">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.validation.info.title</source>
|
||||
<target>Informationen</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="1pUfi7Q" name="project.bom_import.validation.details.title">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.validation.details.title</source>
|
||||
<target>Detaillierte Validierungsergebnisse</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="4Vv0Xns" name="project.bom_import.validation.details.line">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.validation.details.line</source>
|
||||
<target>Zeile</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="RbvD2zF" name="project.bom_import.validation.details.status">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.validation.details.status</source>
|
||||
<target>Status</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="iGtKkH_" name="project.bom_import.validation.details.messages">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.validation.details.messages</source>
|
||||
<target>Meldungen</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="IgdgZd8" name="project.bom_import.validation.details.valid">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.validation.details.valid</source>
|
||||
<target>Gültig</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="lWQEtkq" name="project.bom_import.validation.details.invalid">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.validation.details.invalid</source>
|
||||
<target>Ungültig</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="tPn6Ind" name="project.bom_import.validation.all_valid">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.validation.all_valid</source>
|
||||
<target>Alle Einträge sind gültig und bereit zum Import!</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="fzoGCaf" name="project.bom_import.validation.fix_errors">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.validation.fix_errors</source>
|
||||
<target>Bitte beheben Sie die Validierungsfehler, bevor Sie mit dem Import fortfahren.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="nc9MqUc" name="project.bom_import.type.generic_csv">
|
||||
<segment state="translated">
|
||||
<source>project.bom_import.type.generic_csv</source>
|
||||
<target>Generische CSV-Datei</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id=".N35Pvs" name="label_generator.update_profile">
|
||||
<segment state="translated">
|
||||
<source>label_generator.update_profile</source>
|
||||
<target>Profil mit aktuellen Einstellungen aktualisieren</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="ulTo6Aa" name="label_generator.profile_updated">
|
||||
<segment state="translated">
|
||||
<source>label_generator.profile_updated</source>
|
||||
<target>Labelprofil aktualisiert</target>
|
||||
</segment>
|
||||
</unit>
|
||||
</file>
|
||||
</xliff>
|
||||
|
|
|
|||
|
|
@ -13441,5 +13441,65 @@ Please note, that you can not impersonate a disabled user. If you try you will g
|
|||
<target>Label profile updated successfully.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="7lgFa7I" name="settings.behavior.hompepage.items">
|
||||
<segment>
|
||||
<source>settings.behavior.hompepage.items</source>
|
||||
<target>Homepage items</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="FsrRdkp" name="settings.behavior.homepage.items.help">
|
||||
<segment>
|
||||
<source>settings.behavior.homepage.items.help</source>
|
||||
<target><![CDATA[The items to show at the homepage. Order can be changed via drag & drop.]]></target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="CYw3_pS" name="settings.system.customization.showVersionOnHomepage">
|
||||
<segment>
|
||||
<source>settings.system.customization.showVersionOnHomepage</source>
|
||||
<target>Show Part-DB version on homepage</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="GLYhV9m" name="settings.behavior.part_info.extract_params_from_description">
|
||||
<segment>
|
||||
<source>settings.behavior.part_info.extract_params_from_description</source>
|
||||
<target>Extract parameters from part description</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="aYOedkN" name="settings.behavior.part_info.extract_params_from_notes">
|
||||
<segment>
|
||||
<source>settings.behavior.part_info.extract_params_from_notes</source>
|
||||
<target>Extract parameters from part notes</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="nCH2MW6" name="settings.ips.default_providers">
|
||||
<segment>
|
||||
<source>settings.ips.default_providers</source>
|
||||
<target>Default search providers</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="TLNoCLT" name="settings.ips.general">
|
||||
<segment>
|
||||
<source>settings.ips.general</source>
|
||||
<target>General settings</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="IDs2sXK" name="settings.ips.default_providers.help">
|
||||
<segment>
|
||||
<source>settings.ips.default_providers.help</source>
|
||||
<target>These providers will be preselected for searches in part providers.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="dv6eslZ" name="settings.behavior.table.preview_image_max_width">
|
||||
<segment>
|
||||
<source>settings.behavior.table.preview_image_max_width</source>
|
||||
<target>Preview image max width (px)</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="5bOoqEL" name="settings.behavior.table.preview_image_min_width">
|
||||
<segment>
|
||||
<source>settings.behavior.table.preview_image_min_width</source>
|
||||
<target>Preview image min width (px)</target>
|
||||
</segment>
|
||||
</unit>
|
||||
</file>
|
||||
</xliff>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue