Implemented a new darkmode selector using bootstrap 5.3 color mode

This commit is contained in:
Jan Böhmer 2023-06-19 01:08:11 +02:00
parent 0aec9419ec
commit 6df65a0b9d
15 changed files with 1465 additions and 1412 deletions

View file

@ -18,43 +18,118 @@
*/ */
import {Controller} from "@hotwired/stimulus"; import {Controller} from "@hotwired/stimulus";
import Darkmode from "darkmode-js/src";
import "darkmode-js"
export default class extends Controller { export default class extends Controller {
_darkmode;
connect() { connect() {
if (typeof window.getComputedStyle(document.body).mixBlendMode == 'undefined') { this.setMode(this.getMode());
console.warn("The browser does not support mix blend mode. Darkmode will not work."); document.querySelectorAll('input[name="darkmode"]').forEach((radio) => {
radio.addEventListener('change', this._radioChanged.bind(this));
});
}
/**
* Event listener for the change of radio buttons
* @private
*/
_radioChanged(event) {
const new_mode = this.getSelectedMode();
this.setMode(new_mode);
}
/**
* Get the current mode from the local storage
* @return {'dark', 'light', 'auto'}
*/
getMode() {
return localStorage.getItem('darkmode') ?? 'auto';
}
/**
* Set the mode in the local storage and apply it and change the state of the radio buttons
* @param mode
*/
setMode(mode) {
if (mode !== 'dark' && mode !== 'light' && mode !== 'auto') {
console.warn('Invalid darkmode mode: ' + mode);
mode = 'auto';
}
localStorage.setItem('darkmode', mode);
this.setButtonMode(mode);
if (mode === 'auto') {
this._setDarkmodeAuto();
} else if (mode === 'dark') {
this._enableDarkmode();
} else if (mode === 'light') {
this._disableDarkmode();
}
}
/**
* Get the selected mode via the radio buttons
* @return {'dark', 'light', 'auto'}
*/
getSelectedMode() {
return document.querySelector('input[name="darkmode"]:checked').value;
}
/**
* Set the state of the radio buttons
* @param mode
*/
setButtonMode(mode) {
document.querySelector('input[name="darkmode"][value="' + mode + '"]').checked = true;
}
/**
* Enable darkmode by adding the data-bs-theme="dark" to the html tag
* @private
*/
_enableDarkmode() {
//Add data-bs-theme="dark" to the html tag
document.documentElement.setAttribute('data-bs-theme', 'dark');
}
/**
* Disable darkmode by adding the data-bs-theme="light" to the html tag
* @private
*/
_disableDarkmode() {
//Set data-bs-theme to light
document.documentElement.setAttribute('data-bs-theme', 'light');
}
/**
* Set the darkmode to auto and enable/disable it depending on the system settings, also add
* an event listener to change the darkmode if the system settings change
* @private
*/
_setDarkmodeAuto() {
if (this.getMode() !== 'auto') {
return; return;
} }
try { if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
const darkmode = new Darkmode(); this._enableDarkmode();
this._darkmode = darkmode; } else {
this._disableDarkmode();
//Unhide darkmode button
this._showWidget();
//Set the switch according to our current darkmode state
const toggler = document.getElementById("toggleDarkmode");
toggler.checked = darkmode.isActivated();
}
catch (e)
{
console.error(e);
} }
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => {
console.log('Prefered color scheme changed to ' + event.matches ? 'dark' : 'light');
this._setDarkmodeAuto();
});
} }
_showWidget() { /**
this.element.classList.remove('hidden'); * Check if darkmode is activated
} * @return {boolean}
*/
toggleDarkmode() { isDarkmodeActivated() {
this._darkmode.toggle(); return document.documentElement.getAttribute('data-bs-theme') === 'dark';
} }
} }

View file

@ -1,37 +0,0 @@
/*
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
*
* Copyright (C) 2019 - 2022 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/>.
*/
.darkmode-layer {
z-index: 2020;
}
/** If darkmode is enabled revert the blening for images and videos, as these should be shown not inverted */
.darkmode--activated img,
.darkmode--activated video,
.darkmode--activated object {
mix-blend-mode: difference;
}
.darkmode--activated .hoverpic:hover {
background: black;
}
.tools-ic-logos img {
mix-blend-mode: normal;
}

View file

@ -22,7 +22,6 @@
import '../css/app/layout.css'; import '../css/app/layout.css';
import '../css/app/helpers.css'; import '../css/app/helpers.css';
import '../css/app/darkmode.css';
import '../css/app/tables.css'; import '../css/app/tables.css';
import '../css/app/bs-overrides.css'; import '../css/app/bs-overrides.css';
import '../css/app/treeview.css'; import '../css/app/treeview.css';

View file

@ -62,7 +62,7 @@ class RegisterEventHelper {
this.registerLoadHandler(() => { this.registerLoadHandler(() => {
$(".tooltip").remove(); $(".tooltip").remove();
//Exclude dropdown buttons from tooltips, otherwise we run into endless errors from bootstrap (bootstrap.esm.js:614 Bootstrap doesn't allow more than one instance per element. Bound instance: bs.dropdown.) //Exclude dropdown buttons from tooltips, otherwise we run into endless errors from bootstrap (bootstrap.esm.js:614 Bootstrap doesn't allow more than one instance per element. Bound instance: bs.dropdown.)
$('a[title], button[title]:not([data-bs-toggle="dropdown"]), p[title], span[title], h6[title], h3[title], i.fas[title]') $('a[title], label[title], button[title]:not([data-bs-toggle="dropdown"]), p[title], span[title], h6[title], h3[title], i.fas[title]')
//@ts-ignore //@ts-ignore
.tooltip("hide").tooltip({container: "body", placement: "auto", boundary: 'window'}); .tooltip("hide").tooltip({container: "body", placement: "auto", boundary: 'window'});
}); });

View file

@ -66,7 +66,6 @@
"bs-custom-file-input": "^1.3.4", "bs-custom-file-input": "^1.3.4",
"clipboard": "^2.0.4", "clipboard": "^2.0.4",
"compression-webpack-plugin": "^10.0.0", "compression-webpack-plugin": "^10.0.0",
"darkmode-js": "^1.5.0",
"datatables.net-bs5": "^1.10.20", "datatables.net-bs5": "^1.10.20",
"datatables.net-buttons-bs5": "^2.2.2", "datatables.net-buttons-bs5": "^2.2.2",
"datatables.net-colreorder-bs5": "^1.5.1", "datatables.net-colreorder-bs5": "^1.5.1",

View file

@ -1,6 +1,6 @@
{% import "helper.twig" as helper %} {% import "helper.twig" as helper %}
<nav class="navbar navbar-expand-md navbar-light bg-light border-bottom shadow-sm fixed-top py-0" id="navbar"> <nav class="navbar navbar-expand-md bg-body-tertiary border-bottom shadow-sm fixed-top py-0" id="navbar">
<div class="container-fluid"> <div class="container-fluid">
<button type="button" class="navbar-toggler" data-bs-toggle="collapse" data-bs-target="#sidebar-container"> <button type="button" class="navbar-toggler" data-bs-toggle="collapse" data-bs-target="#sidebar-container">
<span class="visually-hidden">{% trans %}sidebar.toggle{% endtrans %}</span> <span class="visually-hidden">{% trans %}sidebar.toggle{% endtrans %}</span>
@ -61,11 +61,15 @@
aria-hidden="true"></i> {% trans %}user.login{% endtrans %}</a> aria-hidden="true"></i> {% trans %}user.login{% endtrans %}</a>
{% endif %} {% endif %}
<li role="separator" class="dropdown-divider" id="toggleDarkmodeSeparator"></li> <li role="separator" class="dropdown-divider" id="toggleDarkmodeSeparator"></li>
<div class="px-4 px-3" id="toggleDarkmodeContainer hidden" {{ stimulus_controller('common/darkmode') }}> <div class="px-4 py-0 d-flex justify-content-between align-items-baseline">
<div class="form-check form-switch"> <span>{% trans %}ui.toggle_darkmode{% endtrans %}</span>
<input type="checkbox" class="form-check-input" id="toggleDarkmode" {{ stimulus_action('common/darkmode', 'toggleDarkmode', 'change') }}> <div class="btn-group" role="group" {{ stimulus_controller('common/darkmode') }}>
<label class="form-check-label" <input type="radio" class="btn-check" name="darkmode" id="darkmode-light" autocomplete="off" value="light">
for="toggleDarkmode">{% trans %}ui.toggle_darkmode{% endtrans %}</label> <label class="btn btn-outline-secondary" for="darkmode-light" title="{% trans %}ui.darkmode.light{% endtrans %}"><i class="fa-solid fa-sun"></i></label>
<input type="radio" class="btn-check" name="darkmode" id="darkmode-dark" autocomplete="off" value="dark">
<label class="btn btn-outline-secondary" for="darkmode-dark" title="{% trans %}ui.darkmode.dark{% endtrans %}"><i class="fa-solid fa-moon"></i></label>
<input type="radio" class="btn-check" name="darkmode" id="darkmode-auto" autocomplete="off" value="auto" checked>
<label class="btn btn-outline-secondary" for="darkmode-auto" title="{% trans %}ui.darkmode.auto{% endtrans %}"><i class="fa-solid fa-circle-half-stroke"></i></label>
</div> </div>
</div> </div>
<li role="separator" class="dropdown-divider"></li> <li role="separator" class="dropdown-divider"></li>

View file

@ -34,7 +34,7 @@
<ul class="dropdown-menu" aria-labelledby="dropdownCat"> <ul class="dropdown-menu" aria-labelledby="dropdownCat">
{{ _self.sidebar_dropdown('tree-categories') }} {{ _self.sidebar_dropdown('tree-categories') }}
</ul> </ul>
<input type="search" class="form-control bg-light border-0" placeholder="{% trans %}search.placeholder{% endtrans %}" {{ stimulus_action('elements/sidebar_tree', 'searchInput') }}> <input type="search" class="form-control bg-body-tertiary border-0" placeholder="{% trans %}search.placeholder{% endtrans %}" {{ stimulus_action('elements/sidebar_tree', 'searchInput') }}>
</div> </div>
<div id="{{ id }}Tree" {{ stimulus_target('elements/sidebar_tree', 'tree') }}></div> <div id="{{ id }}Tree" {{ stimulus_target('elements/sidebar_tree', 'tree') }}></div>

View file

@ -1,7 +1,7 @@
{% extends "base.html.twig" %} {% extends "base.html.twig" %}
{% block content %} {% block content %}
<div class="rounded p-4" style="background-color: var(--bs-gray-300);"> <div class="rounded p-4 bg-body-secondary">
<h1 class="display-3">{{ partdb_title }}</h1> <h1 class="display-3">{{ partdb_title }}</h1>
<h4> <h4>
{% trans %}version.caption{% endtrans %}: {{ shivas_app_version }} {% trans %}version.caption{% endtrans %}: {{ shivas_app_version }}

View file

@ -42,7 +42,7 @@
<td> <td>
<h6> <h6>
{% if lot.owner %} {% if lot.owner %}
<span class="badge bg-light mb-1" title="{% trans %}part_lot.owner{% endtrans %}"> <span class="badge bg-body-tertiary mb-1" title="{% trans %}part_lot.owner{% endtrans %}">
{{ helper.user_icon_link(lot.owner) }} {{ helper.user_icon_link(lot.owner) }}
</span><br> </span><br>
{% endif %} {% endif %}

View file

@ -12,10 +12,10 @@
{# @var pic App\Entity\Attachments\Attachment #} {# @var pic App\Entity\Attachments\Attachment #}
<div class="carousel-item {% if loop.first %}active{% endif %}"> <div class="carousel-item {% if loop.first %}active{% endif %}">
<a href="{{ entity_url(pic, 'file_view') }}" data-turbo="false" target="_blank" rel="noopener"> <a href="{{ entity_url(pic, 'file_view') }}" data-turbo="false" target="_blank" rel="noopener">
<img class="d-block w-100 img-fluid img-thumbnail bg-light part-info-image" src="{{ entity_url(pic, 'file_view') }}" alt=""> <img class="d-block w-100 img-fluid img-thumbnail bg-body-tertiary part-info-image" src="{{ entity_url(pic, 'file_view') }}" alt="">
<div class="mask"></div> <div class="mask"></div>
<div class="carousel-caption-hover"> <div class="carousel-caption-hover">
<div class="carousel-caption"> <div class="carousel-caption text-body ">
<div><b>{{ pic.name }}</b></div> <div><b>{{ pic.name }}</b></div>
<div>{% if pic.filename %}({{ pic.filename }}) {% endif %}</div> <div>{% if pic.filename %}({{ pic.filename }}) {% endif %}</div>
<div>{{ entity_type_label(pic.element) }}</div> <div>{{ entity_type_label(pic.element) }}</div>
@ -38,5 +38,5 @@
</div> </div>
{% else %} {% else %}
<img src="{{ asset('img/part_placeholder.svg') }}" class="img-fluid img-thumbnail bg-light mb-2" alt="Part main image" height="300" width="300"> <img src="{{ asset('img/part_placeholder.svg') }}" class="img-fluid img-thumbnail bg-body-tertiary mb-2" alt="Part main image" height="300" width="300">
{% endif %} {% endif %}

View file

@ -6,10 +6,10 @@
<div class="col-md-3 col-lg-4 col-4 mt-auto mb-auto"> <div class="col-md-3 col-lg-4 col-4 mt-auto mb-auto">
{% if project.masterPictureAttachment %} {% if project.masterPictureAttachment %}
<a href="{{ entity_url(project.masterPictureAttachment, 'file_view') }}" data-turbo="false" target="_blank" rel="noopener"> <a href="{{ entity_url(project.masterPictureAttachment, 'file_view') }}" data-turbo="false" target="_blank" rel="noopener">
<img class="d-block w-100 img-fluid img-thumbnail bg-light part-info-image" src="{{ entity_url(project.masterPictureAttachment, 'file_view') }}" alt=""> <img class="d-block w-100 img-fluid img-thumbnail bg-body-tertiary part-info-image" src="{{ entity_url(project.masterPictureAttachment, 'file_view') }}" alt="">
</a> </a>
{% else %} {% else %}
<img src="{{ asset('img/part_placeholder.svg') }}" class="img-fluid img-thumbnail bg-light mb-2 " alt="Part main image" height="300" width="300"> <img src="{{ asset('img/part_placeholder.svg') }}" class="img-fluid img-thumbnail bg-body-tertiary mb-2 " alt="Part main image" height="300" width="300">
{% endif %} {% endif %}
</div> </div>
<div class="col-md-9 col-lg-8 col-7"> <div class="col-md-9 col-lg-8 col-7">

File diff suppressed because it is too large Load diff

View file

@ -1,14 +1,14 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:2.0" version="2.0" srcLang="en" trgLang="de"> <xliff xmlns="urn:oasis:names:tc:xliff:document:2.0" version="2.0" srcLang="en" trgLang="de">
<file id="security.en"> <file id="security.de">
<unit id="aazoCks" name="user.login_error.user_disabled"> <unit id="aazoCks" name="user.login_error.user_disabled">
<segment state="translated"> <segment>
<source>user.login_error.user_disabled</source> <source>user.login_error.user_disabled</source>
<target>Ihr Account ist deaktiviert! Kontaktiere einen Administrator, wenn Sie denken, dass dies ein Fehler ist.</target> <target>Ihr Account ist deaktiviert! Kontaktiere einen Administrator, wenn Sie denken, dass dies ein Fehler ist.</target>
</segment> </segment>
</unit> </unit>
<unit id="Dpb9AmY" name="saml.error.cannot_login_local_user_per_saml"> <unit id="Dpb9AmY" name="saml.error.cannot_login_local_user_per_saml">
<segment state="translated"> <segment>
<source>saml.error.cannot_login_local_user_per_saml</source> <source>saml.error.cannot_login_local_user_per_saml</source>
<target>Sie können sich per SSO nicht als lokaler Nutzer einloggen! Nutzen Sie stattdessen ihr lokales Passwort.</target> <target>Sie können sich per SSO nicht als lokaler Nutzer einloggen! Nutzen Sie stattdessen ihr lokales Passwort.</target>
</segment> </segment>

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:2.0" version="2.0" srcLang="en" trgLang="de"> <xliff xmlns="urn:oasis:names:tc:xliff:document:2.0" version="2.0" srcLang="en" trgLang="de">
<file id="validators.en"> <file id="validators.de">
<unit id="xevSdCK" name="part.master_attachment.must_be_picture"> <unit id="xevSdCK" name="part.master_attachment.must_be_picture">
<notes> <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\AttachmentContainingDBElement.php:0</note>
@ -37,7 +37,7 @@
<note priority="1">Part-DB1\src\Entity\UserSystem\Group.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> <note priority="1">Part-DB1\src\Entity\UserSystem\User.php:0</note>
</notes> </notes>
<segment state="translated"> <segment>
<source>part.master_attachment.must_be_picture</source> <source>part.master_attachment.must_be_picture</source>
<target>Der Vorschauanhang muss ein gültiges Bild sein!</target> <target>Der Vorschauanhang muss ein gültiges Bild sein!</target>
</segment> </segment>
@ -82,7 +82,7 @@
<note priority="1">src\Entity\StructuralDBElement.php:0</note> <note priority="1">src\Entity\StructuralDBElement.php:0</note>
<note priority="1">src\Entity\Supplier.php:0</note> <note priority="1">src\Entity\Supplier.php:0</note>
</notes> </notes>
<segment state="translated"> <segment>
<source>structural.entity.unique_name</source> <source>structural.entity.unique_name</source>
<target>Es kann auf jeder Ebene nur ein Objekt mit dem gleichem Namen geben!</target> <target>Es kann auf jeder Ebene nur ein Objekt mit dem gleichem Namen geben!</target>
</segment> </segment>
@ -102,7 +102,7 @@
<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\StorelocationParameter.php:0</note>
<note category="file-source" priority="1">Part-DB1\src\Entity\Parameters\SupplierParameter.php:0</note> <note category="file-source" priority="1">Part-DB1\src\Entity\Parameters\SupplierParameter.php:0</note>
</notes> </notes>
<segment state="translated"> <segment>
<source>parameters.validator.min_lesser_typical</source> <source>parameters.validator.min_lesser_typical</source>
<target>Wert muss kleiner oder gleich als der typische Wert sein ({{ compared_value }}).</target> <target>Wert muss kleiner oder gleich als der typische Wert sein ({{ compared_value }}).</target>
</segment> </segment>
@ -122,7 +122,7 @@
<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\StorelocationParameter.php:0</note>
<note category="file-source" priority="1">Part-DB1\src\Entity\Parameters\SupplierParameter.php:0</note> <note category="file-source" priority="1">Part-DB1\src\Entity\Parameters\SupplierParameter.php:0</note>
</notes> </notes>
<segment state="translated"> <segment>
<source>parameters.validator.min_lesser_max</source> <source>parameters.validator.min_lesser_max</source>
<target>Wert muss kleiner als der Maximalwert sein ({{ compared_value }}).</target> <target>Wert muss kleiner als der Maximalwert sein ({{ compared_value }}).</target>
</segment> </segment>
@ -142,7 +142,7 @@
<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\StorelocationParameter.php:0</note>
<note category="file-source" priority="1">Part-DB1\src\Entity\Parameters\SupplierParameter.php:0</note> <note category="file-source" priority="1">Part-DB1\src\Entity\Parameters\SupplierParameter.php:0</note>
</notes> </notes>
<segment state="translated"> <segment>
<source>parameters.validator.max_greater_typical</source> <source>parameters.validator.max_greater_typical</source>
<target>Wert muss größer oder gleich dem typischen Wert sein ({{ compared_value }}).</target> <target>Wert muss größer oder gleich dem typischen Wert sein ({{ compared_value }}).</target>
</segment> </segment>
@ -152,7 +152,7 @@
<note category="file-source" priority="1">Part-DB1\src\Entity\UserSystem\User.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\UserSystem\User.php:0</note> <note priority="1">Part-DB1\src\Entity\UserSystem\User.php:0</note>
</notes> </notes>
<segment state="translated"> <segment>
<source>validator.user.username_already_used</source> <source>validator.user.username_already_used</source>
<target>Es existiert bereits ein Benutzer mit diesem Namen.</target> <target>Es existiert bereits ein Benutzer mit diesem Namen.</target>
</segment> </segment>
@ -162,7 +162,7 @@
<note category="file-source" priority="1">Part-DB1\src\Entity\UserSystem\User.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\UserSystem\User.php:0</note> <note priority="1">Part-DB1\src\Entity\UserSystem\User.php:0</note>
</notes> </notes>
<segment state="translated"> <segment>
<source>user.invalid_username</source> <source>user.invalid_username</source>
<target>Der Benutzername darf nur Buchstaben, Zahlen, Unterstriche, Punkte, Plus- oder Minuszeichen enthalten.</target> <target>Der Benutzername darf nur Buchstaben, Zahlen, Unterstriche, Punkte, Plus- oder Minuszeichen enthalten.</target>
</segment> </segment>
@ -171,7 +171,7 @@
<notes> <notes>
<note category="state" priority="1">obsolete</note> <note category="state" priority="1">obsolete</note>
</notes> </notes>
<segment state="translated"> <segment>
<source>validator.noneofitschild.self</source> <source>validator.noneofitschild.self</source>
<target>Ein Element kann nicht sein eigenenes übergeordnetes Element sein!</target> <target>Ein Element kann nicht sein eigenenes übergeordnetes Element sein!</target>
</segment> </segment>
@ -180,139 +180,139 @@
<notes> <notes>
<note category="state" priority="1">obsolete</note> <note category="state" priority="1">obsolete</note>
</notes> </notes>
<segment state="final"> <segment>
<source>validator.noneofitschild.children</source> <source>validator.noneofitschild.children</source>
<target>Ein Kindelement kann nicht das übergeordnete Element sein!</target> <target>Ein Kindelement kann nicht das übergeordnete Element sein!</target>
</segment> </segment>
</unit> </unit>
<unit id="ayNr6QK" name="validator.select_valid_category"> <unit id="ayNr6QK" name="validator.select_valid_category">
<segment state="translated"> <segment>
<source>validator.select_valid_category</source> <source>validator.select_valid_category</source>
<target>Bitte wählen Sie eine gültige Kategorie.</target> <target>Bitte wählen Sie eine gültige Kategorie.</target>
</segment> </segment>
</unit> </unit>
<unit id="6vIlN5q" name="validator.part_lot.only_existing"> <unit id="6vIlN5q" name="validator.part_lot.only_existing">
<segment state="translated"> <segment>
<source>validator.part_lot.only_existing</source> <source>validator.part_lot.only_existing</source>
<target>Der Lagerort wurde als "nur bestehende Teile" markiert, daher können keine neuen Teile hinzugefügt werden.</target> <target>Der Lagerort wurde als "nur bestehende Teile" markiert, daher können keine neuen Teile hinzugefügt werden.</target>
</segment> </segment>
</unit> </unit>
<unit id="3xoKOIS" name="validator.part_lot.location_full.no_increase"> <unit id="3xoKOIS" name="validator.part_lot.location_full.no_increase">
<segment state="translated"> <segment>
<source>validator.part_lot.location_full.no_increase</source> <source>validator.part_lot.location_full.no_increase</source>
<target>Lagerort ist voll. Bestand kann nicht erhöht werden (neuer Wert muss kleiner sein als {{old_amount}}).</target> <target>Lagerort ist voll. Bestand kann nicht erhöht werden (neuer Wert muss kleiner sein als {{old_amount}}).</target>
</segment> </segment>
</unit> </unit>
<unit id="R6Ov4Yt" name="validator.part_lot.location_full"> <unit id="R6Ov4Yt" name="validator.part_lot.location_full">
<segment state="final"> <segment>
<source>validator.part_lot.location_full</source> <source>validator.part_lot.location_full</source>
<target>Der Lagerort ist voll, daher können keine neue Teile hinzugefügt werden.</target> <target>Der Lagerort ist voll, daher können keine neue Teile hinzugefügt werden.</target>
</segment> </segment>
</unit> </unit>
<unit id="BNQk2e7" name="validator.part_lot.single_part"> <unit id="BNQk2e7" name="validator.part_lot.single_part">
<segment state="final"> <segment>
<source>validator.part_lot.single_part</source> <source>validator.part_lot.single_part</source>
<target>Der Lagerort wurde als "Nur ein Bauteil" markiert, daher kann kein neues Bauteil hinzugefügt werden.</target> <target>Der Lagerort wurde als "Nur ein Bauteil" markiert, daher kann kein neues Bauteil hinzugefügt werden.</target>
</segment> </segment>
</unit> </unit>
<unit id="4gPskOG" name="validator.attachment.must_not_be_null"> <unit id="4gPskOG" name="validator.attachment.must_not_be_null">
<segment state="translated"> <segment>
<source>validator.attachment.must_not_be_null</source> <source>validator.attachment.must_not_be_null</source>
<target>Sie müssen ein Dateitypen auswählen!</target> <target>Sie müssen ein Dateitypen auswählen!</target>
</segment> </segment>
</unit> </unit>
<unit id="cDDVrWT" name="validator.orderdetail.supplier_must_not_be_null"> <unit id="cDDVrWT" name="validator.orderdetail.supplier_must_not_be_null">
<segment state="translated"> <segment>
<source>validator.orderdetail.supplier_must_not_be_null</source> <source>validator.orderdetail.supplier_must_not_be_null</source>
<target>Sie müssen einen Lieferanten auswählen!</target> <target>Sie müssen einen Lieferanten auswählen!</target>
</segment> </segment>
</unit> </unit>
<unit id="k5DDdB4" name="validator.measurement_unit.use_si_prefix_needs_unit"> <unit id="k5DDdB4" name="validator.measurement_unit.use_si_prefix_needs_unit">
<segment state="translated"> <segment>
<source>validator.measurement_unit.use_si_prefix_needs_unit</source> <source>validator.measurement_unit.use_si_prefix_needs_unit</source>
<target>Um SI-Prefixe zu aktivieren, müssen Sie einen Einheitensymbol setzen!</target> <target>Um SI-Prefixe zu aktivieren, müssen Sie einen Einheitensymbol setzen!</target>
</segment> </segment>
</unit> </unit>
<unit id="DuzIOCr" name="part.ipn.must_be_unique"> <unit id="DuzIOCr" name="part.ipn.must_be_unique">
<segment state="translated"> <segment>
<source>part.ipn.must_be_unique</source> <source>part.ipn.must_be_unique</source>
<target>Die Internal Part Number (IPN) muss einzigartig sein. Der Wert {{value}} wird bereits benutzt!</target> <target>Die Internal Part Number (IPN) muss einzigartig sein. Der Wert {{value}} wird bereits benutzt!</target>
</segment> </segment>
</unit> </unit>
<unit id="Z4Kuuo2" name="validator.project.bom_entry.name_or_part_needed"> <unit id="Z4Kuuo2" name="validator.project.bom_entry.name_or_part_needed">
<segment state="translated"> <segment>
<source>validator.project.bom_entry.name_or_part_needed</source> <source>validator.project.bom_entry.name_or_part_needed</source>
<target>Sie müssen ein Bauteil auswählen, oder einen Namen für ein nicht-Bauteil BOM-Eintrag setzen!</target> <target>Sie müssen ein Bauteil auswählen, oder einen Namen für ein nicht-Bauteil BOM-Eintrag setzen!</target>
</segment> </segment>
</unit> </unit>
<unit id="WF_v4ih" name="project.bom_entry.name_already_in_bom"> <unit id="WF_v4ih" name="project.bom_entry.name_already_in_bom">
<segment state="translated"> <segment>
<source>project.bom_entry.name_already_in_bom</source> <source>project.bom_entry.name_already_in_bom</source>
<target>Es gibt bereits einen BOM Eintrag mit diesem Namen!</target> <target>Es gibt bereits einen BOM Eintrag mit diesem Namen!</target>
</segment> </segment>
</unit> </unit>
<unit id="5v4p85H" name="project.bom_entry.part_already_in_bom"> <unit id="5v4p85H" name="project.bom_entry.part_already_in_bom">
<segment state="translated"> <segment>
<source>project.bom_entry.part_already_in_bom</source> <source>project.bom_entry.part_already_in_bom</source>
<target>Dieses Bauteil existiert bereits in der BOM!</target> <target>Dieses Bauteil existiert bereits in der BOM!</target>
</segment> </segment>
</unit> </unit>
<unit id="3lM32Tw" name="project.bom_entry.mountnames_quantity_mismatch"> <unit id="3lM32Tw" name="project.bom_entry.mountnames_quantity_mismatch">
<segment state="translated"> <segment>
<source>project.bom_entry.mountnames_quantity_mismatch</source> <source>project.bom_entry.mountnames_quantity_mismatch</source>
<target>Die Anzahl der Bestückungsnamen muss mit der Menge der zu bestückenden Bauteile übereinstimmen!</target> <target>Die Anzahl der Bestückungsnamen muss mit der Menge der zu bestückenden Bauteile übereinstimmen!</target>
</segment> </segment>
</unit> </unit>
<unit id="x47D5WT" name="project.bom_entry.can_not_add_own_builds_part"> <unit id="x47D5WT" name="project.bom_entry.can_not_add_own_builds_part">
<segment state="translated"> <segment>
<source>project.bom_entry.can_not_add_own_builds_part</source> <source>project.bom_entry.can_not_add_own_builds_part</source>
<target>Die BOM eines Projektes kann nicht das eigene Produktionsbauteil enthalten!</target> <target>Die BOM eines Projektes kann nicht das eigene Produktionsbauteil enthalten!</target>
</segment> </segment>
</unit> </unit>
<unit id="2x2XDI_" name="project.bom_has_to_include_all_subelement_parts"> <unit id="2x2XDI_" name="project.bom_has_to_include_all_subelement_parts">
<segment state="translated"> <segment>
<source>project.bom_has_to_include_all_subelement_parts</source> <source>project.bom_has_to_include_all_subelement_parts</source>
<target>Die Projekt-BOM muss alle Produktionsbauteile der Unterprojekte enthalten. Bauteil %part_name% des Projektes %project_name% fehlt!</target> <target>Die Projekt-BOM muss alle Produktionsbauteile der Unterprojekte enthalten. Bauteil %part_name% des Projektes %project_name% fehlt!</target>
</segment> </segment>
</unit> </unit>
<unit id="U9b1EzD" name="project.bom_entry.price_not_allowed_on_parts"> <unit id="U9b1EzD" name="project.bom_entry.price_not_allowed_on_parts">
<segment state="translated"> <segment>
<source>project.bom_entry.price_not_allowed_on_parts</source> <source>project.bom_entry.price_not_allowed_on_parts</source>
<target>Sie können keinen Preis für Bauteil-BOM-Einträge definieren. Definieren Sie die Preise stattdessen auf dem Bauteil.</target> <target>Sie können keinen Preis für Bauteil-BOM-Einträge definieren. Definieren Sie die Preise stattdessen auf dem Bauteil.</target>
</segment> </segment>
</unit> </unit>
<unit id="ID056SR" name="validator.project_build.lot_bigger_than_needed"> <unit id="ID056SR" name="validator.project_build.lot_bigger_than_needed">
<segment state="translated"> <segment>
<source>validator.project_build.lot_bigger_than_needed</source> <source>validator.project_build.lot_bigger_than_needed</source>
<target>Sie haben mehr zur Entnahme ausgewählt als notwendig. Entfernen Sie die überflüssige Anzahl.</target> <target>Sie haben mehr zur Entnahme ausgewählt als notwendig. Entfernen Sie die überflüssige Anzahl.</target>
</segment> </segment>
</unit> </unit>
<unit id="6hV5UqD" name="validator.project_build.lot_smaller_than_needed"> <unit id="6hV5UqD" name="validator.project_build.lot_smaller_than_needed">
<segment state="translated"> <segment>
<source>validator.project_build.lot_smaller_than_needed</source> <source>validator.project_build.lot_smaller_than_needed</source>
<target>Sie haben weniger zur Entnahme ausgewählt, als zum Bau notwendig ist! Fügen Sie mehr hinzu.</target> <target>Sie haben weniger zur Entnahme ausgewählt, als zum Bau notwendig ist! Fügen Sie mehr hinzu.</target>
</segment> </segment>
</unit> </unit>
<unit id="G9ZKt.4" name="part.name.must_match_category_regex"> <unit id="G9ZKt.4" name="part.name.must_match_category_regex">
<segment state="translated"> <segment>
<source>part.name.must_match_category_regex</source> <source>part.name.must_match_category_regex</source>
<target>Der Bauteilename entspricht nicht dem regulären Ausdruck, der von der Kategorie vorgegeben wurde: %regex%</target> <target>Der Bauteilename entspricht nicht dem regulären Ausdruck, der von der Kategorie vorgegeben wurde: %regex%</target>
</segment> </segment>
</unit> </unit>
<unit id="m8kMFhf" name="validator.attachment.name_not_blank"> <unit id="m8kMFhf" name="validator.attachment.name_not_blank">
<segment state="translated"> <segment>
<source>validator.attachment.name_not_blank</source> <source>validator.attachment.name_not_blank</source>
<target>Wählen Sie einen Wert, oder laden Sie eine Datei hoch, um dessen Dateiname automatisch als Namen für diesen Anhang zu nutzen.</target> <target>Wählen Sie einen Wert, oder laden Sie eine Datei hoch, um dessen Dateiname automatisch als Namen für diesen Anhang zu nutzen.</target>
</segment> </segment>
</unit> </unit>
<unit id="nwGaNBW" name="validator.part_lot.owner_must_match_storage_location_owner"> <unit id="nwGaNBW" name="validator.part_lot.owner_must_match_storage_location_owner">
<segment state="translated"> <segment>
<source>validator.part_lot.owner_must_match_storage_location_owner</source> <source>validator.part_lot.owner_must_match_storage_location_owner</source>
<target>Der Besitzer dieses Bauteilebestandes und des gewählten Lagerortes müssen übereinstimmen (%owner_name%)!</target> <target>Der Besitzer dieses Bauteilebestandes und des gewählten Lagerortes müssen übereinstimmen (%owner_name%)!</target>
</segment> </segment>
</unit> </unit>
<unit id="HXSz3nQ" name="validator.part_lot.owner_must_not_be_anonymous"> <unit id="HXSz3nQ" name="validator.part_lot.owner_must_not_be_anonymous">
<segment state="translated"> <segment>
<source>validator.part_lot.owner_must_not_be_anonymous</source> <source>validator.part_lot.owner_must_not_be_anonymous</source>
<target>Der Eigentümer darf nicht der anonymous Benutzer sein!</target> <target>Der Eigentümer darf nicht der anonymous Benutzer sein!</target>
</segment> </segment>

View file

@ -3029,11 +3029,6 @@ d@1, d@^1.0.1:
es5-ext "^0.10.50" es5-ext "^0.10.50"
type "^1.0.1" type "^1.0.1"
darkmode-js@^1.5.0:
version "1.5.7"
resolved "https://registry.yarnpkg.com/darkmode-js/-/darkmode-js-1.5.7.tgz#b260ff671d67e021446ac8bade458e08338f6410"
integrity sha512-gM1KhV/yy/84ZUpES9/oeOn0CVtuOi2HBd+Kccr4CJz+rFccQo2gUuPbjfyPXUx7t800Zf408G6kZb5rkTgjFA==
dash-ast@^2.0.1: dash-ast@^2.0.1:
version "2.0.1" version "2.0.1"
resolved "https://registry.yarnpkg.com/dash-ast/-/dash-ast-2.0.1.tgz#8d0fd2e601c59bf874cc22877ee7dd889f54dee8" resolved "https://registry.yarnpkg.com/dash-ast/-/dash-ast-2.0.1.tgz#8d0fd2e601c59bf874cc22877ee7dd889f54dee8"