diff --git a/.docker/partdb-entrypoint.sh b/.docker/partdb-entrypoint.sh index ffd2b24a..3b0326ac 100644 --- a/.docker/partdb-entrypoint.sh +++ b/.docker/partdb-entrypoint.sh @@ -20,6 +20,25 @@ set -e +# Pass all environment variables to PHP-FPM +# Path where PHP-FPM pool configs live +PHP_FPM_ENV_CONF="/etc/php/PHP_VERSION/fpm/pool.d/99-env.conf" + +# start fresh +echo "; auto-generated env config" > "$PHP_FPM_ENV_CONF" +echo "[www]" >> "$PHP_FPM_ENV_CONF" +echo "clear_env = no" >> "$PHP_FPM_ENV_CONF" + +# add all container envs +printenv | while IFS='=' read -r name value; do + case "$name" in + HOSTNAME|PWD|SHLVL|PATH|_*) continue ;; + esac + # write literal value in quotes + echo "env[$name] = \"$value\"" >> "$PHP_FPM_ENV_CONF" +done + + # recursive chowns can take a while, so we'll just do it if the owner is wrong # Chown uploads/ folder if it does not belong to www-data @@ -90,4 +109,4 @@ if [ "${1#-}" != "$1" ]; then fi # Pass to the original entrypoint -exec "$@" \ No newline at end of file +exec "$@" diff --git a/.docker/symfony.conf b/.docker/symfony.conf index 90c30e26..aa88eef2 100644 --- a/.docker/symfony.conf +++ b/.docker/symfony.conf @@ -24,34 +24,6 @@ ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined - # Pass the configuration from the docker env to the PHP environment (here you should list all .env options) - PassEnv APP_ENV APP_DEBUG APP_SECRET REDIRECT_TO_HTTPS DISABLE_YEAR2038_BUG_CHECK - PassEnv TRUSTED_PROXIES TRUSTED_HOSTS LOCK_DSN - PassEnv DATABASE_URL ENFORCE_CHANGE_COMMENTS_FOR DATABASE_MYSQL_USE_SSL_CA DATABASE_MYSQL_SSL_VERIFY_CERT - PassEnv DEFAULT_LANG DEFAULT_TIMEZONE BASE_CURRENCY INSTANCE_NAME ALLOW_ATTACHMENT_DOWNLOADS USE_GRAVATAR MAX_ATTACHMENT_FILE_SIZE DEFAULT_URI CHECK_FOR_UPDATES ATTACHMENT_DOWNLOAD_BY_DEFAULT - PassEnv MAILER_DSN ALLOW_EMAIL_PW_RESET EMAIL_SENDER_EMAIL EMAIL_SENDER_NAME - PassEnv HISTORY_SAVE_CHANGED_FIELDS HISTORY_SAVE_CHANGED_DATA HISTORY_SAVE_REMOVED_DATA HISTORY_SAVE_NEW_DATA - PassEnv ERROR_PAGE_ADMIN_EMAIL ERROR_PAGE_SHOW_HELP - PassEnv DEMO_MODE NO_URL_REWRITE_AVAILABLE FIXER_API_KEY BANNER - # In old version the SAML sp private key env, was wrongly named SAMLP_SP_PRIVATE_KEY, keep it for backward compatibility - PassEnv SAML_ENABLED SAML_BEHIND_PROXY SAML_ROLE_MAPPING SAML_UPDATE_GROUP_ON_LOGIN SAML_IDP_ENTITY_ID SAML_IDP_SINGLE_SIGN_ON_SERVICE SAML_IDP_SINGLE_LOGOUT_SERVICE SAML_IDP_X509_CERT SAML_SP_ENTITY_ID SAML_SP_X509_CERT SAML_SP_PRIVATE_KEY SAMLP_SP_PRIVATE_KEY - PassEnv TABLE_DEFAULT_PAGE_SIZE TABLE_PARTS_DEFAULT_COLUMNS - - PassEnv PROVIDER_DIGIKEY_CLIENT_ID PROVIDER_DIGIKEY_SECRET PROVIDER_DIGIKEY_CURRENCY PROVIDER_DIGIKEY_LANGUAGE PROVIDER_DIGIKEY_COUNTRY - PassEnv PROVIDER_ELEMENT14_KEY PROVIDER_ELEMENT14_STORE_ID - PassEnv PROVIDER_TME_KEY PROVIDER_TME_SECRET PROVIDER_TME_CURRENCY PROVIDER_TME_LANGUAGE PROVIDER_TME_COUNTRY PROVIDER_TME_GET_GROSS_PRICES - PassEnv PROVIDER_OCTOPART_CLIENT_ID PROVIDER_OCTOPART_SECRET PROVIDER_OCTOPART_CURRENCY PROVIDER_OCTOPART_COUNTRY PROVIDER_OCTOPART_SEARCH_LIMIT PROVIDER_OCTOPART_ONLY_AUTHORIZED_SELLERS - PassEnv PROVIDER_MOUSER_KEY PROVIDER_MOUSER_SEARCH_OPTION PROVIDER_MOUSER_SEARCH_LIMIT PROVIDER_MOUSER_SEARCH_WITH_SIGNUP_LANGUAGE - PassEnv PROVIDER_LCSC_ENABLED PROVIDER_LCSC_CURRENCY - PassEnv PROVIDER_OEMSECRETS_KEY PROVIDER_OEMSECRETS_COUNTRY_CODE PROVIDER_OEMSECRETS_CURRENCY PROVIDER_OEMSECRETS_ZERO_PRICE PROVIDER_OEMSECRETS_SET_PARAM PROVIDER_OEMSECRETS_SORT_CRITERIA - PassEnv PROVIDER_REICHELT_ENABLED PROVIDER_REICHELT_CURRENCY PROVIDER_REICHELT_COUNTRY PROVIDER_REICHELT_LANGUAGE PROVIDER_REICHELT_INCLUDE_VAT - PassEnv PROVIDER_POLLIN_ENABLED - PassEnv EDA_KICAD_CATEGORY_DEPTH - PassEnv SHOW_PART_IMAGE_OVERLAY - - # Proxy configuration env - PassEnv NO_PROXY HTTPS_PROXY HTTP_PROXY http_proxy https_proxy ALL_PROXY all_proxy - # For most configuration files from conf-available/, which are # enabled or disabled at a global level, it is possible to # include a line for only one particular virtual host. For example the diff --git a/.env b/.env index b51b1897..982d4bbd 100644 --- a/.env +++ b/.env @@ -31,13 +31,6 @@ DATABASE_EMULATE_NATURAL_SORT=0 # General settings ################################################################################### -# The language to use serverwide as default (en, de, ru, etc.) -#DEFAULT_LANG="en" -# The default timezone to use serverwide (e.g. Europe/Berlin) -#DEFAULT_TIMEZONE="Europe/Berlin" -# The currency that is used inside the DB (and is assumed when no currency is set). This can not be changed later, so be sure to set it the currency used in your country -#BASE_CURRENCY="EUR" - # The public reachable URL of this Part-DB installation. This is used for generating links in SAML and email templates # This must end with a slash! DEFAULT_URI="https://partdb.changeme.invalid/" @@ -68,15 +61,6 @@ ERROR_PAGE_ADMIN_EMAIL='' ERROR_PAGE_SHOW_HELP=1 -################################################################################## -# EDA integration related settings -################################################################################## - -# This value determines the depth of the category tree, that is visible inside KiCad -# 0 means that only the top level categories are visible. Set to a value > 0 to show more levels. -# Set to -1, to show all parts of Part-DB inside a sigle cnategory in KiCad -#EDA_KICAD_CATEGORY_DEPTH=0 - ################################################################################### # SAML Single sign on-settings ################################################################################### @@ -149,5 +133,5 @@ CORS_ALLOW_ORIGIN='^https?://(localhost|127\.0\.0\.1)(:[0-9]+)?$' ###> symfony/framework-bundle ### APP_ENV=prod -APP_SECRET= +APP_SECRET=a03498528f5a5fc089273ec9ae5b2849 ###< symfony/framework-bundle ### diff --git a/.github/workflows/assets_artifact_build.yml b/.github/workflows/assets_artifact_build.yml index 09dbbe38..c950375b 100644 --- a/.github/workflows/assets_artifact_build.yml +++ b/.github/workflows/assets_artifact_build.yml @@ -1,5 +1,8 @@ name: Build assets artifact +permissions: + contents: read + on: push: branches: @@ -19,7 +22,7 @@ jobs: APP_ENV: prod steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Setup PHP uses: shivammathur/setup-php@v2 diff --git a/.github/workflows/docker_build.yml b/.github/workflows/docker_build.yml index 64287d83..c912e769 100644 --- a/.github/workflows/docker_build.yml +++ b/.github/workflows/docker_build.yml @@ -1,5 +1,8 @@ name: Docker Image Build +permissions: + contents: read + on: #schedule: # - cron: '0 10 * * *' # everyday at 10am @@ -17,7 +20,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Docker meta id: docker_meta @@ -73,4 +76,4 @@ jobs: tags: ${{ steps.docker_meta.outputs.tags }} labels: ${{ steps.docker_meta.outputs.labels }} cache-from: type=gha - cache-to: type=gha,mode=max \ No newline at end of file + cache-to: type=gha,mode=max diff --git a/.github/workflows/docker_frankenphp.yml b/.github/workflows/docker_frankenphp.yml index d8cd0695..0b2eb874 100644 --- a/.github/workflows/docker_frankenphp.yml +++ b/.github/workflows/docker_frankenphp.yml @@ -1,5 +1,8 @@ name: Docker Image Build (FrankenPHP) +permissions: + contents: read + on: #schedule: # - cron: '0 10 * * *' # everyday at 10am @@ -17,7 +20,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Docker meta id: docker_meta @@ -74,4 +77,4 @@ jobs: tags: ${{ steps.docker_meta.outputs.tags }} labels: ${{ steps.docker_meta.outputs.labels }} cache-from: type=gha - cache-to: type=gha,mode=max \ No newline at end of file + cache-to: type=gha,mode=max diff --git a/.github/workflows/static_analysis.yml b/.github/workflows/static_analysis.yml index 20150b28..1de98ee9 100644 --- a/.github/workflows/static_analysis.yml +++ b/.github/workflows/static_analysis.yml @@ -1,5 +1,8 @@ name: Static analysis +permissions: + contents: read + on: push: branches: @@ -16,7 +19,7 @@ jobs: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Setup PHP uses: shivammathur/setup-php@v2 @@ -30,20 +33,20 @@ jobs: id: composer-cache run: | echo "::set-output name=dir::$(composer config cache-files-dir)" - + - uses: actions/cache@v4 with: path: ${{ steps.composer-cache.outputs.dir }} key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} restore-keys: | - ${{ runner.os }}-composer- + ${{ runner.os }}-composer- - name: Install dependencies run: composer install --prefer-dist --no-progress - name: Lint config files run: ./bin/console lint:yaml config --parse-tags - + - name: Lint twig templates run: ./bin/console lint:twig templates --env=prod @@ -53,13 +56,13 @@ jobs: - name: Check dependencies for security uses: symfonycorp/security-checker-action@v5 - + - name: Check doctrine mapping run: ./bin/console doctrine:schema:validate --skip-sync -vvv --no-interaction # Use the -d option to raise the max nesting level - name: Generate dev container run: php -d xdebug.max_nesting_level=1000 ./bin/console cache:clear --env dev - + - name: Run PHPstan run: composer phpstan diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 1233996e..66e2f40c 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -1,5 +1,8 @@ name: PHPUnit Tests +permissions: + contents: read + on: push: branches: @@ -43,7 +46,7 @@ jobs: if: matrix.db-type == 'postgres' - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Setup PHP uses: shivammathur/setup-php@v2 diff --git a/Dockerfile b/Dockerfile index 13a8d5c7..cb18c78f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -119,12 +119,12 @@ realpath_cache_size=4096K realpath_cache_ttl=600 EOF -# Increase upload limit and enable preloading +# Increase upload limit and enable preloading (disabled for now, as it does not seem to work properly, and require prod env anyway) COPY <. + */ + +import { Controller } from '@hotwired/stimulus'; +import '../css/components/toggle_password.css'; + +export default class extends Controller { + static values = { + visibleLabel: { type: String, default: 'Show' }, + visibleIcon: { type: String, default: 'Default' }, + hiddenLabel: { type: String, default: 'Hide' }, + hiddenIcon: { type: String, default: 'Default' }, + buttonClasses: Array, + }; + + isDisplayed = false; + visibleIcon = ` + + +`; + hiddenIcon = ` + + +`; + + connect() { + if (this.visibleIconValue !== 'Default') { + this.visibleIcon = this.visibleIconValue; + } + + if (this.hiddenIconValue !== 'Default') { + this.hiddenIcon = this.hiddenIconValue; + } + + const button = this.createButton(); + + this.element.insertAdjacentElement('afterend', button); + this.dispatchEvent('connect', { element: this.element, button }); + } + + /** + * @returns {HTMLButtonElement} + */ + createButton() { + const button = document.createElement('button'); + button.type = 'button'; + button.classList.add(...this.buttonClassesValue); + button.setAttribute('tabindex', '-1'); + button.addEventListener('click', this.toggle.bind(this)); + button.innerHTML = `${this.visibleIcon} ${this.visibleLabelValue}`; + return button; + } + + /** + * Toggle input type between "text" or "password" and update label accordingly + */ + toggle(event) { + this.isDisplayed = !this.isDisplayed; + const toggleButtonElement = event.currentTarget; + toggleButtonElement.innerHTML = this.isDisplayed + ? `${this.hiddenIcon} ${this.hiddenLabelValue}` + : `${this.visibleIcon} ${this.visibleLabelValue}`; + this.element.setAttribute('type', this.isDisplayed ? 'text' : 'password'); + this.dispatchEvent(this.isDisplayed ? 'show' : 'hide', { element: this.element, button: toggleButtonElement }); + } + + dispatchEvent(name, payload) { + this.dispatch(name, { detail: payload, prefix: 'toggle-password' }); + } +} diff --git a/assets/css/components/toggle_password.css b/assets/css/components/toggle_password.css new file mode 100644 index 00000000..f1f4a889 --- /dev/null +++ b/assets/css/components/toggle_password.css @@ -0,0 +1,41 @@ +/* + * 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 . + */ + +.toggle-password-container { + position: relative; +} +.toggle-password-icon { + height: 1rem; + width: 1rem; +} +.toggle-password-button { + align-items: center; + background-color: transparent; + border: none; + column-gap: 0.25rem; + display: flex; + flex-direction: row; + font-size: 0.875rem; + justify-items: center; + height: 1rem; + line-height: 1.25rem; + position: absolute; + right: 0.5rem; + top: -1.25rem; +} diff --git a/assets/js/lib/datatables.js b/assets/js/lib/datatables.js index 8e39548b..67bab02d 100644 --- a/assets/js/lib/datatables.js +++ b/assets/js/lib/datatables.js @@ -75,11 +75,10 @@ request._dt = config.name; //Try to resolve the original column index when the column was reordered (using the ColReorder plugin) - //Only do this when _ColReorder_iOrigCol is available - if (settings.aoColumns && settings.aoColumns.length && settings.aoColumns[0]._ColReorder_iOrigCol !== undefined) { + if (dt.colReorder && dt.colReorder.transpose) { if (request.order && request.order.length) { request.order.forEach(function (order) { - order.column = settings.aoColumns[order.column]._ColReorder_iOrigCol; + order.column = dt.colReorder.transpose(order.column, "toOriginal"); }); } } diff --git a/composer.json b/composer.json index a602e505..8e3d1194 100644 --- a/composer.json +++ b/composer.json @@ -80,7 +80,6 @@ "symfony/string": "7.3.*", "symfony/translation": "7.3.*", "symfony/twig-bundle": "7.3.*", - "symfony/ux-toggle-password": "^2.29", "symfony/ux-translator": "^2.10", "symfony/ux-turbo": "^2.0", "symfony/validator": "7.3.*", diff --git a/composer.lock b/composer.lock index 91fcf0e4..6b9888d7 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "3b97b6338827ba56e0404860f3e98359", + "content-hash": "09b78f345ea8115b5b29ea3e67dcb579", "packages": [ { "name": "amphp/amp", @@ -8036,16 +8036,16 @@ }, { "name": "phpstan/phpdoc-parser", - "version": "2.2.0", + "version": "2.3.0", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "b9e61a61e39e02dd90944e9115241c7f7e76bfd8" + "reference": "1e0cd5370df5dd2e556a36b9c62f62e555870495" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/b9e61a61e39e02dd90944e9115241c7f7e76bfd8", - "reference": "b9e61a61e39e02dd90944e9115241c7f7e76bfd8", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/1e0cd5370df5dd2e556a36b9c62f62e555870495", + "reference": "1e0cd5370df5dd2e556a36b9c62f62e555870495", "shasum": "" }, "require": { @@ -8077,9 +8077,9 @@ "description": "PHPDoc parser with support for nullable, intersection and generic types", "support": { "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/2.2.0" + "source": "https://github.com/phpstan/phpdoc-parser/tree/2.3.0" }, - "time": "2025-07-13T07:04:09+00:00" + "time": "2025-08-30T15:50:23+00:00" }, { "name": "psr/cache", @@ -15206,90 +15206,6 @@ ], "time": "2025-06-27T19:55:54+00:00" }, - { - "name": "symfony/ux-toggle-password", - "version": "v2.30.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/ux-toggle-password.git", - "reference": "414b1ea51b93c4c6c6cc3a485adbfc8764ea6dc8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/ux-toggle-password/zipball/414b1ea51b93c4c6c6cc3a485adbfc8764ea6dc8", - "reference": "414b1ea51b93c4c6c6cc3a485adbfc8764ea6dc8", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "symfony/config": "^5.4|^6.0|^7.0|^8.0", - "symfony/dependency-injection": "^5.4|^6.0|^7.0|^8.0", - "symfony/form": "^5.4|^6.0|^7.0|^8.0", - "symfony/http-kernel": "^5.4|^6.0|^7.0|^8.0", - "symfony/options-resolver": "^5.4|^6.0|^7.0|^8.0", - "symfony/translation": "^5.4|^6.0|^7.0|^8.0" - }, - "require-dev": { - "symfony/framework-bundle": "^5.4|^6.0|^7.0|^8.0", - "symfony/phpunit-bridge": "^5.4|^6.0|^7.0|^8.0", - "symfony/twig-bundle": "^5.4|^6.0|^7.0|^8.0", - "symfony/var-dumper": "^5.4|^6.0|^7.0|^8.0", - "twig/twig": "^2.14.7|^3.0.4" - }, - "type": "symfony-bundle", - "extra": { - "thanks": { - "url": "https://github.com/symfony/ux", - "name": "symfony/ux" - } - }, - "autoload": { - "psr-4": { - "Symfony\\UX\\TogglePassword\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Félix Eymonot", - "email": "felix.eymonot@alximy.io" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Toggle visibility of password inputs for Symfony Forms", - "homepage": "https://symfony.com", - "keywords": [ - "symfony-ux" - ], - "support": { - "source": "https://github.com/symfony/ux-toggle-password/tree/v2.30.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-08-27T15:25:48+00:00" - }, { "name": "symfony/ux-translator", "version": "v2.30.0", diff --git a/config/bundles.php b/config/bundles.php index 084e6870..ae7dc9cc 100644 --- a/config/bundles.php +++ b/config/bundles.php @@ -33,5 +33,4 @@ return [ Jbtronics\SettingsBundle\JbtronicsSettingsBundle::class => ['all' => true], Jbtronics\TranslationEditorBundle\JbtronicsTranslationEditorBundle::class => ['dev' => true], ApiPlatform\Symfony\Bundle\ApiPlatformBundle::class => ['all' => true], - Symfony\UX\TogglePassword\TogglePasswordBundle::class => ['all' => true], ]; diff --git a/config/packages/datatables.yaml b/config/packages/datatables.yaml index 1297fc9d..f1ea4715 100644 --- a/config/packages/datatables.yaml +++ b/config/packages/datatables.yaml @@ -18,7 +18,7 @@ datatables: > <'row' <'col mt-2 input-group flex-nowrap' B l > <'col-auto mt-2' < p >>>" pagingType: 'simple_numbers' - searching: true + searching: false stateSave: true diff --git a/docs/installation/installation_docker.md b/docs/installation/installation_docker.md index c9b46fdb..232633ab 100644 --- a/docs/installation/installation_docker.md +++ b/docs/installation/installation_docker.md @@ -142,28 +142,12 @@ services: # This feature is currently experimental, so use it at your own risk! # - DB_AUTOMIGRATE=true - # You can configure Part-DB using environment variables - # Below you can find the most essential ones predefined + # You can configure Part-DB using the webUI or environment variables # However you can add add any other environment configuration you want here # See .env file for all available options or https://docs.part-db.de/configuration.html - # The language to use serverwide as default (en, de, ru, etc.) - - DEFAULT_LANG=en - # The default timezone to use serverwide (e.g. Europe/Berlin) - - DEFAULT_TIMEZONE=Europe/Berlin - # The currency that is used inside the DB (and is assumed when no currency is set). This can not be changed later, so be sure to set it the currency used in your country - - BASE_CURRENCY=EUR - # The name of this installation. This will be shown as title in the browser and in the header of the website - - INSTANCE_NAME=Part-DB - - # Allow users to download attachments to the server by providing an URL - # This could be a potential security issue, as the user can retrieve any file the server has access to (via internet) - - ALLOW_ATTACHMENT_DOWNLOADS=0 - # Use gravatars for user avatars, when user has no own avatar defined - - USE_GRAVATAR=0 - # Override value if you want to show to show a given text on homepage. - # When this is empty the content of config/banner.md is used as banner + # When this is outcommented the webUI can be used to configure the banner #- BANNER=This is a test banner
with a line break database: diff --git a/docs/upgrade/1_to_2.md b/docs/upgrade/1_to_2.md index e063c49d..f5b3b085 100644 --- a/docs/upgrade/1_to_2.md +++ b/docs/upgrade/1_to_2.md @@ -3,6 +3,7 @@ layout: default title: Upgrade from Part-DB 1.x to 2.x nav_order: 1 has_children: false +parent: Upgrade --- # Upgrade from Part-DB 1.x to 2.x diff --git a/docs/upgrade/upgrade_legacy.md b/docs/upgrade/upgrade_legacy.md index 39257a11..4dd29e4d 100644 --- a/docs/upgrade/upgrade_legacy.md +++ b/docs/upgrade/upgrade_legacy.md @@ -3,6 +3,7 @@ layout: default title: Upgrade from legacy Part-DB version (<1.0) nav_order: 100 redirect_from: /upgrade_legacy +parent: Upgrade --- # Upgrade from legacy Part-DB version diff --git a/package.json b/package.json index 1080a74c..7a3efaa4 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,6 @@ "@hotwired/turbo": "^8.0.1", "@popperjs/core": "^2.10.2", "@symfony/stimulus-bridge": "^4.0.0", - "@symfony/ux-toggle-password": "file:vendor/symfony/ux-toggle-password/assets", "@symfony/ux-translator": "file:vendor/symfony/ux-translator/assets", "@symfony/ux-turbo": "file:vendor/symfony/ux-turbo/assets", "@symfony/webpack-encore": "^5.0.0", diff --git a/src/Form/CollectionTypeExtension.php b/src/Form/Extension/CollectionTypeExtension.php similarity index 99% rename from src/Form/CollectionTypeExtension.php rename to src/Form/Extension/CollectionTypeExtension.php index 4fa93852..52cd4186 100644 --- a/src/Form/CollectionTypeExtension.php +++ b/src/Form/Extension/CollectionTypeExtension.php @@ -39,7 +39,7 @@ declare(strict_types=1); * along with this program. If not, see . */ -namespace App\Form; +namespace App\Form\Extension; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; diff --git a/src/Form/PasswordTypeExtension.php b/src/Form/Extension/PasswordTypeExtension.php similarity index 67% rename from src/Form/PasswordTypeExtension.php rename to src/Form/Extension/PasswordTypeExtension.php index 64711c53..cc0486b0 100644 --- a/src/Form/PasswordTypeExtension.php +++ b/src/Form/Extension/PasswordTypeExtension.php @@ -1,4 +1,22 @@ . + */ declare(strict_types=1); @@ -20,7 +38,7 @@ declare(strict_types=1); * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ -namespace App\Form; +namespace App\Form\Extension; use Symfony\Component\Form\AbstractTypeExtension; use Symfony\Component\Form\Extension\Core\Type\PasswordType; diff --git a/src/Form/SelectTypeOrderExtension.php b/src/Form/Extension/SelectTypeOrderExtension.php similarity index 98% rename from src/Form/SelectTypeOrderExtension.php rename to src/Form/Extension/SelectTypeOrderExtension.php index 7115d763..e8e9a93f 100644 --- a/src/Form/SelectTypeOrderExtension.php +++ b/src/Form/Extension/SelectTypeOrderExtension.php @@ -21,7 +21,7 @@ declare(strict_types=1); -namespace App\Form; +namespace App\Form\Extension; use Symfony\Component\Form\AbstractTypeExtension; use Symfony\Component\Form\Extension\Core\Type\ChoiceType; @@ -57,4 +57,4 @@ class SelectTypeOrderExtension extends AbstractTypeExtension $view->vars['attr']['data-ordered-value'] = json_encode($form->getViewData(), JSON_THROW_ON_ERROR); } } -} \ No newline at end of file +} diff --git a/src/Form/Extension/TogglePasswordTypeExtension.php b/src/Form/Extension/TogglePasswordTypeExtension.php new file mode 100644 index 00000000..8f7320df --- /dev/null +++ b/src/Form/Extension/TogglePasswordTypeExtension.php @@ -0,0 +1,122 @@ +. + */ + +declare(strict_types=1); + +namespace App\Form\Extension; + +use Symfony\Component\Form\AbstractTypeExtension; +use Symfony\Component\Form\Extension\Core\Type\PasswordType; +use Symfony\Component\Form\FormInterface; +use Symfony\Component\Form\FormView; +use Symfony\Component\OptionsResolver\Options; +use Symfony\Component\OptionsResolver\OptionsResolver; +use Symfony\Component\Translation\TranslatableMessage; +use Symfony\Contracts\Translation\TranslatorInterface; + +final class TogglePasswordTypeExtension extends AbstractTypeExtension +{ + public function __construct(private readonly ?TranslatorInterface $translator) + { + } + + public static function getExtendedTypes(): iterable + { + return [PasswordType::class]; + } + + public function configureOptions(OptionsResolver $resolver): void + { + $resolver->setDefaults([ + 'toggle' => false, + 'hidden_label' => 'Hide', + 'visible_label' => 'Show', + 'hidden_icon' => 'Default', + 'visible_icon' => 'Default', + 'button_classes' => ['toggle-password-button'], + 'toggle_container_classes' => ['toggle-password-container'], + 'toggle_translation_domain' => null, + 'use_toggle_form_theme' => true, + ]); + + $resolver->setNormalizer( + 'toggle_translation_domain', + static fn (Options $options, $labelTranslationDomain) => $labelTranslationDomain ?? $options['translation_domain'], + ); + + $resolver->setAllowedTypes('toggle', ['bool']); + $resolver->setAllowedTypes('hidden_label', ['string', TranslatableMessage::class, 'null']); + $resolver->setAllowedTypes('visible_label', ['string', TranslatableMessage::class, 'null']); + $resolver->setAllowedTypes('hidden_icon', ['string', 'null']); + $resolver->setAllowedTypes('visible_icon', ['string', 'null']); + $resolver->setAllowedTypes('button_classes', ['string[]']); + $resolver->setAllowedTypes('toggle_container_classes', ['string[]']); + $resolver->setAllowedTypes('toggle_translation_domain', ['string', 'bool', 'null']); + $resolver->setAllowedTypes('use_toggle_form_theme', ['bool']); + } + + public function buildView(FormView $view, FormInterface $form, array $options): void + { + $view->vars['toggle'] = $options['toggle']; + + if (!$options['toggle']) { + return; + } + + if ($options['use_toggle_form_theme']) { + array_splice($view->vars['block_prefixes'], -1, 0, 'toggle_password'); + } + + $controllerName = 'toggle-password'; + $controllerValues = []; + $view->vars['attr']['data-controller'] = trim(\sprintf('%s %s', $view->vars['attr']['data-controller'] ?? '', $controllerName)); + + if (false !== $options['toggle_translation_domain']) { + $controllerValues['hidden-label'] = $this->translateLabel($options['hidden_label'], $options['toggle_translation_domain']); + $controllerValues['visible-label'] = $this->translateLabel($options['visible_label'], $options['toggle_translation_domain']); + } else { + $controllerValues['hidden-label'] = $options['hidden_label']; + $controllerValues['visible-label'] = $options['visible_label']; + } + + $controllerValues['hidden-icon'] = $options['hidden_icon']; + $controllerValues['visible-icon'] = $options['visible_icon']; + $controllerValues['button-classes'] = json_encode($options['button_classes'], \JSON_THROW_ON_ERROR); + + foreach ($controllerValues as $name => $value) { + $view->vars['attr'][\sprintf('data-%s-%s-value', $controllerName, $name)] = $value; + } + + $view->vars['toggle_container_classes'] = $options['toggle_container_classes']; + } + + private function translateLabel(string|TranslatableMessage|null $label, ?string $translationDomain): ?string + { + if (null === $this->translator || null === $label) { + return $label; + } + + if ($label instanceof TranslatableMessage) { + return $label->trans($this->translator); + } + + return $this->translator->trans($label, domain: $translationDomain); + } +} diff --git a/symfony.lock b/symfony.lock index f484d13c..d301c269 100644 --- a/symfony.lock +++ b/symfony.lock @@ -729,9 +729,6 @@ }, "files": [] }, - "symfony/ux-toggle-password": { - "version": "v2.29.2" - }, "symfony/ux-translator": { "version": "2.9", "recipe": { diff --git a/templates/form/extended_bootstrap_layout.html.twig b/templates/form/extended_bootstrap_layout.html.twig index 811f57ac..75e44a15 100644 --- a/templates/form/extended_bootstrap_layout.html.twig +++ b/templates/form/extended_bootstrap_layout.html.twig @@ -1,5 +1,9 @@ {% extends 'bootstrap_5_horizontal_layout.html.twig' %} +{%- block toggle_password_widget -%} +
{{ block('password_widget') }}
+{%- endblock toggle_password_widget -%} + {# Make form rows smaller #} {% block form_row -%} {%- set row_attr = row_attr|merge({"class": "mb-2"}) -%} @@ -139,4 +143,4 @@ {% else %} {{- parent() -}} {% endif %} -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/translations/messages.de.xlf b/translations/messages.de.xlf index 24e140c8..a5c18cdd 100644 --- a/translations/messages.de.xlf +++ b/translations/messages.de.xlf @@ -12311,6 +12311,529 @@ Bitte beachten Sie, dass Sie sich nicht als deaktivierter Benutzer ausgeben kön Profil gespeichert! + + + settings.ips.element14 + Element 14 / Farnell + + + + + settings.ips.element14.apiKey + API Key + + + + + settings.ips.element14.apiKey.help + Sie können sich unter <a href="https://partner.element14.com/">https://partner.element14.com/</a> für einen API-Schlüssel registrieren. + + + + + settings.ips.element14.storeId + Store Domain + + + + + settings.ips.element14.storeId.help + Die Domain des Shops, aus dem die Daten abgerufen werden sollen. Diese bestimmt die Sprache und Währung der Ergebnisse. Eine Liste der gültigen Domains finden Sie <a href="https://partner.element14.com/docs/Product_Search_API_REST__Description">hier</a>. + + + + + settings.ips.tme + TME + + + + + settings.ips.tme.token + API Token + + + + + settings.ips.tme.token.help + Sie können einen API-Token und einen geheimen Schlüssel unter <a href="https://developers.tme.eu/en/">https://developers.tme.eu/en/</a> erhalten. + + + + + settings.ips.tme.secret + API Secret + + + + + settings.ips.tme.currency + Währung + + + + + settings.ips.tme.language + Sprache + + + + + settings.ips.tme.country + Land + + + + + settings.ips.tme.grossPrices + Bruttopreise (inklusive Steuern) abrufen + + + + + settings.ips.mouser + Mouser + + + + + settings.ips.mouser.apiKey + API Key + + + + + settings.ips.mouser.apiKey.help + Sie können sich unter <a href="https://eu.mouser.com/api-hub/">https://eu.mouser.com/api-hub/</a> für einen API-Schlüssel registrieren. + + + + + settings.ips.mouser.searchLimit + Suchlimit + + + + + settings.ips.mouser.searchLimit.help + Die maximale Anzahl an Ergebnissen für eine einzelne Suche. Kann nicht höher als 50 sein. + + + + + settings.ips.mouser.searchOptions + Suchfilter + + + + + settings.ips.mouser.searchOptions.help + Erlaubt es nur Teile mit einer bestimmten Verfügbarkeit und/oder Konformität anzuzeigen + + + + + settings.ips.mouser.searchOptions.none + Keine Filterung + + + + + settings.ips.mouser.searchOptions.rohs + Nur RoHS konforme Bauteile + + + + + settings.ips.mouser.searchOptions.inStock + Nur sofort verfügbare Bauteile + + + + + settings.ips.mouser.searchOptions.rohsAndInStock + Sofort verfügbar & RoHS konform + + + + + settings.ips.lcsc + LCSC + + + + + settings.ips.lcsc.help + Achtung: LCSC stellt keine offizielle API zur Verfügung. Dieser Anbieter nutzt die Webshop-API. LCSC hat die Nutzung dieser API nicht vorgesehen, und sie kann jederzeit ausfallen. Die Nutzung erfolgt daher auf eigene Gefahr. + + + + + settings.ips.lcsc.enabled + Aktivieren + + + + + settings.ips.lcsc.currency + Währung + + + + + settings.system.attachments + Anhänge & Dateien + + + + + settings.system.attachments.maxFileSize + Maximale Dateigröße + + + + + settings.system.attachments.maxFileSize.help + Die maximale Größe der Dateien, die hochgeladen werden können. Bitte beachten Sie, dass dies auch durch die PHP-Konfiguration begrenzt ist. + + + + + settings.system.attachments.allowDownloads + Herunterladen externer Dateien zulassen + + + + + settings.system.attachments.allowDownloads.help + Mit dieser Option können Benutzer externe Dateien in die Part-DB herunterladen, indem sie eine URL angeben. <b>Achtung: Dies kann ein Sicherheitsrisiko darstellen, da Benutzer dadurch möglicherweise über die Part-DB auf Intranet-Ressourcen zugreifen können!</b> + + + + + settings.system.attachments.downloadByDefault + Standardmäßig die URL für neue Anhänge herunterladen + + + + + settings.system.customization + Anpassungen + + + + + settings.system.customization.instanceName + Instanzname + + + + + settings.system.customization.instanceName.help + Name dieser Part-DB-Installation. Der Wert wird in der Navigationsleiste und in Titeln angezeigt. + + + + + settings.system.customization.banner + Startseiten Banner + + + + + settings.system.history + Ereignislog + + + + + settings.system.history.saveChangedFields + Speichern, welche Felder eines Elements in Protokolleinträgen geändert wurden. + + + + + settings.system.history.saveOldData + Alten Daten in Protokolleinträgen bei Elementänderungen speichern + + + + + settings.system.history.saveNewData + Neue Daten in Logeinträgen bei Elementänderung/-erstellung speichern + + + + + settings.system.history.saveRemovedData + Gelöschte Daten in Logeintrag beim Löschen von Elementen speichern + + + + + settings.system.customization.theme + Globales Thema + + + + + settings.system.history.enforceComments + Kommentare für Aktionen erzwingen + + + + + settings.system.history.enforceComments.description + Mit dieser Option können Sie festlegen, für welche Aktionen Benutzer einen Grund angeben müssen, der protokolliert wird. + + + + + settings.system.history.enforceComments.type.part_edit + Bauteil bearbeiten + + + + + settings.system.history.enforceComments.type.part_create + Bauteil erstellen + + + + + settings.system.history.enforceComments.type.part_delete + Bauteil löschen + + + + + settings.system.history.enforceComments.type.part_stock_operation + Bauteilebestand ändern + + + + + settings.system.history.enforceComments.type.datastructure_edit + Datenstruktur bearbeiten + + + + + settings.system.history.enforceComments.type.datastructure_create + Datenstruktur erstellen + + + + + settings.system.history.enforceComments.type.datastructure_delete + Datenstruktur löschen + + + + + settings.system.privacy.useGravatar + Verwende Gravatar Avatare + + + + + settings.system.privacy.useGravatar.description + Wenn ein Benutzer kein Avatar-Bild angegeben hat, verwenden Sie das Avatar von Gravatar basierend auf der E-Mail-Adresse des Benutzers. Dies führt dazu, dass der Browser Bilder von einem Drittanbieter lädt! + + + + + settings.system.privacy.checkForUpdates + Auf verfügbare Aktualisierungen von Part-DB prüfen + + + + + settings.system.privacy.checkForUpdates.description + Part-DB überprüft regelmäßig, ob auf GitHub eine neue Version verfügbar ist. Deaktivieren Sie diese Option hier, wenn Sie dies nicht wünschen oder wenn Ihr Server keine Verbindung zum Internet herstellen kann. + + + + + settings.system.localization.locale + Standardsprache + + + + + settings.system.localization + Lokalisierung + + + + + settings.system.localization.timezone + Standardzeitzone + + + + + settings.system.localization.base_currency + Basiswährung + + + + + settings.system.localization.base_currency_description + Die Währung, in der Preisinformationen und Wechselkurse gespeichert werden. Diese Währung wird angenommen, wenn für eine Preisinformation keine Währung festgelegt ist. +<b>Bitte beachten Sie, dass die Währungen bei einer Änderung dieses Wertes nicht umgerechnet werden. Wenn Sie also die Basiswährung ändern, nachdem Sie bereits Preisinformationen hinzugefügt haben, führt dies zu falschen Preisen!</b> + + + + + settings.system.privacy + Datenschutz + + + + + settings.title + Servereinstellungen + + + + + settings.misc.kicad_eda + KiCAD Integration + + + + + settings.misc.kicad_eda.category_depth + Kategorientiefe + + + + + settings.misc.kicad_eda.category_depth.help + Dieser Wert bestimmt die Tiefe des Kategoriebaums, der in KiCad sichtbar ist. 0 bedeutet, dass nur die Kategorien der obersten Ebene sichtbar sind. Setzen Sie den Wert auf > 0, um weitere Ebenen anzuzeigen. Setzen Sie den Wert auf -1, um alle Teile der Part-DB innerhalb einer einzigen Kategorie in KiCad anzuzeigen. + + + + + settings.behavior.sidebar + Seitenleiste + + + + + settings.behavior.sidebar.items + Seitenleisteneinträge + + + + + settings.behavior.sidebar.items.help + Die Menüs, die standardmäßig in der Seitenleiste angezeigt werden. Die Reihenfolge der Elemente kann per Drag & Drop geändert werden. + + + + + settings.behavior.sidebar.rootNodeEnabled + Stammknoten anzeigen + + + + + settings.behavior.sidebar.rootNodeEnabled.help + Ist diese Funktion aktiviert, werden alle Kategorien der obersten Ebene, Footprints usw. unter einem einzigen Stammknoten zusammengefasst. Ist sie deaktiviert, werden die Kategorien der obersten Ebene direkt im Menü angezeigt. + + + + + settings.behavior.sidebar.rootNodeExpanded + Stammknoten standardmäßig ausgeklappt + + + + + settings.behavior.table + Tabellen + + + + + settings.behavior.table.default_page_size + Standardmäßige Seitengröße + + + + + settings.behavior.table.default_page_size.help + Wie viele Einträge standardmäßig auf ganzseitigen Tabellen gezeigt werden. Setzen Sie den Wert auf -1, um standardmäßig alle Elemente ohne Seitenunterteilung anzuzeigen. + + + + + settings.behavior.table.parts_default_columns + Standardmäßige Spalten für Bauteiletabellen + + + + + settings.behavior.table.parts_default_columns.help + Die Spalten, die standardmäßig in Bauteiltabellen angezeigt werden sollen. Die Reihenfolge der Elemente kann per Drag & Drop geändert werden. + + + + + settings.ips.oemsecrets + OEMSecrets + + + + + settings.ips.oemsecrets.keepZeroPrices + Händler mit Nullpreisen anzeigen + + + + + settings.ips.oemsecrets.keepZeroPrices.help + Wenn dies nicht gesetzt ist, werden Händler, deren Preise 0 betragen, als ungültig verworfen. + + + + + settings.ips.oemsecrets.parseParams + Parameter aus Beschreibung extrahieren + + + + + settings.ips.oemsecrets.parseParams.help + Wenn diese Option aktiviert ist, versucht der Anbieter, die unstrukturierten Beschreibungen von OEMSecrets in strukturierte Parameter umzuwandeln. Jeder Parameter in der Beschreibung sollte die Form „...;name1:value1;name2:value2“ haben. + + + + + settings.ips.oemsecrets.sortMode + Sortierung der Ergebnisse + + + + + settings.ips.oemsecrets.sortMode.N + Keine + + + + + settings.ips.oemsecrets.sortMode.C + Vollständigkeit (Priorisierung von Elementen mit detaillierten Informationen) + + + + + settings.ips.oemsecrets.sortMode.M + Vollständigkeit & Herstellername + + entity.export.flash.error.no_entities @@ -12365,5 +12888,167 @@ Bitte beachten Sie, dass Sie sich nicht als deaktivierter Benutzer ausgeben kön Dieses Bauteil enthält mehr als einen Bestand. Ändere den Lagerort bei Hand, um auszuwählen, welcher Bestand geändert werden soll. + + + settings.ips.reichelt + Reichelt + + + + + settings.ips.reichelt.help + Reichelt.com bietet keine offizielle API an, daher extrahiert dieser Informationsanbieter die Informationen per Webscraping aus der Website. Dies kann jederzeit unterbrochen werden, die Nutzung erfolgt auf eigene Gefahr. + + + + + settings.ips.reichelt.include_vat + Preise inkl. Mehrwertsteuer anzeigen + + + + + settings.ips.pollin + Pollin + + + + + settings.ips.pollin.help + Pollin.de bietet keine offizielle API an, daher extrahiert dieser Informationsanbieter die Daten per Webscraping aus der Website. Dies kann jederzeit aufhören zu funktionieren, die Nutzung erfolgt auf eigene Gefahr. + + + + + settings.behavior.sidebar.rootNodeRedirectsToNewEntity + Wurzelknoten leitet zur Erstellung eines neuen Elements weiter + + + + + settings.ips.digikey + Digikey + + + + + settings.ips.digikey.client_id + Client ID + + + + + settings.ips.digikey.secret + Secret + + + + + settings.ips.octopart + Octopart / Nexar + + + + + settings.ips.octopart.searchLimit + Anzahl an Ergebnissen + + + + + settings.ips.octopart.searchLimit.help + Die Anzahl der Ergebnisse, die Sie bei der Suche von Octopart erhalten möchten (bitte beachten Sie, dass dies auf Ihre API-Limits angerechnet wird) + + + + + settings.ips.octopart.onlyAuthorizedSellers + Nur autorisierte Verkäufer + + + + + settings.ips.octopart.onlyAuthorizedSellers.help + Anwählen, um nicht-autorisierte Angebote in den Ergebnissen anzuzeigen + + + + + settings.misc.exchange_rate + Wechselkurse + + + + + settings.misc.exchange_rate.fixer_api_key + Fixer.io API Key + + + + + settings.misc.exchange_rate.fixer_api_key.help + Wenn Sie Wechselkurse zwischen Nicht-Euro-Währungen benötigen, können Sie hier einen API-Schlüssel von fixer.io eingeben. + + + + + settings.behavior.part_info + Bauteileinfoseite + + + + + settings.behavior.part_info.show_part_image_overlay + Bildoverlay anzeigen + + + + + settings.behavior.part_info.show_part_image_overlay.help + Zeigen Sie die Bildoverlay mit den Details zum Anhang an, wenn Sie mit der Maus über die Teilebildgalerie fahren. + + + + + perm.config.change_system_settings + Systemeinstellungen bearbeiten + + + + + tree.tools.system.settings + Systemeinstellungen + + + + + settings.tooltip.overrideable_by_env + Der Wert dieses Parameters kann durch Setzen der Umgebungsvariable „%env%“ überschrieben werden. + + + + + settings.flash.saved + Einstellungen erfolgreich gespeichert. + + + + + settings.flash.invalid + Die Einstellungen sind ungültig. Bitte überprüfen Sie Ihre Eingabe! + + + + + info_providers.settings.title + Informationsquelle-Einstellungen + + + + + form.apikey.redacted + Aus Sicherheitsgründen ausgeblendet + + diff --git a/translations/messages.en.xlf b/translations/messages.en.xlf index 481a5083..e65445ce 100644 --- a/translations/messages.en.xlf +++ b/translations/messages.en.xlf @@ -7164,8 +7164,8 @@ Exampletown Element 2 Element 3 -Element 1 -> Element 1.1 -Element 1 -> Element 1.2]]> +Element 1 -> Element 1.1 +Element 1 -> Element 1.2]]> @@ -12319,526 +12319,526 @@ Please note, that you can not impersonate a disabled user. If you try you will g - + settings.ips.element14 Element 14 / Farnell - + settings.ips.element14.apiKey API Key - + settings.ips.element14.apiKey.help - https://partner.element14.com/.]]> + You can register for an API key on <a href="https://partner.element14.com/">https://partner.element14.com/</a>. - + settings.ips.element14.storeId Store Domain - + settings.ips.element14.storeId.help - here for a list of valid domains.]]> + The store domain to retrieve the data from. This decides the language and currency of results. See <a href="https://partner.element14.com/docs/Product_Search_API_REST__Description">here</a> for a list of valid domains. - + settings.ips.tme TME - + settings.ips.tme.token API Token - + settings.ips.tme.token.help - https://developers.tme.eu/en/.]]> + You can get an API token and secret on <a href="https://developers.tme.eu/en/">https://developers.tme.eu/en/</a>. - + settings.ips.tme.secret API Secret - + settings.ips.tme.currency Currency - + settings.ips.tme.language Language - + settings.ips.tme.country Country - + settings.ips.tme.grossPrices Get gross prices (including tax) - + settings.ips.mouser Mouser - + settings.ips.mouser.apiKey API key - + settings.ips.mouser.apiKey.help - https://eu.mouser.com/api-hub/.]]> + You can register for an API key on <a href="https://eu.mouser.com/api-hub/">https://eu.mouser.com/api-hub/</a>. - + settings.ips.mouser.searchLimit Search limit - + settings.ips.mouser.searchLimit.help The maximum amount of results for a single search. Can not be higher than 50. - + settings.ips.mouser.searchOptions Search filters - + settings.ips.mouser.searchOptions.help This allows you to only show parts with a certain availability and/or compliance. - + settings.ips.mouser.searchOptions.none No filter - + settings.ips.mouser.searchOptions.rohs Only RoHS compliant parts - + settings.ips.mouser.searchOptions.inStock Only in stock parts - + settings.ips.mouser.searchOptions.rohsAndInStock Only in stock, RoHS compliant parts - + settings.ips.lcsc LCSC - + settings.ips.lcsc.help Warning: LCSC does not provide an official API. This provider utilizes the webshop API. LCSC did not intend the use of this API, and it could break any time, so use it on your own risk. - + settings.ips.lcsc.enabled Enable - + settings.ips.lcsc.currency Currency - + settings.system.attachments - + Attachments & Files - + settings.system.attachments.maxFileSize Maximum file size - + settings.system.attachments.maxFileSize.help The maximum size of files that can be uploaded. Please note that this is also limited by PHP configuration. - + settings.system.attachments.allowDownloads Allow downloading of external files - + settings.system.attachments.allowDownloads.help - Attention: This can be a security issue, as it might allow users to access intranet ressources via Part-DB!]]> + With this option users can download external files into Part-DB by providing an URL. <b>Attention: This can be a security issue, as it might allow users to access intranet ressources via Part-DB!</b> - + settings.system.attachments.downloadByDefault Download new attachment URLs by default - + settings.system.customization Customization - + settings.system.customization.instanceName Instance name - + settings.system.customization.instanceName.help Name of this Part-DB installation. The value is shown in nav bar and titles. - + settings.system.customization.banner Homepage banner - + settings.system.history History log - + settings.system.history.saveChangedFields Save which fields of an element were changed in log entries - + settings.system.history.saveOldData Save the old data in log entries on element changes - + settings.system.history.saveNewData Save the new data in log entries on element change/creation - + settings.system.history.saveRemovedData Save removed data in log entries on element deletion - + settings.system.customization.theme Global theme - + settings.system.history.enforceComments Enforce comments for action types - + settings.system.history.enforceComments.description With this option, you can specify for which actions, users are enforced to give a reason, which will be logged in history. - + settings.system.history.enforceComments.type.part_edit Part edit - + settings.system.history.enforceComments.type.part_create Part creation - + settings.system.history.enforceComments.type.part_delete Part deletion - + settings.system.history.enforceComments.type.part_stock_operation Part stock operation - + settings.system.history.enforceComments.type.datastructure_edit Data structure edit - + settings.system.history.enforceComments.type.datastructure_create Data structure creation - + settings.system.history.enforceComments.type.datastructure_delete Data structure deletion - + settings.system.privacy.useGravatar Use Gravatar avatars - + settings.system.privacy.useGravatar.description If a user does not have an avatar image specified, use the avatar from Gravatar based on the user email. This causes the browser to load pictures from a third-party! - + settings.system.privacy.checkForUpdates Check for Part-DB updates - + settings.system.privacy.checkForUpdates.description Part-DB regularly checks if a new version is available on GitHub. Disable this here, if you do not want this or if your server can not connect to the internet. - + settings.system.localization.locale Default language / locale - + settings.system.localization Localization - + settings.system.localization.timezone Default timezone - + settings.system.localization.base_currency Base currency - + settings.system.localization.base_currency_description - Please note that the currencies are not converted, when changing this value. So changing the default currency after you already added price information, will result in wrong prices!]]> + The currency that is used to store price information and exchange rates in. This currency is assumed, when no currency is set for a price information. +<b>Please note that the currencies are not converted, when changing this value. So changing the default currency after you already added price information, will result in wrong prices!</b> - + settings.system.privacy Privacy - + settings.title Server settings - + settings.misc.kicad_eda KiCAD integration - + settings.misc.kicad_eda.category_depth Category depth - + settings.misc.kicad_eda.category_depth.help - 0 to show more levels. Set to -1, to show all parts of Part-DB inside a sigle cnategory in KiCad.]]> + This value determines the depth of the category tree, that is visible inside KiCad. 0 means that only the top level categories are visible. Set to a value > 0 to show more levels. Set to -1, to show all parts of Part-DB inside a sigle cnategory in KiCad. - + settings.behavior.sidebar Sidebar - + settings.behavior.sidebar.items Sidebar items - + settings.behavior.sidebar.items.help - + The menus which appear at the sidebar by default. Order of items can be changed via drag & drop. - + settings.behavior.sidebar.rootNodeEnabled Use root node - + settings.behavior.sidebar.rootNodeEnabled.help If this is enabled, all top-level categories, footprints, etc. will be put under a single root node. If disabled, the top-level categories will be put directly into the menu. - + settings.behavior.sidebar.rootNodeExpanded Expand root node by default - + settings.behavior.table Tables - + settings.behavior.table.default_page_size Default page size - + settings.behavior.table.default_page_size.help The default page size on full page tables. Set to -1 to show all items by default without pagination. - + settings.behavior.table.parts_default_columns Default columns for part tables - + settings.behavior.table.parts_default_columns.help - + The columns to show by default in part tables. Order of items can be changed via drag & drop. - + settings.ips.oemsecrets OEMSecrets - + settings.ips.oemsecrets.keepZeroPrices Keep distributors with zero prices - + settings.ips.oemsecrets.keepZeroPrices.help If this is not set, distributors where the prices are 0 will be discarded as invalid - + settings.ips.oemsecrets.parseParams Extract parameters from description - + settings.ips.oemsecrets.parseParams.help If enabled, the provider tries to convert the unstructured descriptions of OEMSecrets into structured parameters. Each parameter in the description should have the form "...;name1:value1;name2:value2" - + settings.ips.oemsecrets.sortMode Result sort mode - + settings.ips.oemsecrets.sortMode.N None - + settings.ips.oemsecrets.sortMode.C Completeness (prioritize items with detailed information) - + settings.ips.oemsecrets.sortMode.M - + Completeness & Manufacturer name @@ -12886,7 +12886,7 @@ Please note, that you can not impersonate a disabled user. If you try you will g part_list.action.action.change_location - Change location (only for parts with single stock) + Change location (only for parts with single lot) @@ -12896,163 +12896,163 @@ Please note, that you can not impersonate a disabled user. If you try you will g - + settings.ips.reichelt Reichelt - + settings.ips.reichelt.help Reichelt.com offers no official API, so this info provider webscrapes the website to extract info. It could break at any time, use it at your own risk. - + settings.ips.reichelt.include_vat Include VAT in prices - + settings.ips.pollin Pollin - + settings.ips.pollin.help Pollin.de offers no official API, so this info provider webscrapes the website to extract info. It could break at any time, use it at your own risk. - + settings.behavior.sidebar.rootNodeRedirectsToNewEntity Root nodes redirect to new entity pages - + settings.ips.digikey Digikey - + settings.ips.digikey.client_id Client ID - + settings.ips.digikey.secret Secret - + settings.ips.octopart Octopart / Nexar - + settings.ips.octopart.searchLimit Number of results - + settings.ips.octopart.searchLimit.help The number of results to get from Octopart while searching (please note that this counts towards your API limits) - + settings.ips.octopart.onlyAuthorizedSellers Only authorized sellers - + settings.ips.octopart.onlyAuthorizedSellers.help Set to false to include non-authorized offers in the results - + settings.misc.exchange_rate Money exchange rates - + settings.misc.exchange_rate.fixer_api_key Fixer.io API Key - + settings.misc.exchange_rate.fixer_api_key.help If you need exchange rates between non-euro currencies, you can input an API key from fixer.io here. - + settings.behavior.part_info Part info page - + settings.behavior.part_info.show_part_image_overlay Show image overlay - + settings.behavior.part_info.show_part_image_overlay.help Show the image overlay with attachment details on hovering over the part image gallery. - + perm.config.change_system_settings Change system settings - + tree.tools.system.settings System settings - + settings.tooltip.overrideable_by_env The value of this parameter can be overridden by setting the environment variable "%env%". - + settings.flash.saved Settings saved successfully. - + settings.flash.invalid Settings are invalid. Please check your input! - + info_providers.settings.title Info provider settings - + form.apikey.redacted Redacted for security reasons diff --git a/translations/messages.es.xlf b/translations/messages.es.xlf index 3694a7f3..f1fd8263 100644 --- a/translations/messages.es.xlf +++ b/translations/messages.es.xlf @@ -12344,5 +12344,29 @@ Por favor ten en cuenta que no puedes personificar a un usuario deshabilitado. S Ver versión externa + + + part.table.actions.error + Han ocurrido %count% errores mientras se ejecutaba la acción: + + + + + part.table.actions.error_detail + %part_name% (ID: %part_id%): %message% + + + + + part_list.action.action.change_location + Cambiar de ubicación (solo para componentes con un único lote) + + + + + parts.table.action_handler.error.part_lots_multiple + Este componente contiene más de un stock. Cambie la ubicación manualmente para seleccionar el stock deseado. + + diff --git a/translations/validators.de.xlf b/translations/validators.de.xlf index dc3f94df..9c123fd8 100644 --- a/translations/validators.de.xlf +++ b/translations/validators.de.xlf @@ -347,7 +347,13 @@ Aufgrund technischer Beschränkungen ist es nicht möglich, ein Datum nach dem 19.01.2038 auf 32-Bit Systemen auszuwählen! - + + + validator.fileSize.invalidFormat + Ungültige Angabe für die Dateigröße. Verwenden Sie eine ganze Zahl mit K, M, G als Suffix für Kilo, Mega oder Gigabytes. + + + validator.invalid_range Der gegebene Bereich ist nicht gültig! diff --git a/translations/validators.en.xlf b/translations/validators.en.xlf index 1eae19eb..6ad14460 100644 --- a/translations/validators.en.xlf +++ b/translations/validators.en.xlf @@ -348,13 +348,13 @@ - + validator.fileSize.invalidFormat Invalid file size format. Use an integer number plus K, M, G as suffix for Kilo, Mega or Gigabytes. - + validator.invalid_range The given range is not valid! diff --git a/yarn.lock b/yarn.lock index ba6b118a..307692f2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2023,9 +2023,6 @@ loader-utils "^2.0.0 || ^3.0.0" schema-utils "^3.0.0 || ^4.0.0" -"@symfony/ux-toggle-password@file:vendor/symfony/ux-toggle-password/assets": - version "2.29.2" - "@symfony/ux-translator@file:vendor/symfony/ux-translator/assets": version "2.29.2"