mirror of
https://github.com/Part-DB/Part-DB-server.git
synced 2025-06-21 01:25:55 +02:00
Implement attachment CollectionType using stimulus
This commit is contained in:
parent
bf3dba0fb2
commit
8323f374a4
10 changed files with 141 additions and 231 deletions
|
@ -0,0 +1,29 @@
|
|||
import {Controller} from "@hotwired/stimulus";
|
||||
|
||||
/**
|
||||
* This controller synchronizes the filetype filters of the file input type with our selected attachment type
|
||||
*/
|
||||
export default class extends Controller
|
||||
{
|
||||
_selectInput;
|
||||
_fileInput;
|
||||
|
||||
connect() {
|
||||
//Find the select input for our attachment form
|
||||
this._selectInput = this.element.querySelector('select');
|
||||
//Find the file input for our attachment form
|
||||
this._fileInput = this.element.querySelector('input[type="file"]');
|
||||
|
||||
this._selectInput.addEventListener('change', this.updateAllowedFiletypes.bind(this));
|
||||
|
||||
//Update file file on load
|
||||
this.updateAllowedFiletypes();
|
||||
}
|
||||
|
||||
updateAllowedFiletypes() {
|
||||
let selected_option = this._selectInput.options[this._selectInput.selectedIndex];
|
||||
let filetype_filter = selected_option.dataset.filetype_filter;
|
||||
//Apply filetype filter to file input
|
||||
this._fileInput.setAttribute('accept', filetype_filter);
|
||||
}
|
||||
}
|
|
@ -95,9 +95,6 @@ class AttachmentFormType extends AbstractType
|
|||
'label' => 'attachment.edit.attachment_type',
|
||||
'class' => AttachmentType::class,
|
||||
'disable_not_selectable' => true,
|
||||
'attr' => [
|
||||
'class' => 'attachment_type_selector',
|
||||
],
|
||||
]);
|
||||
|
||||
$builder->add('showInTable', CheckboxType::class, [
|
||||
|
@ -139,9 +136,9 @@ class AttachmentFormType extends AbstractType
|
|||
'mapped' => false,
|
||||
'required' => false,
|
||||
'attr' => [
|
||||
'class' => 'file',
|
||||
/*'class' => 'file',
|
||||
'data-show-preview' => 'false',
|
||||
'data-show-upload' => 'false',
|
||||
'data-show-upload' => 'false',*/
|
||||
],
|
||||
'constraints' => [
|
||||
//new AllowedFileExtension(),
|
||||
|
@ -186,4 +183,9 @@ class AttachmentFormType extends AbstractType
|
|||
'allow_builtins' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
public function getBlockPrefix()
|
||||
{
|
||||
return 'attachment';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -114,9 +114,11 @@ class StructuralEntityType extends AbstractType
|
|||
|
||||
$resolver->setDefault('empty_message', null);
|
||||
|
||||
$resolver->setDefault('controller', 'elements--selectpicker');
|
||||
|
||||
$resolver->setDefault('attr', static function (Options $options) {
|
||||
$tmp = [
|
||||
'data-controller' => 'elements--selectpicker',
|
||||
'data-controller' => $options['controller'],
|
||||
'data-live-search' => true,
|
||||
'title' => 'selectpicker.nothing_selected',
|
||||
];
|
||||
|
|
|
@ -1,115 +1,3 @@
|
|||
{% set delete_btn %}
|
||||
<button type="button" class="btn btn-danger lot_btn_delete" onclick="delete_attachment_entry(this);">
|
||||
<i class="fas fa-trash-alt fa-fw"></i>
|
||||
{% trans %}attachment.delete{% endtrans %}
|
||||
</button>
|
||||
{% endset %}
|
||||
{% import "components/attachments.macro.html.twig" as attachments %}
|
||||
|
||||
{#{{ form_row(form.master_picture_attachment) }} #}
|
||||
|
||||
<table class="table table-striped table-sm" id="attachments_table" data-prototype="{% if form.attachments.vars.prototype is defined %}{{ form_widget(form.attachments.vars.prototype)|e('html_attr') }}{% endif %}">
|
||||
<tbody>
|
||||
{% for attachment in form.attachments %}
|
||||
<tr>
|
||||
<td class="row">
|
||||
<div class="col-9">
|
||||
{{ form_widget(attachment) }}
|
||||
</div>
|
||||
<div class="ps-0 col-3">
|
||||
{{ delete_btn }}
|
||||
|
||||
{% set attach = attachment.vars.value %}
|
||||
{# @var attach \App\Entity\Attachments\Attachment #}
|
||||
|
||||
|
||||
{% if attachment_manager.fileExisting(attach) %}
|
||||
{% if not attach.external %}
|
||||
<br><br>
|
||||
<h6>
|
||||
<span class="badge bg-primary">
|
||||
<i class="fas fa-fw {{ ext_to_fa_icon(attach.extension) }}"></i> {{ attach.filename }}
|
||||
</span>
|
||||
<br>
|
||||
<span class="badge bg-secondary">
|
||||
<i class="fas fa-hdd fa-fw"></i> {{ attachment_manager.humanFileSize(attach) }}
|
||||
</span>
|
||||
</h6>
|
||||
{% else %}
|
||||
<br><br>
|
||||
<h6>
|
||||
<span class="badge bg-primary">
|
||||
<i class="fas fa-fw fa-globe"></i> {% trans %}attachment.external{% endtrans %}
|
||||
</span>
|
||||
</h6>
|
||||
{% endif %}
|
||||
{% if attach.secure and not is_granted('show_private', attach) %}
|
||||
{# Leave blank #}
|
||||
{% elseif attach.picture %}
|
||||
<a href="{{ attach | entityURL('file_view') }}" target="_blank" rel="noopener" data-turbo="false">
|
||||
<img class="img-fluid img-thumbnail thumbnail-sm" src="{{ attachment_thumbnail(attach, 'thumbnail_md') }}" alt="{% trans %}attachment.preview.alt{% endtrans %}" />
|
||||
</a>
|
||||
{% else %}
|
||||
<a href="{{ attach | entityURL('file_view') }}" rel="noopener" target="_blank" data-turbo="false" class="link-external">{% trans %}attachment.view{% endtrans %}</a>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<br><br>
|
||||
<h6>
|
||||
<span class="badge bg-warning">
|
||||
<i class="fas fa-exclamation-circle fa-fw"></i> {% trans %}attachment.file_not_found{% endtrans %}
|
||||
</span>
|
||||
</h6>
|
||||
{% endif %}
|
||||
|
||||
{% if attach.secure %}
|
||||
<h6>
|
||||
<span class="badge bg-success">
|
||||
<i class="fas fa-fw fa-shield-alt"></i> {% trans %}attachment.secure{% endtrans %}
|
||||
</span>
|
||||
</h6>
|
||||
{% endif %}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<button type="button" class="btn btn-success" onclick="create_attachment_entry(this)">
|
||||
<i class="fas fa-plus-square fa-fw"></i>
|
||||
{% trans %}attachment.create{% endtrans %}
|
||||
</button>
|
||||
|
||||
<script>
|
||||
function delete_attachment_entry(btn) {
|
||||
window.bootbox.confirm('{% trans %}part_lot.edit.delete.confirm{% endtrans %}', function (result) {
|
||||
if(result) {
|
||||
$(btn).parents("tr").remove();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function create_attachment_entry(btn) {
|
||||
//Determine the table, so we can determine, how many entries there are already.
|
||||
$holder = $("#attachments_table");
|
||||
|
||||
var index = $holder.children("tbody").children("tr").length;
|
||||
var newForm = $holder.data("prototype");
|
||||
|
||||
//Increase the index
|
||||
newForm = newForm.replace(/__name__/g, index);
|
||||
newForm = '<div class="col-9">' + newForm + '</div>';
|
||||
$newFormRow = $('<tr></tr>').html("<td class='row'>" + newForm + "</td>");
|
||||
|
||||
//Add delete button
|
||||
$btn = '<div class="col-3">' + '{{ delete_btn|e('js') }}' + '</div>';
|
||||
$('td' ,$newFormRow).append($btn);
|
||||
|
||||
$holder.append($newFormRow);
|
||||
|
||||
//Reinit the selectpickers
|
||||
$(".file").fileinput();
|
||||
|
||||
//Reinit typeahead:
|
||||
$(document).trigger('attachment:create');
|
||||
}
|
||||
</script>
|
||||
{{ attachments.attachment_edit_list(form.attachments) }}
|
|
@ -115,7 +115,7 @@
|
|||
|
||||
{%- block choice_widget_collapsed -%}
|
||||
{# Only add the BS5 form-select class if we dont use bootstrap-selectpicker #}
|
||||
{% if attr["data-controller"] is defined and attr["data-controller"] != "elements--selectpicker" %}
|
||||
{% if attr["data-controller"] is defined and attr["data-controller"] not in ["elements--selectpicker"] %}
|
||||
{%- set attr = attr|merge({class: (attr.class|default('') ~ ' form-select')|trim}) -%}
|
||||
{% else %}
|
||||
{# If it is an selectpicker add form-control class to fill whole width #}
|
||||
|
|
|
@ -1,112 +1,5 @@
|
|||
{% set delete_btn %}
|
||||
<button type="button" class="btn btn-danger lot_btn_delete" onclick="delete_attachment_entry(this);" {% if not is_granted('attachments.delete', part) %}disabled{% endif %}>
|
||||
<i class="fas fa-trash-alt fa-fw"></i>
|
||||
{% trans %}attachment.delete{% endtrans %}
|
||||
</button>
|
||||
{% endset %}
|
||||
{% import "components/attachments.macro.html.twig" as attachments %}
|
||||
|
||||
{{ form_row(form.master_picture_attachment) }}
|
||||
|
||||
<table class="table table-striped table-sm" id="attachments_table" data-prototype="{% if form.attachments.vars.prototype is defined %}{{ form_widget(form.attachments.vars.prototype)|e('html_attr') }}{% endif %}">
|
||||
<tbody>
|
||||
{% for attachment in form.attachments %}
|
||||
<tr>
|
||||
<td>
|
||||
{{ form_widget(attachment) }}
|
||||
</td>
|
||||
<td>
|
||||
{{ delete_btn }}
|
||||
|
||||
{% set attach = attachment.vars.value %}
|
||||
|
||||
{% if attachment_manager.fileExisting(attach) %}
|
||||
{% if not attach.external %}
|
||||
<br><br>
|
||||
<h6>
|
||||
<span class="badge bg-primary">
|
||||
<i class="fas fa-fw {{ ext_to_fa_icon(attach.extension) }}"></i> {{ attach.filename }}
|
||||
</span>
|
||||
<br>
|
||||
<span class="badge bg-secondary">
|
||||
<i class="fas fa-hdd fa-fw"></i> {{ attachment_manager.humanFileSize(attach) }}
|
||||
</span>
|
||||
</h6>
|
||||
{% else %}
|
||||
<br><br>
|
||||
<h6>
|
||||
<span class="badge bg-primary">
|
||||
<i class="fas fa-fw fa-globe"></i> {% trans %}attachment.external{% endtrans %}
|
||||
</span>
|
||||
</h6>
|
||||
{% endif %}
|
||||
|
||||
{% if attach.secure and not is_granted('show_private', attach) %}
|
||||
{# Leave blank #}
|
||||
{% elseif attach.picture %}
|
||||
<a href="{{ attach | entityURL('file_view') }}" rel="noopener" target="_blank" data-turbo="false">
|
||||
<img class="img-fluid img-thumbnail thumbnail-sm" src="{{ attachment_thumbnail(attach, 'thumbnail_md') }}" alt="{% trans %}attachment.preview.alt{% endtrans %}" />
|
||||
</a>
|
||||
{% else %}
|
||||
<a href="{{ attach | entityURL('file_view') }}" rel="noopener" target="_blank" data-turbo="false" class="link-external">{% trans %}attachment.view{% endtrans %}</a>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<br><br>
|
||||
<h6>
|
||||
<span class="badge bg-warning">
|
||||
<i class="fas fa-exclamation-circle fa-fw"></i> {% trans %}attachment.file_not_found{% endtrans %}
|
||||
</span>
|
||||
</h6>
|
||||
{% endif %}
|
||||
|
||||
{% if attach.secure %}
|
||||
<h6>
|
||||
<span class="badge bg-success">
|
||||
<i class="fas fa-fw fa-shield-alt"></i> {% trans %}attachment.secure{% endtrans %}
|
||||
</span>
|
||||
</h6>
|
||||
{% endif %}
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<button type="button" class="btn btn-success" onclick="create_attachment_entry(this)" {% if not is_granted('attachments.create', part) %}disabled{% endif %}>
|
||||
<i class="fas fa-plus-square fa-fw"></i>
|
||||
{% trans %}attachment.create{% endtrans %}
|
||||
</button>
|
||||
|
||||
<script>
|
||||
function delete_attachment_entry(btn) {
|
||||
window.bootbox.confirm('{% trans %}part_lot.edit.delete.confirm{% endtrans %}', function (result) {
|
||||
if(result) {
|
||||
$(btn).parents("tr").remove();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function create_attachment_entry(btn) {
|
||||
//Determine the table, so we can determine, how many entries there are already.
|
||||
$holder = $("#attachments_table");
|
||||
|
||||
var index = $holder.children("tbody").children("tr").length;
|
||||
var newForm = $holder.data("prototype");
|
||||
|
||||
//Increase the index
|
||||
newForm = newForm.replace(/__name__/g, index);
|
||||
newForm = '<td>' + newForm + '</td>';
|
||||
$newFormRow = $('<tr></tr>').html(newForm);
|
||||
|
||||
//Add delete button
|
||||
$btn = '<td>' + '{{ delete_btn|e('js') }}' + '</td>';
|
||||
$newFormRow.append($btn);
|
||||
|
||||
$holder.append($newFormRow);
|
||||
|
||||
$(".file").fileinput();
|
||||
|
||||
//Reinit typeahead:
|
||||
$(document).trigger('attachment:create');
|
||||
}
|
||||
</script>
|
||||
{{ attachments.attachment_edit_list(form.attachments) }}
|
|
@ -102,3 +102,73 @@
|
|||
</td>
|
||||
</tr>
|
||||
{% endblock %}
|
||||
|
||||
{% block attachment_widget %}
|
||||
{% import 'components/collection_type.macro.html.twig' as collection %}
|
||||
|
||||
{% dump(form) %}
|
||||
|
||||
<tr {{ stimulus_controller('elements/attachmenttype_change') }}>
|
||||
<td>
|
||||
{{ form_widget(form) }}
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" class="btn btn-danger lot_btn_delete" {{ collection.delete_btn() }} {# {% if not is_granted('attachments.delete', part) %}disabled{% endif %}#}>
|
||||
<i class="fas fa-trash-alt fa-fw"></i>
|
||||
{% trans %}attachment.delete{% endtrans %}
|
||||
</button>
|
||||
|
||||
{% set attach = form.vars.value %}
|
||||
|
||||
{% if attach is not null %}
|
||||
{% if attachment_manager.fileExisting(attach) %}
|
||||
{% if not attach.external %}
|
||||
<br><br>
|
||||
<h6>
|
||||
<span class="badge bg-primary">
|
||||
<i class="fas fa-fw {{ ext_to_fa_icon(attach.extension) }}"></i> {{ attach.filename }}
|
||||
</span>
|
||||
<br>
|
||||
<span class="badge bg-secondary">
|
||||
<i class="fas fa-hdd fa-fw"></i> {{ attachment_manager.humanFileSize(attach) }}
|
||||
</span>
|
||||
</h6>
|
||||
{% else %}
|
||||
<br><br>
|
||||
<h6>
|
||||
<span class="badge bg-primary">
|
||||
<i class="fas fa-fw fa-globe"></i> {% trans %}attachment.external{% endtrans %}
|
||||
</span>
|
||||
</h6>
|
||||
{% endif %}
|
||||
|
||||
{% if attach.secure and not is_granted('show_private', attach) %}
|
||||
{# Leave blank #}
|
||||
{% elseif attach.picture %}
|
||||
<a href="{{ attach | entityURL('file_view') }}" rel="noopener" target="_blank" data-turbo="false">
|
||||
<img class="img-fluid img-thumbnail thumbnail-sm" src="{{ attachment_thumbnail(attach, 'thumbnail_md') }}" alt="{% trans %}attachment.preview.alt{% endtrans %}" />
|
||||
</a>
|
||||
{% else %}
|
||||
<a href="{{ attach | entityURL('file_view') }}" rel="noopener" target="_blank" data-turbo="false" class="link-external">{% trans %}attachment.view{% endtrans %}</a>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<br><br>
|
||||
<h6>
|
||||
<span class="badge bg-warning">
|
||||
<i class="fas fa-exclamation-circle fa-fw"></i> {% trans %}attachment.file_not_found{% endtrans %}
|
||||
</span>
|
||||
</h6>
|
||||
{% endif %}
|
||||
|
||||
{% if attach.secure %}
|
||||
<h6>
|
||||
<span class="badge bg-success">
|
||||
<i class="fas fa-fw fa-shield-alt"></i> {% trans %}attachment.secure{% endtrans %}
|
||||
</span>
|
||||
</h6>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
{% endblock %}
|
20
templates/components/attachments.macro.html.twig
Normal file
20
templates/components/attachments.macro.html.twig
Normal file
|
@ -0,0 +1,20 @@
|
|||
{# Renders a editable list of all attachments. form is the Attachment CollectionType #}
|
||||
{% macro attachment_edit_list(form, part_mode = false) %}
|
||||
{% form_theme form with ['Parts/edit/edit_form_styles.html.twig'] %}
|
||||
|
||||
{% import 'components/collection_type.macro.html.twig' as collection %}
|
||||
<div {{ collection.controller(form, 'attachment.edit.delete.confirm') }}>
|
||||
<table class="table table-striped table-sm" {{ collection.target() }}>
|
||||
<tbody>
|
||||
{% for attachment in form %}
|
||||
{{ form_widget(attachment) }}
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<button type="button" class="btn btn-success" {{ collection.create_btn() }} {% if part_mode and not is_granted('attachments.create', part) %}disabled{% endif %}>
|
||||
<i class="fas fa-plus-square fa-fw"></i>
|
||||
{% trans %}attachment.create{% endtrans %}
|
||||
</button>
|
||||
</div>
|
||||
{% endmacro %}
|
|
@ -1,6 +1,6 @@
|
|||
{% macro controller(form, deleteMessage) %}
|
||||
{{ stimulus_controller('elements/collection_type', {
|
||||
'deleteMessage': 'parameter.delete.confirm'|trans,
|
||||
'deleteMessage': deleteMessage|trans,
|
||||
'prototype': form_widget(form.vars.prototype)|e('html_attr')
|
||||
}) }}
|
||||
{% endmacro %}
|
||||
|
|
|
@ -9351,5 +9351,11 @@ Element 3</target>
|
|||
<target>Actions finished successfully.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="_3l6FO_" name="attachment.edit.delete.confirm">
|
||||
<segment>
|
||||
<source>attachment.edit.delete.confirm</source>
|
||||
<target>Do you really want to delete this attachment?</target>
|
||||
</segment>
|
||||
</unit>
|
||||
</file>
|
||||
</xliff>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue