diff --git a/assets/controllers/elements/collection_type_controller.js b/assets/controllers/elements/collection_type_controller.js
new file mode 100644
index 00000000..f0fd09ba
--- /dev/null
+++ b/assets/controllers/elements/collection_type_controller.js
@@ -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();
+ }
+ });
+ }
+}
\ No newline at end of file
diff --git a/assets/css/bootbox_extensions.css b/assets/css/bootbox_extensions.css
new file mode 100644
index 00000000..aaf273ab
--- /dev/null
+++ b/assets/css/bootbox_extensions.css
@@ -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;
+}
\ No newline at end of file
diff --git a/templates/AdminPages/_parameters.html.twig b/templates/AdminPages/_parameters.html.twig
index 49f3d0c5..0a98674b 100644
--- a/templates/AdminPages/_parameters.html.twig
+++ b/templates/AdminPages/_parameters.html.twig
@@ -1,54 +1,31 @@
{% form_theme form with ['Parts/edit/edit_form_styles.html.twig', "bootstrap_4_layout.html.twig"] %}
-
-
-
-
{% trans %}specifications.property{% endtrans %}
-
{% trans %}specifications.symbol{% endtrans %}
-
{% trans %}specifications.value_min{% endtrans %}
-
{% trans %}specifications.value_typ{% endtrans %}
-
{% trans %}specifications.value_max{% endtrans %}
-
{% trans %}specifications.unit{% endtrans %}
-
{% trans %}specifications.text{% endtrans %}
-
{% trans %}specifications.group{% endtrans %}
-
-
-
-
- {% for param in form.parameters %}
- {{ form_widget(param) }}
- {% endfor %}
-
-
+{% import 'components/collection_type.macro.html.twig' as collection %}
-
+
+
+
+
+
{% trans %}specifications.property{% endtrans %}
+
{% trans %}specifications.symbol{% endtrans %}
+
{% trans %}specifications.value_min{% endtrans %}
+
{% trans %}specifications.value_typ{% endtrans %}
+
{% trans %}specifications.value_max{% endtrans %}
+
{% trans %}specifications.unit{% endtrans %}
+
{% trans %}specifications.text{% endtrans %}
+
{% trans %}specifications.group{% endtrans %}
+
+
+
+
+ {% for param in form.parameters %}
+ {{ form_widget(param) }}
+ {% endfor %}
+
+
-
\ No newline at end of file
+
+
\ No newline at end of file
diff --git a/templates/Parts/edit/_specifications.html.twig b/templates/Parts/edit/_specifications.html.twig
index 4176d750..e3bea0b1 100644
--- a/templates/Parts/edit/_specifications.html.twig
+++ b/templates/Parts/edit/_specifications.html.twig
@@ -1,7 +1,10 @@
{% form_theme form with ['Parts/edit/edit_form_styles.html.twig', "bootstrap_4_layout.html.twig"] %}
-
-
+{% import 'components/collection_type.macro.html.twig' as collection %}
+
+
+
+
{% trans %}specifications.property{% endtrans %}
{% trans %}specifications.symbol{% endtrans %}
@@ -13,42 +16,16 @@
{% trans %}specifications.group{% endtrans %}
-
-
- {% for param in form.parameters %}
- {{ form_widget(param) }}
- {% endfor %}
-
-
+
+
+ {% for param in form.parameters %}
+ {{ form_widget(param) }}
+ {% endfor %}
+
+
-
-
-
\ No newline at end of file
+
+
\ No newline at end of file
diff --git a/templates/Parts/edit/edit_form_styles.html.twig b/templates/Parts/edit/edit_form_styles.html.twig
index b6d873b9..9ad495e0 100644
--- a/templates/Parts/edit/edit_form_styles.html.twig
+++ b/templates/Parts/edit/edit_form_styles.html.twig
@@ -63,6 +63,7 @@
{% endblock %}
{% block parameter_widget %}
+ {% import 'components/collection_type.macro.html.twig' as collection %}