Merge tag 'v2.2.1' into order-details
2
VERSION
|
|
@ -1 +1 @@
|
|||
2.2.0
|
||||
2.2.1
|
||||
|
|
|
|||
|
|
@ -20,11 +20,12 @@
|
|||
import {Plugin} from 'ckeditor5';
|
||||
|
||||
require('./lang/de.js');
|
||||
require('./lang/en.js');
|
||||
|
||||
import { addListToDropdown, createDropdown } from 'ckeditor5';
|
||||
|
||||
import {Collection} from 'ckeditor5';
|
||||
import {Model} from 'ckeditor5';
|
||||
import {UIModel} from 'ckeditor5';
|
||||
|
||||
export default class PartDBLabelUI extends Plugin {
|
||||
init() {
|
||||
|
|
@ -151,18 +152,28 @@ const PLACEHOLDERS = [
|
|||
function getDropdownItemsDefinitions(t) {
|
||||
const itemDefinitions = new Collection();
|
||||
|
||||
let first = true;
|
||||
|
||||
for ( const group of PLACEHOLDERS) {
|
||||
|
||||
//Add group header
|
||||
itemDefinitions.add({
|
||||
'type': 'separator',
|
||||
model: new Model( {
|
||||
withText: true,
|
||||
})
|
||||
});
|
||||
|
||||
//Skip separator for first group
|
||||
if (!first) {
|
||||
|
||||
itemDefinitions.add({
|
||||
'type': 'separator',
|
||||
model: new UIModel( {
|
||||
withText: true,
|
||||
})
|
||||
});
|
||||
} else {
|
||||
first = false;
|
||||
}
|
||||
|
||||
itemDefinitions.add({
|
||||
type: 'button',
|
||||
model: new Model( {
|
||||
model: new UIModel( {
|
||||
label: t(group.label),
|
||||
withText: true,
|
||||
isEnabled: false,
|
||||
|
|
@ -173,7 +184,7 @@ function getDropdownItemsDefinitions(t) {
|
|||
for ( const entry of group.entries) {
|
||||
const definition = {
|
||||
type: 'button',
|
||||
model: new Model( {
|
||||
model: new UIModel( {
|
||||
commandParam: entry[0],
|
||||
label: t(entry[1]),
|
||||
tooltip: entry[0],
|
||||
|
|
|
|||
|
|
@ -17,15 +17,9 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// Make sure that the global object is defined. If not, define it.
|
||||
window.CKEDITOR_TRANSLATIONS = window.CKEDITOR_TRANSLATIONS || {};
|
||||
import {add} from "ckeditor5";
|
||||
|
||||
// Make sure that the dictionary for Polish translations exist.
|
||||
window.CKEDITOR_TRANSLATIONS[ 'de' ] = window.CKEDITOR_TRANSLATIONS[ 'de' ] || {};
|
||||
window.CKEDITOR_TRANSLATIONS[ 'de' ].dictionary = window.CKEDITOR_TRANSLATIONS[ 'de' ].dictionary || {};
|
||||
|
||||
// Extend the dictionary for Polish translations with your translations:
|
||||
Object.assign( window.CKEDITOR_TRANSLATIONS[ 'de' ].dictionary, {
|
||||
add( "de", {
|
||||
'Label Placeholder': 'Label Platzhalter',
|
||||
'Part': 'Bauteil',
|
||||
|
||||
|
|
@ -88,5 +82,4 @@ Object.assign( window.CKEDITOR_TRANSLATIONS[ 'de' ].dictionary, {
|
|||
'Instance name': 'Instanzname',
|
||||
'Target type': 'Zieltyp',
|
||||
'URL of this Part-DB instance': 'URL dieser Part-DB Instanz',
|
||||
|
||||
} );
|
||||
});
|
||||
|
|
|
|||
84
assets/ckeditor/plugins/PartDBLabel/lang/en.js
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
import {add} from "ckeditor5";
|
||||
|
||||
add( "en", {
|
||||
'Label Placeholder': 'Label placeholder',
|
||||
'Part': 'Part',
|
||||
|
||||
'Database ID': 'Database ID',
|
||||
'Part name': 'Part name',
|
||||
'Category': 'Category',
|
||||
'Category (Full path)': 'Category (full path)',
|
||||
'Manufacturer': 'Manufacturer',
|
||||
'Manufacturer (Full path)': 'Manufacturer (full path)',
|
||||
'Footprint': 'Footprint',
|
||||
'Footprint (Full path)': 'Footprint (full path)',
|
||||
'Mass': 'Mass',
|
||||
'Manufacturer Product Number (MPN)': 'Manufacturer Product Number (MPN)',
|
||||
'Internal Part Number (IPN)': 'Internal Part Number (IPN)',
|
||||
'Tags': 'Tags',
|
||||
'Manufacturing status': 'Manufacturing status',
|
||||
'Description': 'Description',
|
||||
'Description (plain text)': 'Description (plain text)',
|
||||
'Comment': 'Comment',
|
||||
'Comment (plain text)': 'Comment (plain text)',
|
||||
'Last modified datetime': 'Last modified datetime',
|
||||
'Creation datetime': 'Creation datetime',
|
||||
'IPN as QR code': 'IPN as QR code',
|
||||
'IPN as Code 128 barcode': 'IPN as Code 128 barcode',
|
||||
'IPN as Code 39 barcode': 'IPN as Code 39 barcode',
|
||||
|
||||
'Lot ID': 'Lot ID',
|
||||
'Lot name': 'Lot name',
|
||||
'Lot comment': 'Lot comment',
|
||||
'Lot expiration date': 'Lot expiration date',
|
||||
'Lot amount': 'Lot amount',
|
||||
'Storage location': 'Storage location',
|
||||
'Storage location (Full path)': 'Storage location (full path)',
|
||||
'Full name of the lot owner': 'Full name of the lot owner',
|
||||
'Username of the lot owner': 'Username of the lot owner',
|
||||
|
||||
'Barcodes': 'Barcodes',
|
||||
'Content of the 1D barcodes (like Code 39)': 'Content of the 1D barcodes (like Code 39)',
|
||||
'Content of the 2D barcodes (QR codes)': 'Content of the 2D barcodes (QR codes)',
|
||||
'QR code linking to this element': 'QR code linking to this element',
|
||||
'Code 128 barcode linking to this element': 'Code 128 barcode linking to this element',
|
||||
'Code 39 barcode linking to this element': 'Code 39 barcode linking to this element',
|
||||
'Code 93 barcode linking to this element': 'Code 93 barcode linking to this element',
|
||||
'Datamatrix code linking to this element': 'Datamatrix code linking to this element',
|
||||
|
||||
'Location ID': 'Location ID',
|
||||
'Name': 'Name',
|
||||
'Full path': 'Full path',
|
||||
'Parent name': 'Parent name',
|
||||
'Parent full path': 'Parent full path',
|
||||
'Full name of the location owner': 'Full name of the location owner',
|
||||
'Username of the location owner': 'Username of the location owner',
|
||||
|
||||
'Username': 'Username',
|
||||
'Username (including name)': 'Username (including name)',
|
||||
'Current datetime': 'Current datetime',
|
||||
'Current date': 'Current date',
|
||||
'Current time': 'Current time',
|
||||
'Instance name': 'Instance name',
|
||||
'Target type': 'Target type',
|
||||
'URL of this Part-DB instance': 'URL of this Part-DB instance',
|
||||
} );
|
||||
|
|
@ -34,6 +34,11 @@ export default class extends Controller {
|
|||
|
||||
connect() {
|
||||
|
||||
let dropdownParent = "body";
|
||||
if (this.element.closest('.modal')) {
|
||||
dropdownParent = null
|
||||
}
|
||||
|
||||
let settings = {
|
||||
persistent: false,
|
||||
create: true,
|
||||
|
|
@ -42,7 +47,7 @@ export default class extends Controller {
|
|||
selectOnTab: true,
|
||||
//This a an ugly solution to disable the delimiter parsing of the TomSelect plugin
|
||||
delimiter: 'VERY_L0NG_D€LIMITER_WHICH_WILL_NEVER_BE_ENCOUNTERED_IN_A_STRING',
|
||||
dropdownParent: 'body',
|
||||
dropdownParent: dropdownParent,
|
||||
render: {
|
||||
item: (data, escape) => {
|
||||
return '<span>' + escape(data.label) + '</span>';
|
||||
|
|
|
|||
|
|
@ -28,6 +28,27 @@ import {EditorWatchdog} from 'ckeditor5';
|
|||
import "ckeditor5/ckeditor5.css";;
|
||||
import "../../css/components/ckeditor.css";
|
||||
|
||||
const translationContext = require.context(
|
||||
'ckeditor5/translations',
|
||||
false,
|
||||
//Only load the translation files we will really need
|
||||
/(de|it|fr|ru|ja|cs|da|zh|pl|hu)\.js$/
|
||||
);
|
||||
|
||||
function loadTranslation(language) {
|
||||
if (!language || language === 'en') {
|
||||
return null;
|
||||
}
|
||||
const lang = language.slice(0, 2);
|
||||
const path = `./${lang}.js`;
|
||||
if (translationContext.keys().includes(path)) {
|
||||
const module = translationContext(path);
|
||||
return module.default;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/* stimulusFetch: 'lazy' */
|
||||
export default class extends Controller {
|
||||
connect() {
|
||||
|
|
@ -63,6 +84,13 @@ export default class extends Controller {
|
|||
}
|
||||
}
|
||||
|
||||
//Load translations if not english
|
||||
let translations = loadTranslation(language);
|
||||
if (translations) {
|
||||
//Keep existing translations (e.g. from other plugins), if any
|
||||
config.translations = [window.CKEDITOR_TRANSLATIONS, translations];
|
||||
}
|
||||
|
||||
const watchdog = new EditorWatchdog();
|
||||
watchdog.setCreator((elementOrData, editorConfig) => {
|
||||
return EDITOR_TYPE.create(elementOrData, editorConfig)
|
||||
|
|
|
|||
|
|
@ -10,13 +10,19 @@ export default class extends Controller {
|
|||
|
||||
connect() {
|
||||
|
||||
//Check if tomselect is inside an modal and do not attach the dropdown to body in that case (as it breaks the modal)
|
||||
let dropdownParent = "body";
|
||||
if (this.element.closest('.modal')) {
|
||||
dropdownParent = null
|
||||
}
|
||||
|
||||
let settings = {
|
||||
allowEmptyOption: true,
|
||||
plugins: ['dropdown_input'],
|
||||
searchField: ["name", "description", "category", "footprint"],
|
||||
valueField: "id",
|
||||
labelField: "name",
|
||||
dropdownParent: 'body',
|
||||
dropdownParent: dropdownParent,
|
||||
preload: "focus",
|
||||
render: {
|
||||
item: (data, escape) => {
|
||||
|
|
|
|||
|
|
@ -38,13 +38,17 @@ export default class extends Controller {
|
|||
this._emptyMessage = this.element.getAttribute('title');
|
||||
}
|
||||
|
||||
let dropdownParent = "body";
|
||||
if (this.element.closest('.modal')) {
|
||||
dropdownParent = null
|
||||
}
|
||||
|
||||
let settings = {
|
||||
plugins: ["clear_button"],
|
||||
allowEmptyOption: true,
|
||||
selectOnTab: true,
|
||||
maxOptions: null,
|
||||
dropdownParent: 'body',
|
||||
dropdownParent: dropdownParent,
|
||||
|
||||
render: {
|
||||
item: this.renderItem.bind(this),
|
||||
|
|
|
|||
|
|
@ -26,10 +26,15 @@ export default class extends Controller {
|
|||
_tomSelect;
|
||||
|
||||
connect() {
|
||||
let dropdownParent = "body";
|
||||
if (this.element.closest('.modal')) {
|
||||
dropdownParent = null
|
||||
}
|
||||
|
||||
this._tomSelect = new TomSelect(this.element, {
|
||||
maxItems: 1000,
|
||||
allowEmptyOption: true,
|
||||
dropdownParent: 'body',
|
||||
dropdownParent: dropdownParent,
|
||||
plugins: ['remove_button'],
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,6 +40,11 @@ export default class extends Controller {
|
|||
|
||||
connect() {
|
||||
|
||||
let dropdownParent = "body";
|
||||
if (this.element.closest('.modal')) {
|
||||
dropdownParent = null
|
||||
}
|
||||
|
||||
let settings = {
|
||||
persistent: false,
|
||||
create: true,
|
||||
|
|
@ -50,7 +55,7 @@ export default class extends Controller {
|
|||
valueField: 'text',
|
||||
searchField: 'text',
|
||||
orderField: 'text',
|
||||
dropdownParent: 'body',
|
||||
dropdownParent: dropdownParent,
|
||||
|
||||
//This a an ugly solution to disable the delimiter parsing of the TomSelect plugin
|
||||
delimiter: 'VERY_L0NG_D€LIMITER_WHICH_WILL_NEVER_BE_ENCOUNTERED_IN_A_STRING',
|
||||
|
|
|
|||
|
|
@ -40,7 +40,10 @@ export default class extends Controller {
|
|||
const allowAdd = this.element.getAttribute("data-allow-add") === "true";
|
||||
const addHint = this.element.getAttribute("data-add-hint") ?? "";
|
||||
|
||||
|
||||
let dropdownParent = "body";
|
||||
if (this.element.closest('.modal')) {
|
||||
dropdownParent = null
|
||||
}
|
||||
|
||||
|
||||
let settings = {
|
||||
|
|
@ -54,7 +57,7 @@ export default class extends Controller {
|
|||
maxItems: 1,
|
||||
delimiter: "$$VERY_LONG_DELIMITER_THAT_SHOULD_NEVER_APPEAR$$",
|
||||
splitOn: null,
|
||||
dropdownParent: 'body',
|
||||
dropdownParent: dropdownParent,
|
||||
|
||||
searchField: [
|
||||
{field: "text", weight : 2},
|
||||
|
|
|
|||
|
|
@ -33,6 +33,11 @@ export default class extends Controller {
|
|||
_tomSelect;
|
||||
|
||||
connect() {
|
||||
let dropdownParent = "body";
|
||||
if (this.element.closest('.modal')) {
|
||||
dropdownParent = null
|
||||
}
|
||||
|
||||
let settings = {
|
||||
plugins: {
|
||||
remove_button:{},
|
||||
|
|
@ -43,7 +48,7 @@ export default class extends Controller {
|
|||
selectOnTab: true,
|
||||
createOnBlur: true,
|
||||
create: true,
|
||||
dropdownParent: 'body',
|
||||
dropdownParent: dropdownParent,
|
||||
};
|
||||
|
||||
if(this.element.dataset.autocomplete) {
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
"doctrine/doctrine-bundle": "^2.0",
|
||||
"doctrine/doctrine-migrations-bundle": "^3.0",
|
||||
"doctrine/orm": "^3.2.0",
|
||||
"dompdf/dompdf": "^v3.0.0",
|
||||
"dompdf/dompdf": "^3.1.2",
|
||||
"gregwar/captcha-bundle": "^2.1.0",
|
||||
"hshn/base64-encoded-file": "^5.0",
|
||||
"jbtronics/2fa-webauthn": "^3.0.0",
|
||||
|
|
|
|||
919
composer.lock
generated
|
|
@ -8,7 +8,7 @@ parameters:
|
|||
|
||||
# This is used as workaround for places where we can not access the settings directly (like the 2FA application names)
|
||||
partdb.title: '%env(string:settings:customization:instanceName)%' # The title shown inside of Part-DB (e.g. in the navbar and on homepage)
|
||||
partdb.locale_menu: ['en', 'de', 'it', 'fr', 'ru', 'ja', 'cs', 'da', 'zh', 'pl'] # The languages that are shown in user drop down menu
|
||||
partdb.locale_menu: ['en', 'de', 'it', 'fr', 'ru', 'ja', 'cs', 'da', 'zh', 'pl', 'hu'] # The languages that are shown in user drop down menu
|
||||
|
||||
partdb.default_uri: '%env(string:DEFAULT_URI)%' # The default URI to use for the Part-DB instance (e.g. https://part-db.example.com/). This is used for generating links in emails
|
||||
|
||||
|
|
|
|||
|
|
@ -48,14 +48,15 @@ The upgrade process works very similar to a normal (minor release) upgrade.
|
|||
1. Make a backup of your existing Part-DB installation, including the database, data directories and the configuration files and `.env.local` file.
|
||||
The `php bin/console partdb:backup` command can help you with this.
|
||||
2. Pull the v2 version. For git installation you can do this with `git checkout v2.0.0` (or newer version)
|
||||
3. Run `composer install --no-dev -o` to update the dependencies.
|
||||
4. Run `yarn install` and `yarn build` to update the frontend assets.
|
||||
5. Rund `php bin/console doctrine:migrations:migrate` to update the database schema.
|
||||
6. Clear the cache with `php bin/console cache:clear`.
|
||||
7. Open your Part-DB instance in the browser and log in as an admin user.
|
||||
8. Go to the user or group permissions page, and give yourself (and other administrators) the right to change system settings (under "System" and "Configuration").
|
||||
9. You can now go to the settings page (under "System" and "Settings") and check if all settings are correct.
|
||||
10. Parameters which were previously set via environment variables are greyed out and cannot be changed in the web interface.
|
||||
3. Remove the `var/cache/` directory inside the Part-DB installation to ensure that no old cache files remain.
|
||||
4. Run `composer install --no-dev -o` to update the dependencies.
|
||||
5. Run `yarn install` and `yarn build` to update the frontend assets.
|
||||
6. Rund `php bin/console doctrine:migrations:migrate` to update the database schema.
|
||||
7. Clear the cache with `php bin/console cache:clear`.
|
||||
8. Open your Part-DB instance in the browser and log in as an admin user.
|
||||
9. Go to the user or group permissions page, and give yourself (and other administrators) the right to change system settings (under "System" and "Configuration").
|
||||
10. You can now go to the settings page (under "System" and "Settings") and check if all settings are correct.
|
||||
11. Parameters which were previously set via environment variables are greyed out and cannot be changed in the web interface.
|
||||
If you want to change them, you must migrate them to the settings interface as described below.
|
||||
|
||||
### Docker installation
|
||||
|
|
@ -87,3 +88,15 @@ After the migration run successfully, the contents of your environment variables
|
|||
Go through the environment variables listed by the command and remove them from your environment variable configuration (e.g. `.env.local` file or docker compose file), or just comment them out for now.
|
||||
|
||||
If you want to keep some environment variables, just leave them as they are, they will still work as before, the migration command only affects the settings stored in the database.
|
||||
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### cache:clear fails: You have requested a non-existent parameter "jbtronics.settings.proxy_dir".
|
||||
If you receive an error like
|
||||
```
|
||||
In App_KernelProdContainer.php line 2839:
|
||||
You have requested a non-existent parameter "jbtronics.settings.proxy_dir".
|
||||
```
|
||||
when running `php bin/console cache:clear` or `composer install`. You have to manually delete the `var/cache/`
|
||||
directory inside your Part-DB installation and try again.
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@
|
|||
"bootbox": "^6.0.0",
|
||||
"bootswatch": "^5.1.3",
|
||||
"bs-custom-file-input": "^1.3.4",
|
||||
"ckeditor5": "^46.0.0",
|
||||
"ckeditor5": "^47.0.0",
|
||||
"clipboard": "^2.0.4",
|
||||
"compression-webpack-plugin": "^11.1.0",
|
||||
"datatables.net": "^2.0.0",
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 482 B |
|
Before Width: | Height: | Size: 600 B |
|
Before Width: | Height: | Size: 352 B |
|
Before Width: | Height: | Size: 364 B |
|
Before Width: | Height: | Size: 489 B |
|
Before Width: | Height: | Size: 558 B |
|
Before Width: | Height: | Size: 477 B |
|
Before Width: | Height: | Size: 346 B |
|
Before Width: | Height: | Size: 476 B |
|
Before Width: | Height: | Size: 591 B |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 779 B |
|
Before Width: | Height: | Size: 1,004 B |
|
Before Width: | Height: | Size: 645 B |
|
Before Width: | Height: | Size: 459 B |
|
Before Width: | Height: | Size: 1 KiB |
|
Before Width: | Height: | Size: 362 B |
|
Before Width: | Height: | Size: 471 B |
|
Before Width: | Height: | Size: 510 B |
|
Before Width: | Height: | Size: 134 B |
|
Before Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 1,000 B |
|
Before Width: | Height: | Size: 96 B |
|
Before Width: | Height: | Size: 23 KiB |
|
|
@ -1,131 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
width="384"
|
||||
height="448"
|
||||
viewBox="0 0 384 448"
|
||||
id="svg7"
|
||||
sodipodi:docname="file_all.svg"
|
||||
inkscape:version="0.92.1 r15371">
|
||||
<metadata
|
||||
id="metadata13">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs11" />
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1017"
|
||||
id="namedview9"
|
||||
showgrid="false"
|
||||
inkscape:zoom="0.52678571"
|
||||
inkscape:cx="192"
|
||||
inkscape:cy="192.54785"
|
||||
inkscape:window-x="1272"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg7" />
|
||||
<g
|
||||
id="icomoon-ignore" />
|
||||
<path
|
||||
d="M367 95c9.25 9.25 17 27.75 17 41v288c0 13.25-10.75 24-24 24h-336c-13.25 0-24-10.75-24-24v-400c0-13.25 10.75-24 24-24h224c13.25 0 31.75 7.75 41 17zM256 34v94h94c-1.5-4.25-3.75-8.5-5.5-10.25l-78.25-78.25c-1.75-1.75-6-4-10.25-5.5zM352 416v-256h-104c-13.25 0-24-10.75-24-24v-104h-192v384h320z"
|
||||
id="path5"
|
||||
style="fill:#1a1a1a" />
|
||||
<flowRoot
|
||||
xml:space="preserve"
|
||||
id="flowRoot3687"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none;font-family:sans-serif;font-style:normal;font-weight:normal;font-size:40px;line-height:1.25;letter-spacing:0px;word-spacing:0px;"><flowRegion
|
||||
id="flowRegion3689"
|
||||
style="fill:#ffffff;"><rect
|
||||
id="rect3691"
|
||||
width="251.68207"
|
||||
height="110.74011"
|
||||
x="69.128677"
|
||||
y="214.43904"
|
||||
style="fill:#ffffff;" /></flowRegion><flowPara
|
||||
id="flowPara3693" /></flowRoot> <g
|
||||
aria-label="ALL "
|
||||
transform="matrix(1.7053159,0,0,1.4411413,-124.25849,-88.403923)"
|
||||
style="font-style:normal;font-weight:normal;font-size:40px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#1a1a1a;fill-opacity:1;stroke:none"
|
||||
id="flowRoot3699">
|
||||
<path
|
||||
d="m 114.24512,247.89827 -6.32813,16.17188 h 6.9375 v 4.64062 H 98.260742 v -4.64062 h 4.031248 l 25.92188,-65.90625 h 5.57812 l 25.92188,65.90625 h 4.03125 v 4.64062 h -20.90625 v -4.64062 h 6.32812 l -6.375,-16.17188 z m 1.82812,-4.64062 h 24.89063 l -12.46875,-31.64063 z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:96px;font-family:'Lucida Fax';-inkscape-font-specification:'Lucida Fax';text-align:center;text-anchor:middle;fill:#1a1a1a"
|
||||
id="path40" />
|
||||
<path
|
||||
d="m 218.72949,268.71077 h -48.5625 v -4.64062 h 6.9375 v -60.14063 h -6.9375 v -4.59375 h 23.10938 v 4.59375 h -6.32813 v 59.57813 h 26.01563 v -8.67188 h 5.76562 z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:96px;font-family:'Lucida Fax';-inkscape-font-specification:'Lucida Fax';text-align:center;text-anchor:middle;fill:#1a1a1a"
|
||||
id="path42" />
|
||||
<path
|
||||
d="m 273.66699,268.71077 h -48.5625 v -4.64062 h 6.9375 v -60.14063 h -6.9375 v -4.59375 h 23.10938 v 4.59375 h -6.32813 v 59.57813 h 26.01563 v -8.67188 h 5.76562 z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:96px;font-family:'Lucida Fax';-inkscape-font-specification:'Lucida Fax';text-align:center;text-anchor:middle;fill:#1a1a1a"
|
||||
id="path44" />
|
||||
</g>
|
||||
<g
|
||||
aria-label="DATASHEET"
|
||||
transform="matrix(1.3097344,0,0,1.4436797,-64.263952,-115.73324)"
|
||||
style="font-style:normal;font-weight:normal;font-size:40px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#1a1a1a;fill-opacity:1;stroke:none"
|
||||
id="flowRoot3709">
|
||||
<path
|
||||
d="m 85.748047,302.43555 v 22.67578 h 4.765625 q 6.035156,0 8.828125,-2.73438 2.812503,-2.73437 2.812503,-8.63281 0,-5.85937 -2.812503,-8.57422 -2.792969,-2.73437 -8.828125,-2.73437 z m -3.945313,-3.24219 h 8.105469 q 8.476563,0 12.441407,3.53516 3.96484,3.51562 3.96484,11.01562 0,7.53906 -3.98437,11.07422 -3.984377,3.53516 -12.421877,3.53516 h -8.105469 z"
|
||||
style="text-align:center;text-anchor:middle;fill:#1a1a1a"
|
||||
id="path21" />
|
||||
<path
|
||||
d="m 121.62695,303.08008 -5.35156,14.51172 h 10.72266 z m -2.22656,-3.88672 h 4.47266 l 11.11328,29.16016 h -4.10156 l -2.65625,-7.48047 h -13.14454 l -2.65625,7.48047 h -4.16015 z"
|
||||
style="text-align:center;text-anchor:middle;fill:#1a1a1a"
|
||||
id="path23" />
|
||||
<path
|
||||
d="m 132.05664,299.19336 h 24.66797 v 3.32031 h -10.35156 v 25.83985 h -3.96485 v -25.83985 h -10.35156 z"
|
||||
style="text-align:center;text-anchor:middle;fill:#1a1a1a"
|
||||
id="path25" />
|
||||
<path
|
||||
d="m 167.17383,303.08008 -5.35156,14.51172 h 10.72265 z m -2.22656,-3.88672 h 4.47265 l 11.11328,29.16016 h -4.10156 l -2.65625,-7.48047 h -13.14453 l -2.65625,7.48047 h -4.16016 z"
|
||||
style="text-align:center;text-anchor:middle;fill:#1a1a1a"
|
||||
id="path27" />
|
||||
<path
|
||||
d="m 202.25195,300.15039 v 3.84766 q -2.24609,-1.07422 -4.23828,-1.60157 -1.99219,-0.52734 -3.84765,-0.52734 -3.22266,0 -4.98047,1.25 -1.73828,1.25 -1.73828,3.55469 0,1.93359 1.15234,2.92969 1.17187,0.97656 4.41406,1.58203 l 2.38281,0.48828 q 4.41407,0.83984 6.50391,2.96875 2.10938,2.10937 2.10938,5.66406 0,4.23828 -2.85157,6.42578 -2.83203,2.1875 -8.32031,2.1875 -2.07031,0 -4.41406,-0.46875 -2.32422,-0.46875 -4.82422,-1.38672 v -4.0625 q 2.40234,1.34766 4.70703,2.03125 2.30469,0.6836 4.53125,0.6836 3.37891,0 5.21484,-1.32813 1.83594,-1.32812 1.83594,-3.78906 0,-2.14844 -1.32812,-3.35938 -1.3086,-1.21093 -4.31641,-1.8164 l -2.40234,-0.46875 q -4.41407,-0.87891 -6.38672,-2.75391 -1.97266,-1.875 -1.97266,-5.21484 0,-3.86719 2.71485,-6.09375 2.73437,-2.22656 7.51953,-2.22656 2.05078,0 4.17968,0.37109 2.12891,0.37109 4.35547,1.11328 z"
|
||||
style="text-align:center;text-anchor:middle;fill:#1a1a1a"
|
||||
id="path29" />
|
||||
<path
|
||||
d="m 210.16211,299.19336 h 3.94531 v 11.95312 h 14.33594 v -11.95312 h 3.94531 v 29.16016 h -3.94531 V 314.4668 h -14.33594 v 13.88672 h -3.94531 z"
|
||||
style="text-align:center;text-anchor:middle;fill:#1a1a1a"
|
||||
id="path31" />
|
||||
<path
|
||||
d="m 240.24023,299.19336 h 18.4375 v 3.32031 h -14.49218 v 8.63281 h 13.88672 v 3.32032 h -13.88672 v 10.5664 h 14.84375 v 3.32032 h -18.78907 z"
|
||||
style="text-align:center;text-anchor:middle;fill:#1a1a1a"
|
||||
id="path33" />
|
||||
<path
|
||||
d="m 265.55273,299.19336 h 18.4375 v 3.32031 h -14.49218 v 8.63281 h 13.88672 v 3.32032 h -13.88672 v 10.5664 h 14.84375 v 3.32032 h -18.78907 z"
|
||||
style="text-align:center;text-anchor:middle;fill:#1a1a1a"
|
||||
id="path35" />
|
||||
<path
|
||||
d="m 286.82227,299.19336 h 24.66796 v 3.32031 h -10.35156 v 25.83985 h -3.96484 v -25.83985 h -10.35156 z"
|
||||
style="text-align:center;text-anchor:middle;fill:#1a1a1a"
|
||||
id="path37" />
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 7.4 KiB |
|
|
@ -1,90 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
width="384"
|
||||
height="448"
|
||||
viewBox="0 0 384 448"
|
||||
id="svg7"
|
||||
sodipodi:docname="file_dc.svg"
|
||||
inkscape:version="0.92.1 r15371">
|
||||
<metadata
|
||||
id="metadata13">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs11" />
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1017"
|
||||
id="namedview9"
|
||||
showgrid="false"
|
||||
inkscape:zoom="1.0535715"
|
||||
inkscape:cx="192"
|
||||
inkscape:cy="219.39394"
|
||||
inkscape:window-x="1272"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg7" />
|
||||
<g
|
||||
id="icomoon-ignore" />
|
||||
<path
|
||||
d="M367 95c9.25 9.25 17 27.75 17 41v288c0 13.25-10.75 24-24 24h-336c-13.25 0-24-10.75-24-24v-400c0-13.25 10.75-24 24-24h224c13.25 0 31.75 7.75 41 17zM256 34v94h94c-1.5-4.25-3.75-8.5-5.5-10.25l-78.25-78.25c-1.75-1.75-6-4-10.25-5.5zM352 416v-256h-104c-13.25 0-24-10.75-24-24v-104h-192v384h320z"
|
||||
id="path5"
|
||||
style="fill:#1a1a1a" />
|
||||
<rect
|
||||
id="rect3685"
|
||||
width="289.93774"
|
||||
height="149.66695"
|
||||
x="48.32296"
|
||||
y="188.2641"
|
||||
style="fill:#1a1a1a" />
|
||||
<flowRoot
|
||||
xml:space="preserve"
|
||||
id="flowRoot3687"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none;font-family:sans-serif;font-style:normal;font-weight:normal;font-size:40px;line-height:1.25;letter-spacing:0px;word-spacing:0px;"><flowRegion
|
||||
id="flowRegion3689"
|
||||
style="fill:#ffffff;"><rect
|
||||
id="rect3691"
|
||||
width="251.68207"
|
||||
height="110.74011"
|
||||
x="69.128677"
|
||||
y="214.43904"
|
||||
style="fill:#ffffff;" /></flowRegion><flowPara
|
||||
id="flowPara3693" /></flowRoot> <text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:191.63136292px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:4.79078484"
|
||||
x="33.330128"
|
||||
y="354.68042"
|
||||
id="text3697"
|
||||
transform="scale(1.0793658,0.92646993)"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3695"
|
||||
x="33.330128"
|
||||
y="354.68042"
|
||||
style="fill:#ffffff;stroke-width:4.79078484">DC</tspan></text>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3 KiB |
|
|
@ -1,5 +0,0 @@
|
|||
<!-- Generated by IcoMoon.io -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="24" height="28" viewBox="0 0 24 28">
|
||||
<title>google</title>
|
||||
<path d="M12 12.281h11.328c0.109 0.609 0.187 1.203 0.187 2 0 6.844-4.594 11.719-11.516 11.719-6.641 0-12-5.359-12-12s5.359-12 12-12c3.234 0 5.953 1.188 8.047 3.141l-3.266 3.141c-0.891-0.859-2.453-1.859-4.781-1.859-4.094 0-7.438 3.391-7.438 7.578s3.344 7.578 7.438 7.578c4.75 0 6.531-3.406 6.813-5.172h-6.813v-4.125z"></path>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 485 B |
|
|
@ -1,5 +0,0 @@
|
|||
<!-- Generated by IcoMoon.io -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="24" height="28" viewBox="0 0 24 28">
|
||||
<title>cog</title>
|
||||
<path d="M16 14c0-2.203-1.797-4-4-4s-4 1.797-4 4 1.797 4 4 4 4-1.797 4-4zM24 12.297v3.469c0 0.234-0.187 0.516-0.438 0.562l-2.891 0.438c-0.172 0.5-0.359 0.969-0.609 1.422 0.531 0.766 1.094 1.453 1.672 2.156 0.094 0.109 0.156 0.25 0.156 0.391s-0.047 0.25-0.141 0.359c-0.375 0.5-2.484 2.797-3.016 2.797-0.141 0-0.281-0.063-0.406-0.141l-2.156-1.687c-0.453 0.234-0.938 0.438-1.422 0.594-0.109 0.953-0.203 1.969-0.453 2.906-0.063 0.25-0.281 0.438-0.562 0.438h-3.469c-0.281 0-0.531-0.203-0.562-0.469l-0.438-2.875c-0.484-0.156-0.953-0.344-1.406-0.578l-2.203 1.672c-0.109 0.094-0.25 0.141-0.391 0.141s-0.281-0.063-0.391-0.172c-0.828-0.75-1.922-1.719-2.578-2.625-0.078-0.109-0.109-0.234-0.109-0.359 0-0.141 0.047-0.25 0.125-0.359 0.531-0.719 1.109-1.406 1.641-2.141-0.266-0.5-0.484-1.016-0.641-1.547l-2.859-0.422c-0.266-0.047-0.453-0.297-0.453-0.562v-3.469c0-0.234 0.187-0.516 0.422-0.562l2.906-0.438c0.156-0.5 0.359-0.969 0.609-1.437-0.531-0.75-1.094-1.453-1.672-2.156-0.094-0.109-0.156-0.234-0.156-0.375s0.063-0.25 0.141-0.359c0.375-0.516 2.484-2.797 3.016-2.797 0.141 0 0.281 0.063 0.406 0.156l2.156 1.672c0.453-0.234 0.938-0.438 1.422-0.594 0.109-0.953 0.203-1.969 0.453-2.906 0.063-0.25 0.281-0.438 0.562-0.438h3.469c0.281 0 0.531 0.203 0.562 0.469l0.438 2.875c0.484 0.156 0.953 0.344 1.406 0.578l2.219-1.672c0.094-0.094 0.234-0.141 0.375-0.141s0.281 0.063 0.391 0.156c0.828 0.766 1.922 1.734 2.578 2.656 0.078 0.094 0.109 0.219 0.109 0.344 0 0.141-0.047 0.25-0.125 0.359-0.531 0.719-1.109 1.406-1.641 2.141 0.266 0.5 0.484 1.016 0.641 1.531l2.859 0.438c0.266 0.047 0.453 0.297 0.453 0.562z"></path>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.7 KiB |
|
|
@ -1,98 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
width="384"
|
||||
height="448"
|
||||
viewBox="0 0 384 448"
|
||||
id="svg7"
|
||||
sodipodi:docname="file_reichelt.svg"
|
||||
inkscape:version="0.92.1 r15371">
|
||||
<metadata
|
||||
id="metadata13">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs11" />
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1017"
|
||||
id="namedview9"
|
||||
showgrid="false"
|
||||
inkscape:zoom="0.74498751"
|
||||
inkscape:cx="192"
|
||||
inkscape:cy="218.60367"
|
||||
inkscape:window-x="1272"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg7" />
|
||||
<g
|
||||
id="icomoon-ignore" />
|
||||
<path
|
||||
d="M367 95c9.25 9.25 17 27.75 17 41v288c0 13.25-10.75 24-24 24h-336c-13.25 0-24-10.75-24-24v-400c0-13.25 10.75-24 24-24h224c13.25 0 31.75 7.75 41 17zM256 34v94h94c-1.5-4.25-3.75-8.5-5.5-10.25l-78.25-78.25c-1.75-1.75-6-4-10.25-5.5zM352 416v-256h-104c-13.25 0-24-10.75-24-24v-104h-192v384h320z"
|
||||
id="path5"
|
||||
style="fill:#1a1a1a" />
|
||||
<flowRoot
|
||||
xml:space="preserve"
|
||||
id="flowRoot3687"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none;font-family:sans-serif;font-style:normal;font-weight:normal;font-size:40px;line-height:1.25;letter-spacing:0px;word-spacing:0px;"><flowRegion
|
||||
id="flowRegion3689"
|
||||
style="fill:#ffffff;"><rect
|
||||
id="rect3691"
|
||||
width="251.68207"
|
||||
height="110.74011"
|
||||
x="69.128677"
|
||||
y="214.43904"
|
||||
style="fill:#ffffff;" /></flowRegion><flowPara
|
||||
id="flowPara3693" /></flowRoot> <rect
|
||||
style="fill:#666666;stroke-width:1.27060354"
|
||||
id="rect3719"
|
||||
width="150"
|
||||
height="150"
|
||||
x="98.65937"
|
||||
y="204.70981" />
|
||||
<rect
|
||||
style="fill:#1a1a1a;stroke-width:1.30443311"
|
||||
id="rect3717"
|
||||
width="150"
|
||||
height="150"
|
||||
x="130.20366"
|
||||
y="175.17915" />
|
||||
<rect
|
||||
style="fill:#ffffff;stroke-width:1.07838833"
|
||||
id="rect3721"
|
||||
width="39.59798"
|
||||
height="138.9285"
|
||||
x="153.02271"
|
||||
y="198.33139" />
|
||||
<circle
|
||||
style="fill:#ffffff;stroke-width:1.69401228"
|
||||
id="path3723"
|
||||
cx="227.01927"
|
||||
cy="214.12033"
|
||||
r="30.69738" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3 KiB |
|
Before Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 5.7 KiB |
|
Before Width: | Height: | Size: 706 B |
|
Before Width: | Height: | Size: 606 B |
|
|
@ -25,6 +25,7 @@ namespace App\Controller;
|
|||
|
||||
use App\Entity\Parts\Manufacturer;
|
||||
use App\Entity\Parts\Part;
|
||||
use App\Exceptions\OAuthReconnectRequiredException;
|
||||
use App\Form\InfoProviderSystem\PartSearchType;
|
||||
use App\Services\InfoProviderSystem\ExistingPartFinder;
|
||||
use App\Services\InfoProviderSystem\PartInfoRetriever;
|
||||
|
|
@ -175,8 +176,11 @@ class InfoProviderController extends AbstractController
|
|||
$this->addFlash('error',$e->getMessage());
|
||||
//Log the exception
|
||||
$exceptionLogger->error('Error during info provider search: ' . $e->getMessage(), ['exception' => $e]);
|
||||
} catch (OAuthReconnectRequiredException $e) {
|
||||
$this->addFlash('error', t('info_providers.search.error.oauth_reconnect', ['%provider%' => $e->getProviderName()]));
|
||||
}
|
||||
|
||||
|
||||
// modify the array to an array of arrays that has a field for a matching local Part
|
||||
// the advantage to use that format even when we don't look for local parts is that we
|
||||
// always work with the same interface
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ use App\Exceptions\InvalidRegexException;
|
|||
use App\Form\Filters\PartFilterType;
|
||||
use App\Services\Parts\PartsTableActionHandler;
|
||||
use App\Services\Trees\NodesListBuilder;
|
||||
use App\Settings\BehaviorSettings\SidebarSettings;
|
||||
use App\Settings\BehaviorSettings\TableSettings;
|
||||
use Doctrine\DBAL\Exception\DriverException;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
|
|
@ -56,11 +57,21 @@ class PartListsController extends AbstractController
|
|||
private readonly NodesListBuilder $nodesListBuilder,
|
||||
private readonly DataTableFactory $dataTableFactory,
|
||||
private readonly TranslatorInterface $translator,
|
||||
private readonly TableSettings $tableSettings
|
||||
private readonly TableSettings $tableSettings,
|
||||
private readonly SidebarSettings $sidebarSettings,
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the filter operator to use by default (INCLUDING_CHILDREN or =)
|
||||
* @return string
|
||||
*/
|
||||
private function getFilterOperator(): string
|
||||
{
|
||||
return $this->sidebarSettings->dataStructureNodesTableIncludeChildren ? 'INCLUDING_CHILDREN' : '=';
|
||||
}
|
||||
|
||||
#[Route(path: '/table/action', name: 'table_action', methods: ['POST'])]
|
||||
public function tableAction(Request $request, PartsTableActionHandler $actionHandler): Response
|
||||
{
|
||||
|
|
@ -203,7 +214,7 @@ class PartListsController extends AbstractController
|
|||
return $this->showListWithFilter($request,
|
||||
'parts/lists/category_list.html.twig',
|
||||
function (PartFilter $filter) use ($category) {
|
||||
$filter->category->setOperator('INCLUDING_CHILDREN')->setValue($category);
|
||||
$filter->category->setOperator($this->getFilterOperator())->setValue($category);
|
||||
}, function (FormInterface $filterForm) {
|
||||
$this->disableFormFieldAfterCreation($filterForm->get('category')->get('value'));
|
||||
}, [
|
||||
|
|
@ -221,7 +232,7 @@ class PartListsController extends AbstractController
|
|||
return $this->showListWithFilter($request,
|
||||
'parts/lists/footprint_list.html.twig',
|
||||
function (PartFilter $filter) use ($footprint) {
|
||||
$filter->footprint->setOperator('INCLUDING_CHILDREN')->setValue($footprint);
|
||||
$filter->footprint->setOperator($this->getFilterOperator())->setValue($footprint);
|
||||
}, function (FormInterface $filterForm) {
|
||||
$this->disableFormFieldAfterCreation($filterForm->get('footprint')->get('value'));
|
||||
}, [
|
||||
|
|
@ -239,7 +250,7 @@ class PartListsController extends AbstractController
|
|||
return $this->showListWithFilter($request,
|
||||
'parts/lists/manufacturer_list.html.twig',
|
||||
function (PartFilter $filter) use ($manufacturer) {
|
||||
$filter->manufacturer->setOperator('INCLUDING_CHILDREN')->setValue($manufacturer);
|
||||
$filter->manufacturer->setOperator($this->getFilterOperator())->setValue($manufacturer);
|
||||
}, function (FormInterface $filterForm) {
|
||||
$this->disableFormFieldAfterCreation($filterForm->get('manufacturer')->get('value'));
|
||||
}, [
|
||||
|
|
@ -257,7 +268,7 @@ class PartListsController extends AbstractController
|
|||
return $this->showListWithFilter($request,
|
||||
'parts/lists/store_location_list.html.twig',
|
||||
function (PartFilter $filter) use ($storelocation) {
|
||||
$filter->storelocation->setOperator('INCLUDING_CHILDREN')->setValue($storelocation);
|
||||
$filter->storelocation->setOperator($this->getFilterOperator())->setValue($storelocation);
|
||||
}, function (FormInterface $filterForm) {
|
||||
$this->disableFormFieldAfterCreation($filterForm->get('storelocation')->get('value'));
|
||||
}, [
|
||||
|
|
@ -275,7 +286,7 @@ class PartListsController extends AbstractController
|
|||
return $this->showListWithFilter($request,
|
||||
'parts/lists/supplier_list.html.twig',
|
||||
function (PartFilter $filter) use ($supplier) {
|
||||
$filter->supplier->setOperator('INCLUDING_CHILDREN')->setValue($supplier);
|
||||
$filter->supplier->setOperator($this->getFilterOperator())->setValue($supplier);
|
||||
}, function (FormInterface $filterForm) {
|
||||
$this->disableFormFieldAfterCreation($filterForm->get('supplier')->get('value'));
|
||||
}, [
|
||||
|
|
|
|||
|
|
@ -96,14 +96,15 @@ class TextConstraint extends AbstractConstraint
|
|||
|
||||
//The CONTAINS, LIKE, STARTS and ENDS operators use the LIKE operator, but we have to build the value string differently
|
||||
$like_value = null;
|
||||
$escaped_value = str_replace(['%', '_'], ['\%', '\_'], $this->value);
|
||||
if ($this->operator === 'LIKE') {
|
||||
$like_value = $this->value;
|
||||
$like_value = $this->value; //Here we do not escape anything, as the user may provide % and _ wildcards
|
||||
} elseif ($this->operator === 'STARTS') {
|
||||
$like_value = $this->value . '%';
|
||||
$like_value = $escaped_value . '%';
|
||||
} elseif ($this->operator === 'ENDS') {
|
||||
$like_value = '%' . $this->value;
|
||||
$like_value = '%' . $escaped_value;
|
||||
} elseif ($this->operator === 'CONTAINS') {
|
||||
$like_value = '%' . $this->value . '%';
|
||||
$like_value = '%' . $escaped_value . '%';
|
||||
}
|
||||
|
||||
if ($like_value !== null) {
|
||||
|
|
|
|||
|
|
@ -144,6 +144,8 @@ class PartSearchFilter implements FilterInterface
|
|||
if ($this->regex) {
|
||||
$queryBuilder->setParameter('search_query', $this->keyword);
|
||||
} else {
|
||||
//Escape % and _ characters in the keyword
|
||||
$this->keyword = str_replace(['%', '_'], ['\%', '\_'], $this->keyword);
|
||||
$queryBuilder->setParameter('search_query', '%' . $this->keyword . '%');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,7 +56,6 @@ class ILike extends FunctionNode
|
|||
{
|
||||
$platform = $sqlWalker->getConnection()->getDatabasePlatform();
|
||||
|
||||
//
|
||||
if ($platform instanceof AbstractMySQLPlatform || $platform instanceof SQLitePlatform) {
|
||||
$operator = 'LIKE';
|
||||
} elseif ($platform instanceof PostgreSQLPlatform) {
|
||||
|
|
@ -66,6 +65,12 @@ class ILike extends FunctionNode
|
|||
throw new \RuntimeException('Platform ' . gettype($platform) . ' does not support case insensitive like expressions.');
|
||||
}
|
||||
|
||||
return '(' . $this->value->dispatch($sqlWalker) . ' ' . $operator . ' ' . $this->expr->dispatch($sqlWalker) . ')';
|
||||
$escape = "";
|
||||
if ($platform instanceof SQLitePlatform) {
|
||||
//SQLite needs ESCAPE explicitly defined backslash as escape character
|
||||
$escape = " ESCAPE '\\'";
|
||||
}
|
||||
|
||||
return '(' . $this->value->dispatch($sqlWalker) . ' ' . $operator . ' ' . $this->expr->dispatch($sqlWalker) . $escape . ')';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ trait ProjectTrait
|
|||
/**
|
||||
* @var Collection<ProjectBOMEntry> $project_bom_entries
|
||||
*/
|
||||
#[ORM\OneToMany(mappedBy: 'part', targetEntity: ProjectBOMEntry::class, cascade: ['remove'], orphanRemoval: true)]
|
||||
#[ORM\OneToMany(targetEntity: ProjectBOMEntry::class, mappedBy: 'part')]
|
||||
protected Collection $project_bom_entries;
|
||||
|
||||
/**
|
||||
|
|
|
|||
59
src/EntityListeners/PartProjectBOMEntryUnlinkListener.php
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
<?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\EntityListeners;
|
||||
|
||||
use App\Entity\Parts\Part;
|
||||
use Doctrine\Bundle\DoctrineBundle\Attribute\AsEntityListener;
|
||||
use Doctrine\ORM\Event\PreRemoveEventArgs;
|
||||
|
||||
/**
|
||||
* If an part is deleted, this listener makes sure that all ProjectBOMEntries that reference this part, are updated
|
||||
* to not reference the part anymore, but instead store the part name in the name field.
|
||||
*/
|
||||
#[AsEntityListener(event: "preRemove", entity: Part::class)]
|
||||
class PartProjectBOMEntryUnlinkListener
|
||||
{
|
||||
public function preRemove(Part $part, PreRemoveEventArgs $event): void
|
||||
{
|
||||
// Iterate over all ProjectBOMEntries that use this part and put the part name into the name field
|
||||
foreach ($part->getProjectBomEntries() as $bom_entry) {
|
||||
$old_name = $bom_entry->getName();
|
||||
if ($old_name === null || trim($old_name) === '') {
|
||||
$bom_entry->setName($part->getName());
|
||||
} else {
|
||||
$bom_entry->setName($old_name . ' (' . $part->getName() . ')');
|
||||
}
|
||||
|
||||
$old_comment = $bom_entry->getComment();
|
||||
if ($old_comment === null || trim($old_comment) === '') {
|
||||
$bom_entry->setComment('Part was deleted: ' . $part->getName());
|
||||
} else {
|
||||
$bom_entry->setComment($old_comment . "\n\n Part was deleted: " . $part->getName());
|
||||
}
|
||||
|
||||
//Remove the part reference
|
||||
$bom_entry->setPart(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
48
src/Exceptions/OAuthReconnectRequiredException.php
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
<?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\Exceptions;
|
||||
|
||||
use Throwable;
|
||||
|
||||
class OAuthReconnectRequiredException extends \RuntimeException
|
||||
{
|
||||
private string $providerName = "unknown";
|
||||
|
||||
public function __construct(string $message = "You need to reconnect the OAuth connection for this provider!", int $code = 0, ?Throwable $previous = null)
|
||||
{
|
||||
parent::__construct($message, $code, $previous);
|
||||
}
|
||||
|
||||
public static function forProvider(string $providerName): self
|
||||
{
|
||||
$exception = new self("You need to reconnect the OAuth connection for the provider '$providerName'!");
|
||||
$exception->providerName = $providerName;
|
||||
return $exception;
|
||||
}
|
||||
|
||||
public function getProviderName(): string
|
||||
{
|
||||
return $this->providerName;
|
||||
}
|
||||
}
|
||||
57
src/Form/Type/LanguageMenuEntriesType.php
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
<?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\Form\Type;
|
||||
|
||||
use Symfony\Component\DependencyInjection\Attribute\Autowire;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\LanguageType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\LocaleType;
|
||||
use Symfony\Component\Intl\Languages;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
class LanguageMenuEntriesType extends AbstractType
|
||||
{
|
||||
public function __construct(#[Autowire(param: 'partdb.locale_menu')] private readonly array $preferred_languages)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function getParent(): string
|
||||
{
|
||||
return LanguageType::class;
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
{
|
||||
$choices = [];
|
||||
foreach ($this->preferred_languages as $lang_code) {
|
||||
$choices[Languages::getName($lang_code)] = $lang_code;
|
||||
}
|
||||
|
||||
$resolver->setDefaults([
|
||||
'choice_loader' => null,
|
||||
'choices' => $choices,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
@ -38,6 +38,11 @@ class SIFormatter
|
|||
*/
|
||||
public function getMagnitude(float $value): int
|
||||
{
|
||||
//Check for zero, as log10(0) is undefined/gives -infinity, which leads to casting issues in PHP8.5+
|
||||
if (0.0 === $value) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (int) floor(log10(abs($value)));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -221,7 +221,7 @@ final class DTOtoEntityConverter
|
|||
$attachment = $this->convertFile($image, $image_type);
|
||||
|
||||
$attachments_grouped[$attachment->getName()][] = $attachment;
|
||||
if (count($attachments_grouped[$attachment->getName()] ?? []) > 1) {
|
||||
if (count($attachments_grouped[$attachment->getName()]) > 1) {
|
||||
$attachment->setName($attachment->getName() . ' (' . (count($attachments_grouped[$attachment->getName()]) + 1) . ')');
|
||||
}
|
||||
|
||||
|
|
@ -236,7 +236,7 @@ final class DTOtoEntityConverter
|
|||
$attachment = $this->convertFile($datasheet, $datasheet_type);
|
||||
|
||||
$attachments_grouped[$attachment->getName()][] = $attachment;
|
||||
if (count($attachments_grouped[$attachment->getName()] ?? []) > 1) {
|
||||
if (count($attachments_grouped[$attachment->getName()]) > 1) {
|
||||
$attachment->setName($attachment->getName() . ' (' . (count($attachments_grouped[$attachment->getName()])) . ')');
|
||||
}
|
||||
|
||||
|
|
@ -357,4 +357,4 @@ final class DTOtoEntityConverter
|
|||
return $tmp;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ declare(strict_types=1);
|
|||
namespace App\Services\InfoProviderSystem\Providers;
|
||||
|
||||
use App\Entity\Parts\ManufacturingStatus;
|
||||
use App\Exceptions\OAuthReconnectRequiredException;
|
||||
use App\Services\InfoProviderSystem\DTOs\FileDTO;
|
||||
use App\Services\InfoProviderSystem\DTOs\ParameterDTO;
|
||||
use App\Services\InfoProviderSystem\DTOs\PartDetailDTO;
|
||||
|
|
@ -117,12 +118,22 @@ class DigikeyProvider implements InfoProviderInterface
|
|||
];
|
||||
|
||||
//$response = $this->digikeyClient->request('POST', '/Search/v3/Products/Keyword', [
|
||||
$response = $this->digikeyClient->request('POST', '/products/v4/search/keyword', [
|
||||
'json' => $request,
|
||||
'auth_bearer' => $this->authTokenManager->getAlwaysValidTokenString(self::OAUTH_APP_NAME)
|
||||
]);
|
||||
try {
|
||||
$response = $this->digikeyClient->request('POST', '/products/v4/search/keyword', [
|
||||
'json' => $request,
|
||||
'auth_bearer' => $this->authTokenManager->getAlwaysValidTokenString(self::OAUTH_APP_NAME)
|
||||
]);
|
||||
|
||||
$response_array = $response->toArray();
|
||||
} catch (\InvalidArgumentException $exception) {
|
||||
//Check if the exception was caused by an invalid or expired token
|
||||
if (str_contains($exception->getMessage(), 'access_token')) {
|
||||
throw OAuthReconnectRequiredException::forProvider($this->getProviderKey());
|
||||
}
|
||||
|
||||
throw $exception;
|
||||
}
|
||||
|
||||
$response_array = $response->toArray();
|
||||
|
||||
|
||||
$result = [];
|
||||
|
|
@ -150,9 +161,18 @@ class DigikeyProvider implements InfoProviderInterface
|
|||
|
||||
public function getDetails(string $id): PartDetailDTO
|
||||
{
|
||||
$response = $this->digikeyClient->request('GET', '/products/v4/search/' . urlencode($id) . '/productdetails', [
|
||||
'auth_bearer' => $this->authTokenManager->getAlwaysValidTokenString(self::OAUTH_APP_NAME)
|
||||
]);
|
||||
try {
|
||||
$response = $this->digikeyClient->request('GET', '/products/v4/search/' . urlencode($id) . '/productdetails', [
|
||||
'auth_bearer' => $this->authTokenManager->getAlwaysValidTokenString(self::OAUTH_APP_NAME)
|
||||
]);
|
||||
} catch (\InvalidArgumentException $exception) {
|
||||
//Check if the exception was caused by an invalid or expired token
|
||||
if (str_contains($exception->getMessage(), 'access_token')) {
|
||||
throw OAuthReconnectRequiredException::forProvider($this->getProviderKey());
|
||||
}
|
||||
|
||||
throw $exception;
|
||||
}
|
||||
|
||||
$response_array = $response->toArray();
|
||||
$product = $response_array['Product'];
|
||||
|
|
|
|||
|
|
@ -31,9 +31,9 @@ use App\Services\Parts\PartLotWithdrawAddHelper;
|
|||
/**
|
||||
* @see \App\Tests\Services\ProjectSystem\ProjectBuildHelperTest
|
||||
*/
|
||||
class ProjectBuildHelper
|
||||
final readonly class ProjectBuildHelper
|
||||
{
|
||||
public function __construct(private readonly PartLotWithdrawAddHelper $withdraw_add_helper)
|
||||
public function __construct(private PartLotWithdrawAddHelper $withdraw_add_helper)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -63,20 +63,37 @@ class ProjectBuildHelper
|
|||
*/
|
||||
public function getMaximumBuildableCount(Project $project): int
|
||||
{
|
||||
$bom_entries = $project->getBomEntries();
|
||||
if ($bom_entries->isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
$maximum_buildable_count = PHP_INT_MAX;
|
||||
foreach ($project->getBomEntries() as $bom_entry) {
|
||||
foreach ($bom_entries as $bom_entry) {
|
||||
//Skip BOM entries without a part (as we can not determine that)
|
||||
if (!$bom_entry->isPartBomEntry()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//The maximum buildable count for the whole project is the minimum of all BOM entries
|
||||
$maximum_buildable_count = min($maximum_buildable_count, $this->getMaximumBuildableCountForBOMEntry($bom_entry));
|
||||
}
|
||||
|
||||
return $maximum_buildable_count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the maximum buildable amount of the given project as string, based on the stock of the used parts in the BOM.
|
||||
* If the maximum buildable count is infinite, the string '∞' is returned.
|
||||
* @param Project $project
|
||||
* @return string
|
||||
*/
|
||||
public function getMaximumBuildableCountAsString(Project $project): string
|
||||
{
|
||||
$max_count = $this->getMaximumBuildableCount($project);
|
||||
if ($max_count === PHP_INT_MAX) {
|
||||
return '∞';
|
||||
}
|
||||
return (string) $max_count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given project can be built with the current stock.
|
||||
* This means that the maximum buildable count is greater or equal than the requested $number_of_projects
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ namespace App\Settings;
|
|||
use App\Settings\BehaviorSettings\BehaviorSettings;
|
||||
use App\Settings\InfoProviderSystem\InfoProviderSettings;
|
||||
use App\Settings\MiscSettings\MiscSettings;
|
||||
use App\Settings\SystemSettings\AttachmentsSettings;
|
||||
use App\Settings\SystemSettings\SystemSettings;
|
||||
use Jbtronics\SettingsBundle\Settings\EmbeddedSettings;
|
||||
use Jbtronics\SettingsBundle\Settings\Settings;
|
||||
use Jbtronics\SettingsBundle\Settings\SettingsTrait;
|
||||
|
|
@ -49,4 +49,4 @@ class AppSettings
|
|||
|
||||
#[EmbeddedSettings()]
|
||||
public ?MiscSettings $miscSettings = null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,8 +26,9 @@ namespace App\Settings\BehaviorSettings;
|
|||
use Jbtronics\SettingsBundle\Settings\EmbeddedSettings;
|
||||
use Jbtronics\SettingsBundle\Settings\Settings;
|
||||
use Jbtronics\SettingsBundle\Settings\SettingsTrait;
|
||||
use Symfony\Component\Translation\TranslatableMessage as TM;
|
||||
|
||||
#[Settings]
|
||||
#[Settings(label: new TM("settings.behavior"))]
|
||||
class BehaviorSettings
|
||||
{
|
||||
use SettingsTrait;
|
||||
|
|
@ -40,4 +41,4 @@ class BehaviorSettings
|
|||
|
||||
#[EmbeddedSettings]
|
||||
public ?PartInfoSettings $partInfo = null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,4 +73,11 @@ class SidebarSettings
|
|||
*/
|
||||
#[SettingsParameter(label: new TM("settings.behavior.sidebar.rootNodeRedirectsToNewEntity"))]
|
||||
public bool $rootNodeRedirectsToNewEntity = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @var bool Whether to include child nodes in the data structure nodes table, or only show the selected node's parts.
|
||||
*/
|
||||
#[SettingsParameter(label: new TM("settings.behavior.sidebar.data_structure_nodes_table_include_children"),
|
||||
description: new TM("settings.behavior.sidebar.data_structure_nodes_table_include_children.help"))]
|
||||
public bool $dataStructureNodesTableIncludeChildren = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,8 +27,9 @@ use Jbtronics\SettingsBundle\Settings\EmbeddedSettings;
|
|||
use Jbtronics\SettingsBundle\Settings\Settings;
|
||||
use Jbtronics\SettingsBundle\Settings\SettingsParameter;
|
||||
use Jbtronics\SettingsBundle\Settings\SettingsTrait;
|
||||
use Symfony\Component\Translation\TranslatableMessage as TM;
|
||||
|
||||
#[Settings()]
|
||||
#[Settings(label: new TM("settings.ips"))]
|
||||
class InfoProviderSettings
|
||||
{
|
||||
use SettingsTrait;
|
||||
|
|
|
|||
|
|
@ -25,8 +25,9 @@ namespace App\Settings\MiscSettings;
|
|||
|
||||
use Jbtronics\SettingsBundle\Settings\EmbeddedSettings;
|
||||
use Jbtronics\SettingsBundle\Settings\Settings;
|
||||
use Symfony\Component\Translation\TranslatableMessage as TM;
|
||||
|
||||
#[Settings]
|
||||
#[Settings(label: new TM("settings.misc"))]
|
||||
class MiscSettings
|
||||
{
|
||||
#[EmbeddedSettings]
|
||||
|
|
@ -34,4 +35,4 @@ class MiscSettings
|
|||
|
||||
#[EmbeddedSettings]
|
||||
public ?ExchangeRateSettings $exchangeRate = null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,9 +23,12 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Settings\SystemSettings;
|
||||
|
||||
use App\Form\Type\LanguageMenuEntriesType;
|
||||
use App\Form\Type\LocaleSelectType;
|
||||
use App\Settings\SettingsIcon;
|
||||
use Jbtronics\SettingsBundle\Metadata\EnvVarMode;
|
||||
use Jbtronics\SettingsBundle\ParameterTypes\ArrayType;
|
||||
use Jbtronics\SettingsBundle\ParameterTypes\StringType;
|
||||
use Jbtronics\SettingsBundle\Settings\Settings;
|
||||
use Jbtronics\SettingsBundle\Settings\SettingsParameter;
|
||||
use Jbtronics\SettingsBundle\Settings\SettingsTrait;
|
||||
|
|
@ -60,4 +63,14 @@ class LocalizationSettings
|
|||
envVar: "string:BASE_CURRENCY", envVarMode: EnvVarMode::OVERWRITE
|
||||
)]
|
||||
public string $baseCurrency = 'EUR';
|
||||
}
|
||||
|
||||
#[SettingsParameter(type: ArrayType::class,
|
||||
label: new TM("settings.system.localization.language_menu_entries"),
|
||||
description: new TM("settings.system.localization.language_menu_entries.description"),
|
||||
options: ['type' => StringType::class],
|
||||
formType: LanguageMenuEntriesType::class,
|
||||
formOptions: ['multiple' => true, 'required' => false, 'ordered' => true],
|
||||
)]
|
||||
#[Assert\All([new Assert\Locale()])]
|
||||
public array $languageMenuEntries = [];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,17 +21,13 @@
|
|||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Settings;
|
||||
namespace App\Settings\SystemSettings;
|
||||
|
||||
use App\Settings\SystemSettings\AttachmentsSettings;
|
||||
use App\Settings\SystemSettings\CustomizationSettings;
|
||||
use App\Settings\SystemSettings\HistorySettings;
|
||||
use App\Settings\SystemSettings\LocalizationSettings;
|
||||
use App\Settings\SystemSettings\PrivacySettings;
|
||||
use Jbtronics\SettingsBundle\Settings\EmbeddedSettings;
|
||||
use Jbtronics\SettingsBundle\Settings\Settings;
|
||||
use Symfony\Component\Translation\TranslatableMessage as TM;
|
||||
|
||||
#[Settings]
|
||||
#[Settings(label: new TM("settings.system"))]
|
||||
class SystemSettings
|
||||
{
|
||||
#[EmbeddedSettings()]
|
||||
|
|
@ -48,4 +44,4 @@ class SystemSettings
|
|||
|
||||
#[EmbeddedSettings()]
|
||||
public ?HistorySettings $history = null;
|
||||
}
|
||||
}
|
||||
|
|
@ -82,7 +82,7 @@ final class FormatExtension extends AbstractExtension
|
|||
public function formatBytes(int $bytes, int $precision = 2): string
|
||||
{
|
||||
$size = ['B','kB','MB','GB','TB','PB','EB','ZB','YB'];
|
||||
$factor = floor((strlen((string) $bytes) - 1) / 3);
|
||||
$factor = (int) floor((strlen((string) $bytes) - 1) / 3);
|
||||
//We use the real (10 based) SI prefix here
|
||||
return sprintf("%.{$precision}f", $bytes / (1000 ** $factor)) . ' ' . @$size[$factor];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,9 +22,14 @@
|
|||
<div class="d-none" data-title="{{ current_page_title|trim|raw }}" {{ stimulus_controller('turbo/title') }}></div>
|
||||
|
||||
<div class="d-none" {{ stimulus_controller('turbo/locale_menu') }}>
|
||||
{% for locale in locale_menu %}
|
||||
{% set locales = settings_instance('localization').languageMenuEntries %}
|
||||
{% if locales is empty %}
|
||||
{% set locales = locale_menu %}
|
||||
{% endif %}
|
||||
|
||||
{% for locale in locales %}
|
||||
<a class="dropdown-item" data-turbo="false" data-turbo-frame="_top" href="{{ path(app.request.attributes.get('_route'),
|
||||
app.request.query.all|merge(app.request.attributes.get('_route_params'))|merge({'_locale': locale})) }}">
|
||||
{{ locale|language_name }} ({{ locale|upper }})</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -66,12 +66,6 @@
|
|||
{% block javascripts %}
|
||||
{{ encore_entry_script_tags('app') }}
|
||||
{{ encore_entry_script_tags('webauthn_tfa') }}
|
||||
|
||||
{# load translation files for ckeditor #}
|
||||
{% set two_chars_locale = app.request.locale|default("en")|slice(0,2) %}
|
||||
{% if two_chars_locale != "en" %}
|
||||
<script src="{{ asset("build/ckeditor_translations/" ~ two_chars_locale ~ ".js") }}"></script>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
</head>
|
||||
<body data-base-url="{{ path('homepage', {'_locale': app.request.locale}) }}" data-locale="{{ app.request.locale|default("en")|slice(0,2) }}">
|
||||
|
|
|
|||
|
|
@ -70,18 +70,20 @@
|
|||
{% endif %}
|
||||
|
||||
{% if show_presets %}
|
||||
{# This hidden field is there to ensure that none of the presets is submitted, if a user presses enter #}
|
||||
<input type="submit" name="group_admin_form[save]" class="d-none">
|
||||
<div class="col text-end">
|
||||
<div class="btn-group">
|
||||
<button type="button" class="btn btn-secondary dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
{% trans %}permission.preset.button{% endtrans %}
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><button type="submit" name="permission_preset" value="read_only" class="dropdown-item" >{% trans %}permission.preset.read_only{% endtrans%} <br><small class="text-muted">{% trans %}permission.preset.read_only.desc{% endtrans%}</small></button></li>
|
||||
<li><button type="submit" name="permission_preset" value="editor" class="dropdown-item" >{% trans %}permission.preset.editor{% endtrans%} <br><small class="text-muted">{% trans %}permission.preset.editor.desc{% endtrans%}</small></button></li>
|
||||
<li><button type="submit" name="permission_preset" value="admin" class="dropdown-item" >{% trans %}permission.preset.admin{% endtrans%} <br><small class="text-muted">{% trans %}permission.preset.admin.desc{% endtrans%}</small></button></li>
|
||||
<li><button type="submit" name="permission_preset" value="read_only" class="dropdown-item">{% trans %}permission.preset.read_only{% endtrans%} <br><small class="text-muted">{% trans %}permission.preset.read_only.desc{% endtrans%}</small></button></li>
|
||||
<li><button type="submit" name="permission_preset" value="editor" class="dropdown-item">{% trans %}permission.preset.editor{% endtrans%} <br><small class="text-muted">{% trans %}permission.preset.editor.desc{% endtrans%}</small></button></li>
|
||||
<li><button type="submit" name="permission_preset" value="admin" class="dropdown-item">{% trans %}permission.preset.admin{% endtrans%} <br><small class="text-muted">{% trans %}permission.preset.admin.desc{% endtrans%}</small></button></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><button type="submit" name="permission_preset" value="all_inherit" class="dropdown-item" >{% trans %}permission.preset.all_inherit{% endtrans%}<br><small class="text-muted">{% trans %}permission.preset.all_inherit.desc{% endtrans%}</small></button></li>
|
||||
<li><button type="submit" name="permission_preset" value="all_forbid" class="dropdown-item" >{% trans %}permission.preset.all_forbid{% endtrans%}<br><small class="text-muted">{% trans %}permission.preset.all_forbid.desc{% endtrans%}</small></button></li>
|
||||
<li><button type="submit" name="permission_preset" value="all_inherit" class="dropdown-item">{% trans %}permission.preset.all_inherit{% endtrans%}<br><small class="text-muted">{% trans %}permission.preset.all_inherit.desc{% endtrans%}</small></button></li>
|
||||
<li><button type="submit" name="permission_preset" value="all_forbid" class="dropdown-item">{% trans %}permission.preset.all_forbid{% endtrans%}<br><small class="text-muted">{% trans %}permission.preset.all_forbid.desc{% endtrans%}</small></button></li>
|
||||
<li><button type="submit" name="permission_preset" value="all_allow" class="dropdown-item" >{% trans %}permission.preset.all_allow{% endtrans%}<br><small class="text-muted">{% trans %}permission.preset.all_allow.desc{% endtrans%}</small></button></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
|
@ -110,4 +112,4 @@
|
|||
{% endfor %}
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
|
|
|||
|
|
@ -214,11 +214,11 @@
|
|||
{% endmacro %}
|
||||
|
||||
{% macro parameters_table(parameters) %}
|
||||
<table class="table table-hover table-striped table-sm">
|
||||
<table class="table table-hover table-striped table-sm" style="table-layout: fixed;">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{% trans %}specifications.property{% endtrans %}</th>
|
||||
<th>{% trans %}specifications.symbol{% endtrans %}</th>
|
||||
<th class="col-sm-1">{% trans %}specifications.symbol{% endtrans %}</th>
|
||||
<th>{% trans %}specifications.value{% endtrans %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
|
@ -240,4 +240,4 @@
|
|||
{% else %}
|
||||
{{ datetime|format_datetime }}
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
{% endmacro %}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,9 @@
|
|||
{% block card_content %}
|
||||
{{ form_start(form) }}
|
||||
|
||||
{# Default submit to use when pressing enter. #}
|
||||
<input type="submit" name="label_dialog[update]" class="d-none">
|
||||
|
||||
<ul class="nav nav-tabs">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" data-bs-toggle="tab" id="common-tab" role="tab" aria-controls="common" aria-selected="true" href="#common"
|
||||
|
|
|
|||
|
|
@ -16,15 +16,18 @@
|
|||
</head>
|
||||
<body>
|
||||
{% for element in elements %}
|
||||
{# The page div ensures the page breaks, while the page-inner elements restrict the content to the page size. Sine dompdf 3.1.1 we cannot apply the position: absolute; to the page element directly. #}
|
||||
<div class="page">
|
||||
{% if options.barcodeType.none %}
|
||||
{% include "label_system/labels/label_page_none.html.twig" %}
|
||||
{% elseif options.barcodeType.is2D() %}
|
||||
{% include "label_system/labels/label_page_qr.html.twig" %}
|
||||
{% elseif options.barcodeType.is1D() %}
|
||||
{% include "label_system/labels/label_page_1d.html.twig" %}
|
||||
{% endif %}
|
||||
<div class="page-inner">
|
||||
{% if options.barcodeType.none %}
|
||||
{% include "label_system/labels/label_page_none.html.twig" %}
|
||||
{% elseif options.barcodeType.is2D() %}
|
||||
{% include "label_system/labels/label_page_qr.html.twig" %}
|
||||
{% elseif options.barcodeType.is1D() %}
|
||||
{% include "label_system/labels/label_page_1d.html.twig" %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -3,17 +3,31 @@
|
|||
}
|
||||
|
||||
.page {
|
||||
/** We cannot apply the position: absolute trick here, because then dompdf will not respect the page break anymore **/
|
||||
|
||||
page-break-inside: avoid;
|
||||
page-break-before: avoid;
|
||||
page-break-after: always;
|
||||
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.page-inner {
|
||||
/* Absolute position prevents automatic page breaks */
|
||||
/*position: absolute;*/
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
overflow: hidden;
|
||||
|
||||
page-break-inside: avoid;
|
||||
page-break-before: avoid;
|
||||
page-break-after: avoid;
|
||||
}
|
||||
|
||||
/* Last page should not break */
|
||||
|
|
|
|||
|
|
@ -4,6 +4,9 @@
|
|||
{% for name, parameters in part.groupedParameters %}
|
||||
{% if name is not empty %}<h5 class="mt-1">{{ name }}</h5>{% endif %}
|
||||
{{ helper.parameters_table(parameters) }}
|
||||
{% if not loop.last %}
|
||||
<hr class="my-0">
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% if description_params is not empty %}
|
||||
|
|
@ -14,4 +17,4 @@
|
|||
{% if comment_params is not empty %}
|
||||
<h5 class="mt-1">{% trans %}parameters.auto_extracted_from_comment{% endtrans %}</h5>
|
||||
{{ helper.parameters_table(comment_params) }}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,8 @@
|
|||
{% endblock %}
|
||||
|
||||
{% block card_content %}
|
||||
{% set can_build = buildHelper.projectBuildable(project, number_of_builds) %}
|
||||
{% set bom_empty = project.bomEntries | length == 0 %}
|
||||
{% set can_build = not bom_empty and buildHelper.projectBuildable(project, number_of_builds) %}
|
||||
{% import "components/projects.macro.html.twig" as project_macros %}
|
||||
|
||||
{% if project.status is not empty and project.status != "in_production" %}
|
||||
|
|
@ -17,8 +18,10 @@
|
|||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="alert {% if can_build %}alert-success{% else %}alert-danger{% endif %}" role="alert">
|
||||
{% if not can_build %}
|
||||
<div class="alert {% if can_build %}alert-success{% elseif bom_empty%}alert-warning{% else %}alert-danger{% endif %}" role="alert">
|
||||
{% if bom_empty %}
|
||||
<h5><i class="fa-solid fa-circle-exclamation fa-fw"></i> {% trans %}project.builds.no_bom_entries{% endtrans %}</h5>
|
||||
{% elseif not can_build %}
|
||||
<h5><i class="fa-solid fa-circle-exclamation fa-fw"></i> {% trans %}project.builds.build_not_possible{% endtrans %}</h5>
|
||||
<b>{% trans with {"%number_of_builds%": number_of_builds} %}project.builds.following_bom_entries_miss_instock_n{% endtrans %}</b>
|
||||
<ul>
|
||||
|
|
@ -37,4 +40,4 @@
|
|||
{% include 'projects/build/_form.html.twig' %}
|
||||
|
||||
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
{% set can_build = buildHelper.projectBuildable(project) %}
|
||||
{% set bom_empty = project.bomEntries | length == 0 %}
|
||||
{% set can_build = not bom_empty and buildHelper.projectBuildable(project) %}
|
||||
|
||||
{% import "components/projects.macro.html.twig" as project_macros %}
|
||||
|
||||
|
|
@ -8,8 +9,10 @@
|
|||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="alert mt-2 {% if can_build %}alert-success{% else %}alert-danger{% endif %}" role="alert">
|
||||
{% if not can_build %}
|
||||
<div class="alert mt-2 {% if can_build %}alert-success{% elseif bom_empty%}alert-warning{% else %}alert-danger{% endif %}" role="alert">
|
||||
{% if bom_empty %}
|
||||
<h5><i class="fa-solid fa-circle-exclamation fa-fw"></i> {% trans %}project.builds.no_bom_entries{% endtrans %}</h5>
|
||||
{% elseif not can_build %}
|
||||
<h5><i class="fa-solid fa-circle-exclamation fa-fw"></i> {% trans %}project.builds.build_not_possible{% endtrans %}</h5>
|
||||
<b>{% trans %}project.builds.following_bom_entries_miss_instock{% endtrans %}</b>
|
||||
<ul>
|
||||
|
|
@ -19,7 +22,7 @@
|
|||
</ul>
|
||||
{% else %}
|
||||
<h5><i class="fa-solid fa-circle-check fa-fw"></i> {% trans %}project.builds.build_possible{% endtrans %}</h5>
|
||||
<span>{% trans with {"%max_builds%": buildHelper.maximumBuildableCount(project)} %}project.builds.number_of_builds_possible{% endtrans %}</span>
|
||||
<span>{% trans with {"%max_builds%": buildHelper.maximumBuildableCountAsString(project)} %}project.builds.number_of_builds_possible{% endtrans %}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
|
|
@ -27,7 +30,7 @@
|
|||
<div class="row mt-2">
|
||||
<div class="col-4">
|
||||
<div class="input-group mb-3">
|
||||
<input type="number" min="1" class="form-control" placeholder="{% trans %}project.builds.number_of_builds{% endtrans %}" name="n" required>
|
||||
<input type="number" min="1" class="form-control" placeholder="{% trans %}project.builds.number_of_builds{% endtrans %}" name="n" required value="1">
|
||||
<input type="hidden" name="_redirect" value="{{ uri_without_host(app.request) }}">
|
||||
<button class="btn btn-outline-secondary" type="submit" id="button-addon2">{% trans %}project.build.btn_build{% endtrans %}</button>
|
||||
</div>
|
||||
|
|
@ -37,4 +40,4 @@
|
|||
|
||||
{% if project.buildPart %}
|
||||
<p><b>{% trans %}project.builds.no_stocked_builds{% endtrans %}:</b> <a href="{{ entity_url(project.buildPart) }}">{{ project.buildPart.amountSum }}</a></p>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
|
|
|||
|
|
@ -114,4 +114,22 @@ class ProjectBuildHelperTest extends WebTestCase
|
|||
$this->assertSame(0, $this->service->getMaximumBuildableCount($project));
|
||||
|
||||
}
|
||||
|
||||
public function testGetMaximumBuildableCountEmpty(): void
|
||||
{
|
||||
$project = new Project();
|
||||
|
||||
$this->assertSame(0, $this->service->getMaximumBuildableCount($project));
|
||||
}
|
||||
|
||||
public function testGetMaximumBuildableCountAsString(): void
|
||||
{
|
||||
$project = new Project();
|
||||
$bom_entry1 = new ProjectBOMEntry();
|
||||
$bom_entry1->setName("Test");
|
||||
$project->addBomEntry($bom_entry1);
|
||||
|
||||
$this->assertSame('∞', $this->service->getMaximumBuildableCountAsString($project));
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8735,7 +8735,7 @@ Element 1 -> Element 1.2</target>
|
|||
</notes>
|
||||
<segment state="translated">
|
||||
<source>log.type.security.backup_keys_reset</source>
|
||||
<target>Neue Backupkeys erzeugt</target>
|
||||
<target>Neue Backup-Keys erzeugt</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="RF1.KEr" name="log.type.security.google_enabled">
|
||||
|
|
@ -14219,5 +14219,66 @@ Bitte beachten Sie, dass Sie sich nicht als deaktivierter Benutzer ausgeben kön
|
|||
<target>Maximale Anzahl von Zuordnungen erreicht</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="LWLi016" name="settings.system">
|
||||
<segment state="translated">
|
||||
<source>settings.system</source>
|
||||
<target>System</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="8syOoyh" name="settings.behavior">
|
||||
<segment state="translated">
|
||||
<source>settings.behavior</source>
|
||||
<target>Verhalten</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="lAiL2Jw" name="settings.ips">
|
||||
<segment state="translated">
|
||||
<source>settings.ips</source>
|
||||
<target>Informationsquellen</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="GuUZqpX" name="settings.misc">
|
||||
<segment state="translated">
|
||||
<source>settings.misc</source>
|
||||
<target>Verschiedenes</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="mNLyYXa" name="settings.system.localization.language_menu_entries">
|
||||
<segment state="translated">
|
||||
<source>settings.system.localization.language_menu_entries</source>
|
||||
<target>Einträge des Sprachenmenüs</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="Ej2znKK" name="settings.system.localization.language_menu_entries.description">
|
||||
<segment state="translated">
|
||||
<source>settings.system.localization.language_menu_entries.description</source>
|
||||
<target>Die Sprachen, die im Sprachen Dropdown-Menü angezeigt werden sollen. Die Reihenfolge kann via Drag&Drop geändert werden. Lassen Sie das Feld leer, um alle verfügbaren Sprachen anzuzeigen.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="xIZ_mEX" name="project.builds.no_bom_entries">
|
||||
<segment state="translated">
|
||||
<source>project.builds.no_bom_entries</source>
|
||||
<target>Das Projekt hat keine BOM Einträge</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="pCKgjIr" name="settings.behavior.sidebar.data_structure_nodes_table_include_children">
|
||||
<segment state="translated">
|
||||
<source>settings.behavior.sidebar.data_structure_nodes_table_include_children</source>
|
||||
<target>Tabellen sollen Kindelemente standardmäßig inkludieren</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="KJQHfwV" name="settings.behavior.sidebar.data_structure_nodes_table_include_children.help">
|
||||
<segment state="translated">
|
||||
<source>settings.behavior.sidebar.data_structure_nodes_table_include_children.help</source>
|
||||
<target>Wenn ausgewählt, werden für Bauteiletabellen von Kategorien, Footprints, etc. alle Bauteile der Kindkategorie inkludiert. Wenn diese Option nicht ausgewählt ist, werden in den Bauteiletabellen nur die Bauteile angezeigt, die strikt zu der angeklickten Kategorie gehören (exklusive Kindelementen).</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="Gdlnmav" name="info_providers.search.error.oauth_reconnect">
|
||||
<segment state="translated">
|
||||
<source>info_providers.search.error.oauth_reconnect</source>
|
||||
<target>Folgende Informationsquelle benötigt eine OAuth Neu-Verbindung: %provider%
|
||||
Dies ist auf der Informationsquellen Übersichtsseite möglich.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
</file>
|
||||
</xliff>
|
||||
|
|
|
|||
|
|
@ -14220,5 +14220,91 @@ Please note, that you can not impersonate a disabled user. If you try you will g
|
|||
<target>Maximum number of mappings reached</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="LWLi016" name="settings.system">
|
||||
<segment state="translated">
|
||||
<source>settings.system</source>
|
||||
<target>System</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="8syOoyh" name="settings.behavior">
|
||||
<segment state="translated">
|
||||
<source>settings.behavior</source>
|
||||
<target>Behavior</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="lAiL2Jw" name="settings.ips">
|
||||
<segment state="translated">
|
||||
<source>settings.ips</source>
|
||||
<target>Info providers</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="GuUZqpX" name="settings.misc">
|
||||
<segment state="translated">
|
||||
<source>settings.misc</source>
|
||||
<target>Misc</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="mNLyYXa" name="settings.system.localization.language_menu_entries">
|
||||
<segment state="translated">
|
||||
<source>settings.system.localization.language_menu_entries</source>
|
||||
<target>Language menu entries</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="Ej2znKK" name="settings.system.localization.language_menu_entries.description">
|
||||
<segment state="translated">
|
||||
<source>settings.system.localization.language_menu_entries.description</source>
|
||||
<target><![CDATA[The languages to show in the language drop-down menu. Order can be changed via drag & drop. Leave empty to show all available languages.]]></target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="xIZ_mEX" name="project.builds.no_bom_entries">
|
||||
<segment>
|
||||
<source>project.builds.no_bom_entries</source>
|
||||
<target>Project has no BOM entries</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="pCKgjIr" name="settings.behavior.sidebar.data_structure_nodes_table_include_children">
|
||||
<segment>
|
||||
<source>settings.behavior.sidebar.data_structure_nodes_table_include_children</source>
|
||||
<target>Tables should include children nodes by default</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="KJQHfwV" name="settings.behavior.sidebar.data_structure_nodes_table_include_children.help">
|
||||
<segment>
|
||||
<source>settings.behavior.sidebar.data_structure_nodes_table_include_children.help</source>
|
||||
<target>If checked, the part tables for categories, footprints, etc. should include all parts of child categories. If not checked, only parts that strictly belong to the clicked node are shown.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="Gdlnmav" name="info_providers.search.error.oauth_reconnect">
|
||||
<segment>
|
||||
<source>info_providers.search.error.oauth_reconnect</source>
|
||||
<target>You need to reconnect OAuth for following providers: %provider%
|
||||
You can do this in the provider info list.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="xIZ_mEX" name="project.builds.no_bom_entries">
|
||||
<segment state="translated">
|
||||
<source>project.builds.no_bom_entries</source>
|
||||
<target>Project has no BOM entries</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="pCKgjIr" name="settings.behavior.sidebar.data_structure_nodes_table_include_children">
|
||||
<segment state="translated">
|
||||
<source>settings.behavior.sidebar.data_structure_nodes_table_include_children</source>
|
||||
<target>Tables should include children nodes by default</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="KJQHfwV" name="settings.behavior.sidebar.data_structure_nodes_table_include_children.help">
|
||||
<segment state="translated">
|
||||
<source>settings.behavior.sidebar.data_structure_nodes_table_include_children.help</source>
|
||||
<target>If checked, the part tables for categories, footprints, etc. should include all parts of child categories. If not checked, only parts that strictly belong to the clicked node are shown.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="Gdlnmav" name="info_providers.search.error.oauth_reconnect">
|
||||
<segment state="translated">
|
||||
<source>info_providers.search.error.oauth_reconnect</source>
|
||||
<target>You need to reconnect OAuth for following providers: %provider%
|
||||
You can do this in the provider info list.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
</file>
|
||||
</xliff>
|
||||
|
|
|
|||
14211
translations/messages.hu.xlf
Normal file
23
translations/security.hu.xlf
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<xliff xmlns="urn:oasis:names:tc:xliff:document:2.0" version="2.0" srcLang="en" trgLang="hu">
|
||||
<file id="security.en">
|
||||
<unit id="GrLNa9P" name="user.login_error.user_disabled">
|
||||
<segment state="translated">
|
||||
<source>user.login_error.user_disabled</source>
|
||||
<target>A fiókod le van tiltva! Lépj kapcsolatba egy adminisztrátorral, ha úgy gondolod, hogy ez hiba.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="IFQ5XrG" name="saml.error.cannot_login_local_user_per_saml">
|
||||
<segment state="translated">
|
||||
<source>saml.error.cannot_login_local_user_per_saml</source>
|
||||
<target>Nem tudsz helyi felhasználóként bejelentkezni SSO-n keresztül! Használd a helyi felhasználói jelszavad helyette.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="wOYPZmb" name="saml.error.cannot_login_saml_user_locally">
|
||||
<segment state="translated">
|
||||
<source>saml.error.cannot_login_saml_user_locally</source>
|
||||
<target>Nem tudsz helyi hitelesítéssel bejelentkezni SAML felhasználóként! Használd az SSO bejelentkezést helyette.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
</file>
|
||||
</xliff>
|
||||
|
|
@ -1,17 +1,23 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<xliff xmlns="urn:oasis:names:tc:xliff:document:2.0" version="2.0" srcLang="en" trgLang="pl">
|
||||
<file id="security.en">
|
||||
<unit id="aazoCks" name="user.login_error.user_disabled">
|
||||
<unit id="GrLNa9P" name="user.login_error.user_disabled">
|
||||
<segment state="translated">
|
||||
<source>user.login_error.user_disabled</source>
|
||||
<target>Twoje konto jest wyłączone! Skontaktuj się z administratorem, jeśli uważasz, że jest to niewłaściwe.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="Dpb9AmY" name="saml.error.cannot_login_local_user_per_saml">
|
||||
<unit id="IFQ5XrG" name="saml.error.cannot_login_local_user_per_saml">
|
||||
<segment state="translated">
|
||||
<source>saml.error.cannot_login_local_user_per_saml</source>
|
||||
<target>Nie możesz zalogować się jako użytkownik lokalny poprzez SSO! Zamiast tego użyj hasła użytkownika lokalnego.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="wOYPZmb" name="saml.error.cannot_login_saml_user_locally">
|
||||
<segment state="translated">
|
||||
<source>saml.error.cannot_login_saml_user_locally</source>
|
||||
<target>Nie można zalogować się lokalnie do tego użytkownika</target>
|
||||
</segment>
|
||||
</unit>
|
||||
</file>
|
||||
</xliff>
|
||||
|
|
|
|||
369
translations/validators.hu.xlf
Normal file
|
|
@ -0,0 +1,369 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<xliff xmlns="urn:oasis:names:tc:xliff:document:2.0" version="2.0" srcLang="en" trgLang="hu">
|
||||
<file id="validators.en">
|
||||
<unit id="cRbk.cm" name="part.master_attachment.must_be_picture">
|
||||
<notes>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Attachments\AttachmentContainingDBElement.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Attachments\AttachmentType.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Base\AbstractCompany.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Base\AbstractPartsContainingDBElement.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Base\AbstractStructuralDBElement.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Devices\Device.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\LabelSystem\LabelProfile.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Parts\Category.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Parts\Footprint.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Parts\Manufacturer.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Parts\MeasurementUnit.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Parts\Part.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Parts\Part.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Parts\Storelocation.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Parts\Supplier.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\PriceInformations\Currency.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\UserSystem\Group.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\UserSystem\User.php:0</note>
|
||||
<note priority="1">Part-DB1\src\Entity\Attachments\AttachmentType.php:0</note>
|
||||
<note priority="1">Part-DB1\src\Entity\Base\AbstractCompany.php:0</note>
|
||||
<note priority="1">Part-DB1\src\Entity\Base\AbstractPartsContainingDBElement.php:0</note>
|
||||
<note priority="1">Part-DB1\src\Entity\Base\AbstractStructuralDBElement.php:0</note>
|
||||
<note priority="1">Part-DB1\src\Entity\Devices\Device.php:0</note>
|
||||
<note priority="1">Part-DB1\src\Entity\Parts\Category.php:0</note>
|
||||
<note priority="1">Part-DB1\src\Entity\Parts\Footprint.php:0</note>
|
||||
<note priority="1">Part-DB1\src\Entity\Parts\Manufacturer.php:0</note>
|
||||
<note priority="1">Part-DB1\src\Entity\Parts\MeasurementUnit.php:0</note>
|
||||
<note priority="1">Part-DB1\src\Entity\Parts\Part.php:0</note>
|
||||
<note priority="1">Part-DB1\src\Entity\Parts\Storelocation.php:0</note>
|
||||
<note priority="1">Part-DB1\src\Entity\Parts\Supplier.php:0</note>
|
||||
<note priority="1">Part-DB1\src\Entity\PriceInformations\Currency.php:0</note>
|
||||
<note priority="1">Part-DB1\src\Entity\UserSystem\Group.php:0</note>
|
||||
<note priority="1">Part-DB1\src\Entity\UserSystem\User.php:0</note>
|
||||
</notes>
|
||||
<segment state="translated">
|
||||
<source>part.master_attachment.must_be_picture</source>
|
||||
<target>Az előnézeti mellékletnek érvényes képnek kell lennie!</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="v8HkcJB" name="structural.entity.unique_name">
|
||||
<notes>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Attachments\AttachmentType.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Base\AbstractCompany.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Base\AbstractPartsContainingDBElement.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Base\AbstractStructuralDBElement.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Devices\Device.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Parts\Category.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Parts\Footprint.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Parts\Manufacturer.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Parts\MeasurementUnit.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Parts\Storelocation.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Parts\Supplier.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\PriceInformations\Currency.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\UserSystem\Group.php:0</note>
|
||||
<note priority="1">Part-DB1\src\Entity\Attachments\AttachmentType.php:0</note>
|
||||
<note priority="1">Part-DB1\src\Entity\Base\AbstractCompany.php:0</note>
|
||||
<note priority="1">Part-DB1\src\Entity\Base\AbstractPartsContainingDBElement.php:0</note>
|
||||
<note priority="1">Part-DB1\src\Entity\Base\AbstractStructuralDBElement.php:0</note>
|
||||
<note priority="1">Part-DB1\src\Entity\Devices\Device.php:0</note>
|
||||
<note priority="1">Part-DB1\src\Entity\Parts\Category.php:0</note>
|
||||
<note priority="1">Part-DB1\src\Entity\Parts\Footprint.php:0</note>
|
||||
<note priority="1">Part-DB1\src\Entity\Parts\Manufacturer.php:0</note>
|
||||
<note priority="1">Part-DB1\src\Entity\Parts\MeasurementUnit.php:0</note>
|
||||
<note priority="1">Part-DB1\src\Entity\Parts\Storelocation.php:0</note>
|
||||
<note priority="1">Part-DB1\src\Entity\Parts\Supplier.php:0</note>
|
||||
<note priority="1">Part-DB1\src\Entity\PriceInformations\Currency.php:0</note>
|
||||
<note priority="1">Part-DB1\src\Entity\UserSystem\Group.php:0</note>
|
||||
<note priority="1">src\Entity\AttachmentType.php:0</note>
|
||||
<note priority="1">src\Entity\Category.php:0</note>
|
||||
<note priority="1">src\Entity\Company.php:0</note>
|
||||
<note priority="1">src\Entity\Device.php:0</note>
|
||||
<note priority="1">src\Entity\Footprint.php:0</note>
|
||||
<note priority="1">src\Entity\Group.php:0</note>
|
||||
<note priority="1">src\Entity\Manufacturer.php:0</note>
|
||||
<note priority="1">src\Entity\PartsContainingDBElement.php:0</note>
|
||||
<note priority="1">src\Entity\Storelocation.php:0</note>
|
||||
<note priority="1">src\Entity\StructuralDBElement.php:0</note>
|
||||
<note priority="1">src\Entity\Supplier.php:0</note>
|
||||
</notes>
|
||||
<segment state="translated">
|
||||
<source>structural.entity.unique_name</source>
|
||||
<target>Egy elem ezzel a névvel már létezik ezen a szinten!</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="dW7b2B_" name="parameters.validator.min_lesser_typical">
|
||||
<notes>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Parameters\AbstractParameter.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Parameters\AttachmentTypeParameter.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Parameters\CategoryParameter.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Parameters\CurrencyParameter.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Parameters\DeviceParameter.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Parameters\FootprintParameter.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Parameters\GroupParameter.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Parameters\ManufacturerParameter.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Parameters\MeasurementUnitParameter.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Parameters\PartParameter.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Parameters\StorelocationParameter.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Parameters\SupplierParameter.php:0</note>
|
||||
</notes>
|
||||
<segment state="translated">
|
||||
<source>parameters.validator.min_lesser_typical</source>
|
||||
<target>Az értéknek kisebbnek vagy egyenlőnek kell lennie a tipikus értékkel ({{ compared_value }}).</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="Yfp2uC5" name="parameters.validator.min_lesser_max">
|
||||
<notes>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Parameters\AbstractParameter.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Parameters\AttachmentTypeParameter.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Parameters\CategoryParameter.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Parameters\CurrencyParameter.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Parameters\DeviceParameter.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Parameters\FootprintParameter.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Parameters\GroupParameter.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Parameters\ManufacturerParameter.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Parameters\MeasurementUnitParameter.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Parameters\PartParameter.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Parameters\StorelocationParameter.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Parameters\SupplierParameter.php:0</note>
|
||||
</notes>
|
||||
<segment state="translated">
|
||||
<source>parameters.validator.min_lesser_max</source>
|
||||
<target>Az értéknek kisebbnek kell lennie a maximális értéknél ({{ compared_value }}).</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="P6b.8Ou" name="parameters.validator.max_greater_typical">
|
||||
<notes>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Parameters\AbstractParameter.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Parameters\AttachmentTypeParameter.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Parameters\CategoryParameter.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Parameters\CurrencyParameter.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Parameters\DeviceParameter.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Parameters\FootprintParameter.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Parameters\GroupParameter.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Parameters\ManufacturerParameter.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Parameters\MeasurementUnitParameter.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Parameters\PartParameter.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Parameters\StorelocationParameter.php:0</note>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\Parameters\SupplierParameter.php:0</note>
|
||||
</notes>
|
||||
<segment state="translated">
|
||||
<source>parameters.validator.max_greater_typical</source>
|
||||
<target>Az értéknek nagyobbnak vagy egyenlőnek kell lennie a tipikus értéknél ({{ compared_value }}).</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="P41193Y" name="validator.user.username_already_used">
|
||||
<notes>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\UserSystem\User.php:0</note>
|
||||
<note priority="1">Part-DB1\src\Entity\UserSystem\User.php:0</note>
|
||||
</notes>
|
||||
<segment state="translated">
|
||||
<source>validator.user.username_already_used</source>
|
||||
<target>Egy felhasználó ezzel a névvel már létezik</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="EKPQiyf" name="user.invalid_username">
|
||||
<notes>
|
||||
<note category="file-source" priority="1">Part-DB1\src\Entity\UserSystem\User.php:0</note>
|
||||
<note priority="1">Part-DB1\src\Entity\UserSystem\User.php:0</note>
|
||||
</notes>
|
||||
<segment state="translated">
|
||||
<source>user.invalid_username</source>
|
||||
<target>A felhasználónév csak betűket, számokat, aláhúzásokat, pontokat, pluszokat vagy mínuszokat tartalmazhat és nem kezdődhet @ jellel!</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="_v.DMg." name="validator.noneofitschild.self">
|
||||
<notes>
|
||||
<note category="state" priority="1">obsolete</note>
|
||||
</notes>
|
||||
<segment state="translated">
|
||||
<source>validator.noneofitschild.self</source>
|
||||
<target>Egy elem nem lehet a saját szülője!</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="W90LyFQ" name="validator.noneofitschild.children">
|
||||
<notes>
|
||||
<note category="state" priority="1">obsolete</note>
|
||||
</notes>
|
||||
<segment state="translated">
|
||||
<source>validator.noneofitschild.children</source>
|
||||
<target>Nem rendelhetsz gyerek elemet szülőnek (ez hurkokat okozna)!</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="GAUS.LK" name="validator.select_valid_category">
|
||||
<segment state="translated">
|
||||
<source>validator.select_valid_category</source>
|
||||
<target>Kérjük válassz egy érvényes kategóriát!</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="h6qELde" name="validator.part_lot.only_existing">
|
||||
<segment state="translated">
|
||||
<source>validator.part_lot.only_existing</source>
|
||||
<target>Nem lehet új alkatrészeket hozzáadni ehhez a helyhez, mivel "Csak Meglévő" jelölésű</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="Prriyy0" name="validator.part_lot.location_full.no_increase">
|
||||
<segment state="translated">
|
||||
<source>validator.part_lot.location_full.no_increase</source>
|
||||
<target>A hely tele van. A mennyiség nem növelhető (az új értéknek kisebbnek kell lennie, mint {{ old_amount }}).</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="eeEjB4s" name="validator.part_lot.location_full">
|
||||
<segment state="translated">
|
||||
<source>validator.part_lot.location_full</source>
|
||||
<target>A hely tele van. Nem lehet új alkatrészeket hozzáadni.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="2yWi8eP" name="validator.part_lot.single_part">
|
||||
<segment state="translated">
|
||||
<source>validator.part_lot.single_part</source>
|
||||
<target>Ez a hely csak egyetlen alkatrészt tartalmazhat és már tele van!</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="A.TFhbb" name="validator.attachment.must_not_be_null">
|
||||
<segment state="translated">
|
||||
<source>validator.attachment.must_not_be_null</source>
|
||||
<target>Ki kell választanod egy melléklet típust!</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id=".lqKoij" name="validator.orderdetail.supplier_must_not_be_null">
|
||||
<segment state="translated">
|
||||
<source>validator.orderdetail.supplier_must_not_be_null</source>
|
||||
<target>Ki kell választanod egy beszállítót!</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="bcNZzK." name="validator.measurement_unit.use_si_prefix_needs_unit">
|
||||
<segment state="translated">
|
||||
<source>validator.measurement_unit.use_si_prefix_needs_unit</source>
|
||||
<target>Az SI előtagok engedélyezéséhez be kell állítanod egy egység szimbólumot!</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="gZ5FFL1" name="part.ipn.must_be_unique">
|
||||
<segment state="translated">
|
||||
<source>part.ipn.must_be_unique</source>
|
||||
<target>A belső alkatrész számnak egyedinek kell lennie. {{ value }} már használatban van!</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="P31Yg.d" name="validator.project.bom_entry.name_or_part_needed">
|
||||
<segment state="translated">
|
||||
<source>validator.project.bom_entry.name_or_part_needed</source>
|
||||
<target>Ki kell választanod egy alkatrészt az alkatrész BOM bejegyzéshez vagy be kell állítanod egy nevet a nem-alkatrész BOM bejegyzéshez.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="5CEup_N" name="project.bom_entry.name_already_in_bom">
|
||||
<segment state="translated">
|
||||
<source>project.bom_entry.name_already_in_bom</source>
|
||||
<target>Már létezik egy BOM bejegyzés ezzel a névvel!</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="jB3B50E" name="project.bom_entry.part_already_in_bom">
|
||||
<segment state="translated">
|
||||
<source>project.bom_entry.part_already_in_bom</source>
|
||||
<target>Ez az alkatrész már létezik a BOM-ban!</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="NdkzP1n" name="project.bom_entry.mountnames_quantity_mismatch">
|
||||
<segment state="translated">
|
||||
<source>project.bom_entry.mountnames_quantity_mismatch</source>
|
||||
<target>A szerelési nevek számának meg kell egyeznie a BOM mennyiségével!</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="8teRCgR" name="project.bom_entry.can_not_add_own_builds_part">
|
||||
<segment state="translated">
|
||||
<source>project.bom_entry.can_not_add_own_builds_part</source>
|
||||
<target>Nem adhatsz hozzá egy projekt saját építési alkatrészét a BOM-hoz.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="asBxPxe" name="project.bom_has_to_include_all_subelement_parts">
|
||||
<segment state="translated">
|
||||
<source>project.bom_has_to_include_all_subelement_parts</source>
|
||||
<target>A projekt BOM-nak tartalmaznia kell az összes alprojekt építési alkatrészét. A %part_name% alkatrész a %project_name% projektből hiányzik!</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="uxaE9Ct" name="project.bom_entry.price_not_allowed_on_parts">
|
||||
<segment state="translated">
|
||||
<source>project.bom_entry.price_not_allowed_on_parts</source>
|
||||
<target>Az árak nem engedélyezettek a BOM bejegyzésekben, amelyek egy alkatrészhez kapcsolódnak. Határozd meg az árat az alkatrészen helyette.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="xZ68Nzl" name="validator.project_build.lot_bigger_than_needed">
|
||||
<segment state="translated">
|
||||
<source>validator.project_build.lot_bigger_than_needed</source>
|
||||
<target>Több mennyiséget választottál ki kivonásra, mint amennyire szükség van! Távolítsd el a szükségtelen mennyiséget.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="68_.V_X" name="validator.project_build.lot_smaller_than_needed">
|
||||
<segment state="translated">
|
||||
<source>validator.project_build.lot_smaller_than_needed</source>
|
||||
<target>Kevesebb mennyiséget választottál ki kivonásra, mint amennyire szükség van az építéshez! Adj hozzá további mennyiséget.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="yZGS8uZ" name="part.name.must_match_category_regex">
|
||||
<segment state="translated">
|
||||
<source>part.name.must_match_category_regex</source>
|
||||
<target>Az alkatrész név nem egyezik a kategória által megadott reguláris kifejezéssel: %regex%</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="Q8wP5Jd" name="validator.attachment.name_not_blank">
|
||||
<segment state="translated">
|
||||
<source>validator.attachment.name_not_blank</source>
|
||||
<target>Állíts be egy értéket itt, vagy tölts fel egy fájlt, hogy automatikusan használja a fájlnevet a melléklet neveként.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="DH0IkNR" name="validator.part_lot.owner_must_match_storage_location_owner">
|
||||
<segment state="translated">
|
||||
<source>validator.part_lot.owner_must_match_storage_location_owner</source>
|
||||
<target>Ennek a tételnek a tulajdonosának meg kell egyeznie a kiválasztott tárolási hely tulajdonosával (%owner_name%)!</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="TzySicw" name="validator.part_lot.owner_must_not_be_anonymous">
|
||||
<segment state="translated">
|
||||
<source>validator.part_lot.owner_must_not_be_anonymous</source>
|
||||
<target>A tétel tulajdonosa nem lehet az anonim felhasználó!</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="GthNWUb" name="validator.part_association.must_set_an_value_if_type_is_other">
|
||||
<segment state="translated">
|
||||
<source>validator.part_association.must_set_an_value_if_type_is_other</source>
|
||||
<target>Ha a típust "egyéb"-re állítod, akkor be kell állítanod egy leíró értéket hozzá!</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="Be4Im81" name="validator.part_association.part_cannot_be_associated_with_itself">
|
||||
<segment state="translated">
|
||||
<source>validator.part_association.part_cannot_be_associated_with_itself</source>
|
||||
<target>Egy alkatrész nem társítható önmagával!</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="q5Ej6Xm" name="validator.part_association.already_exists">
|
||||
<segment state="translated">
|
||||
<source>validator.part_association.already_exists</source>
|
||||
<target>A társítás ezzel az alkatrésszel már létezik!</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="HbI5bga" name="validator.part_lot.vendor_barcode_must_be_unique">
|
||||
<segment state="translated">
|
||||
<source>validator.part_lot.vendor_barcode_must_be_unique</source>
|
||||
<target>Ez a beszállítói vonalkód érték már használatban volt egy másik tételben. A vonalkódnak egyedinek kell lennie!</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="ufQJh7E" name="validator.year_2038_bug_on_32bit">
|
||||
<segment state="translated">
|
||||
<source>validator.year_2038_bug_on_32bit</source>
|
||||
<target>Technikai korlátok miatt nem lehet dátumokat kiválasztani 2038-01-19 után 32 bites rendszereken!</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="89nojXY" name="validator.fileSize.invalidFormat">
|
||||
<segment state="translated">
|
||||
<source>validator.fileSize.invalidFormat</source>
|
||||
<target>Érvénytelen fájlméret formátum. Használj egész számot plusz K, M, G utótagot Kilo, Mega vagy Gigabyte-okhoz.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="iXcU7ce" name="validator.invalid_range">
|
||||
<segment state="translated">
|
||||
<source>validator.invalid_range</source>
|
||||
<target>A megadott tartomány nem érvényes!</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="m4gp2P_" name="validator.google_code.wrong_code">
|
||||
<segment state="translated">
|
||||
<source>validator.google_code.wrong_code</source>
|
||||
<target>Érvénytelen kód. Ellenőrizd, hogy az autentikátor alkalmazásod megfelelően van beállítva és hogy mind a szerver, mind az autentikációs eszköz időzítése helyes.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
</file>
|
||||
</xliff>
|
||||