mirror of
https://github.com/Part-DB/Part-DB-server.git
synced 2025-06-21 01:25:55 +02:00
Use a stimulus controller to implement collectionType for specifications/parameters.
This commit is contained in:
parent
f7ce94c168
commit
537b7fad7f
6 changed files with 153 additions and 91 deletions
62
assets/controllers/elements/collection_type_controller.js
Normal file
62
assets/controllers/elements/collection_type_controller.js
Normal file
|
@ -0,0 +1,62 @@
|
|||
import {Controller} from "@hotwired/stimulus";
|
||||
|
||||
import * as bootbox from "bootbox";
|
||||
import "../../css/bootbox_extensions.css";
|
||||
|
||||
export default class extends Controller {
|
||||
static values = {
|
||||
deleteMessage: String,
|
||||
prototype: String,
|
||||
}
|
||||
|
||||
static targets = ["target"];
|
||||
|
||||
/**
|
||||
* Decodes escaped HTML entities
|
||||
* @param {string} input
|
||||
* @returns {string}
|
||||
*/
|
||||
htmlDecode(input) {
|
||||
const doc = new DOMParser().parseFromString(input, "text/html");
|
||||
return doc.documentElement.textContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a unique ID to be used for the new element
|
||||
* @returns {string}
|
||||
*/
|
||||
generateUID() {
|
||||
const long = (performance.now().toString(36)+Math.random().toString(36)).replace(/\./g,"");
|
||||
return long.slice(0, 6); // 6 characters is enough for our unique IDs here
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new entry in the target using the given prototype value
|
||||
*/
|
||||
createElement(event) {
|
||||
const targetTable = this.targetTarget;
|
||||
const prototype = this.prototypeValue
|
||||
|
||||
//Apply the index to prototype to create our element to insert
|
||||
const newElementStr = this.htmlDecode(prototype.replace(/__name__/g, this.generateUID()));
|
||||
|
||||
|
||||
//Insert new html after the last child element
|
||||
//If the table has a tbody, insert it there
|
||||
if(targetTable.tBodies[0]) {
|
||||
targetTable.tBodies[0].insertAdjacentHTML('beforeend', newElementStr);
|
||||
} else { //Otherwise just insert it
|
||||
targetTable.insertAdjacentHTML('beforeend', newElementStr);
|
||||
}
|
||||
}
|
||||
|
||||
deleteElement(event) {
|
||||
bootbox.confirm(this.deleteMessageValue, (result) => {
|
||||
if(result) {
|
||||
const target = event.target;
|
||||
//Remove the row element from the table
|
||||
target.closest("tr").remove();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
27
assets/css/bootbox_extensions.css
Normal file
27
assets/css/bootbox_extensions.css
Normal file
|
@ -0,0 +1,27 @@
|
|||
.modal-body > .bootbox-close-button {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
padding: 0.5rem 0.75rem;
|
||||
z-index: 1;
|
||||
}
|
||||
.modal .bootbox-close-button {
|
||||
font-weight: 100;
|
||||
}
|
||||
|
||||
button.bootbox-close-button {
|
||||
padding: 0;
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
.bootbox-close-button {
|
||||
/* float: right; */
|
||||
font-size: 1.40625rem;
|
||||
font-weight: 600;
|
||||
line-height: 1;
|
||||
color: #000;
|
||||
text-shadow: none;
|
||||
opacity: .5;
|
||||
}
|
|
@ -1,54 +1,31 @@
|
|||
{% form_theme form with ['Parts/edit/edit_form_styles.html.twig', "bootstrap_4_layout.html.twig"] %}
|
||||
|
||||
<table class="table table-striped table-sm table-bordered table-responsive-md" id="specifications_table" data-prototype="{% if form.parameters.vars.prototype is defined %}{{ form_widget(form.parameters.vars.prototype)|e('html_attr') }}{% endif %}">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{% trans %}specifications.property{% endtrans %}</th>
|
||||
<th>{% trans %}specifications.symbol{% endtrans %}</th>
|
||||
<th>{% trans %}specifications.value_min{% endtrans %}</th>
|
||||
<th>{% trans %}specifications.value_typ{% endtrans %}</th>
|
||||
<th>{% trans %}specifications.value_max{% endtrans %}</th>
|
||||
<th>{% trans %}specifications.unit{% endtrans %}</th>
|
||||
<th>{% trans %}specifications.text{% endtrans %}</th>
|
||||
<th>{% trans %}specifications.group{% endtrans %}</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for param in form.parameters %}
|
||||
{{ form_widget(param) }}
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% import 'components/collection_type.macro.html.twig' as collection %}
|
||||
|
||||
<button type="button" class="btn btn-success mb-2" onclick="create_specification_entry(this)" {% if not is_granted('edit', entity) %}disabled{% endif %}>
|
||||
<i class="fas fa-plus-square fa-fw"></i>
|
||||
{% trans %}specification.create{% endtrans %}
|
||||
</button>
|
||||
<div {{ collection.controller(form, 'parameter.delete.confirm') }}>
|
||||
<table class="table table-striped table-sm table-bordered table-responsive-md" id="specifications_table" {{ collection.target() }}>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{% trans %}specifications.property{% endtrans %}</th>
|
||||
<th>{% trans %}specifications.symbol{% endtrans %}</th>
|
||||
<th>{% trans %}specifications.value_min{% endtrans %}</th>
|
||||
<th>{% trans %}specifications.value_typ{% endtrans %}</th>
|
||||
<th>{% trans %}specifications.value_max{% endtrans %}</th>
|
||||
<th>{% trans %}specifications.unit{% endtrans %}</th>
|
||||
<th>{% trans %}specifications.text{% endtrans %}</th>
|
||||
<th>{% trans %}specifications.group{% endtrans %}</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for param in form.parameters %}
|
||||
{{ form_widget(param) }}
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<script>
|
||||
function delete_specification_entry(btn) {
|
||||
window.bootbox.confirm('{% trans %}parameter.delete.confirm{% endtrans %}', function (result) {
|
||||
if(result) {
|
||||
$(btn).closest("tr").remove();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function create_specification_entry(btn) {
|
||||
//Determine the table, so we can determine, how many entries there are already.
|
||||
$holder = $(btn).siblings("table");
|
||||
|
||||
var index = $holder.children("tbody").children("tr").length;
|
||||
var newForm = $holder.data("prototype");
|
||||
|
||||
//Increase the index
|
||||
newForm = newForm.replace(/__name__/g, index);
|
||||
|
||||
$holder.children("tbody").append(newForm);
|
||||
|
||||
//Reinit the selectpickers
|
||||
//$(".selectpicker").selectpicker();
|
||||
|
||||
}
|
||||
</script>
|
||||
<button type="button" class="btn btn-success mb-2" {{ collection.create_btn() }} {% if not is_granted('edit', entity) %}disabled{% endif %}>
|
||||
<i class="fas fa-plus-square fa-fw"></i>
|
||||
{% trans %}specification.create{% endtrans %}
|
||||
</button>
|
||||
</div>
|
|
@ -1,7 +1,10 @@
|
|||
{% form_theme form with ['Parts/edit/edit_form_styles.html.twig', "bootstrap_4_layout.html.twig"] %}
|
||||
|
||||
<table class="table table-striped table-sm table-bordered table-responsive-md" id="specifications_table" data-prototype="{% if form.parameters.vars.prototype is defined %}{{ form_widget(form.parameters.vars.prototype)|e('html_attr') }}{% endif %}">
|
||||
<thead>
|
||||
{% import 'components/collection_type.macro.html.twig' as collection %}
|
||||
|
||||
<div {{ collection.controller(form, 'parameter.delete.confirm') }}>
|
||||
<table class="table table-striped table-sm table-bordered table-responsive-md" id="specifications_table" {{ collection.target() }}>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{% trans %}specifications.property{% endtrans %}</th>
|
||||
<th>{% trans %}specifications.symbol{% endtrans %}</th>
|
||||
|
@ -13,42 +16,16 @@
|
|||
<th>{% trans %}specifications.group{% endtrans %}</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for param in form.parameters %}
|
||||
{{ form_widget(param) }}
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for param in form.parameters %}
|
||||
{{ form_widget(param) }}
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<button type="button" class="btn btn-success" onclick="create_specification_entry(this)" {% if not is_granted('parameters.create', part) %}disabled{% endif %}>
|
||||
<i class="fas fa-plus-square fa-fw"></i>
|
||||
{% trans %}specification.create{% endtrans %}
|
||||
</button>
|
||||
|
||||
<script>
|
||||
function delete_specification_entry(btn) {
|
||||
window.bootbox.confirm('{% trans %}parameter.delete.confirm{% endtrans %}', function (result) {
|
||||
if(result) {
|
||||
$(btn).closest("tr").remove();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function create_specification_entry(btn) {
|
||||
//Determine the table, so we can determine, how many entries there are already.
|
||||
$holder = $(btn).siblings("table");
|
||||
|
||||
var index = $holder.children("tbody").children("tr").length;
|
||||
var newForm = $holder.data("prototype");
|
||||
|
||||
//Increase the index
|
||||
newForm = newForm.replace(/__name__/g, index);
|
||||
|
||||
$holder.children("tbody").append(newForm);
|
||||
|
||||
//Reinit the selectpickers
|
||||
//$(".selectpicker").selectpicker();
|
||||
|
||||
}
|
||||
</script>
|
||||
<button type="button" class="btn btn-success" {% if not is_granted('parameters.create', part) %}disabled{% endif %} {{ collection.create_btn() }}>
|
||||
<i class="fas fa-plus-square fa-fw"></i>
|
||||
{% trans %}specification.create{% endtrans %}
|
||||
</button>
|
||||
</div>
|
|
@ -63,6 +63,7 @@
|
|||
{% endblock %}
|
||||
|
||||
{% block parameter_widget %}
|
||||
{% import 'components/collection_type.macro.html.twig' as collection %}
|
||||
<tr>
|
||||
<td>{{ form_widget(form.name) }}{{ form_errors(form.name) }}</td>
|
||||
<td>{{ form_widget(form.symbol) }}{{ form_errors(form.symbol) }}</td>
|
||||
|
@ -73,7 +74,7 @@
|
|||
<td>{{ form_widget(form.value_text) }}{{ form_errors(form.value_text) }}</td>
|
||||
<td>{{ form_widget(form.group) }}{{ form_errors(form.group) }}</td>
|
||||
<td>
|
||||
<button type="button" class="btn btn-danger btn-sm order_btn_delete {% if form.parent.vars.allow_delete is defined and not form.parent.vars.allow_delete %}disabled{% endif %}" onclick="delete_specification_entry(this);" title="{% trans %}orderdetail.delete{% endtrans %}">
|
||||
<button type="button" class="btn btn-danger btn-sm order_btn_delete {% if form.parent.vars.allow_delete is defined and not form.parent.vars.allow_delete %}disabled{% endif %}" {{ collection.delete_btn() }} title="{% trans %}orderdetail.delete{% endtrans %}">
|
||||
<i class="fas fa-trash-alt fa-fw"></i>
|
||||
</button>
|
||||
{{ form_errors(form) }}
|
||||
|
|
18
templates/components/collection_type.macro.html.twig
Normal file
18
templates/components/collection_type.macro.html.twig
Normal file
|
@ -0,0 +1,18 @@
|
|||
{% macro controller(form, deleteMessage) %}
|
||||
{{ stimulus_controller('elements/collection_type', {
|
||||
'deleteMessage': 'parameter.delete.confirm'|trans,
|
||||
'prototype': form_widget(form.parameters.vars.prototype)|e('html_attr')
|
||||
}) }}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro target() %}
|
||||
{{ stimulus_target('elements/collection_type', 'target') }}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro create_btn() %}
|
||||
{{ stimulus_action('elements/collection_type', 'createElement') }}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro delete_btn() %}
|
||||
{{ stimulus_action('elements/collection_type', 'deleteElement') }}
|
||||
{% endmacro %}
|
Loading…
Add table
Add a link
Reference in a new issue