Move optional twig form macro attributes to opt

This commit is contained in:
Michael Weimann 2023-04-19 22:34:08 +02:00 committed by Igor Scheller
parent c0957955fd
commit dc216a0464
19 changed files with 541 additions and 299 deletions

View File

@ -14,7 +14,10 @@
<form method="post" action="{{ url('/admin/logs') }}" class="form-inline"> <form method="post" action="{{ url('/admin/logs') }}" class="form-inline">
{{ csrf() }} {{ csrf() }}
{{ f.input('search', __('form.search'), 'text', {'value': search, 'hide_label': true}) }} {{ f.input('search', __('form.search'), {
'value': search,
'hide_label': true,
}) }}
{{ f.submit(__('form.search')) }} {{ f.submit(__('form.search')) }}
</form> </form>

View File

@ -11,26 +11,26 @@
<div class="row"> <div class="row">
<div class="col-lg-6"> <div class="col-lg-6">
{{ f.input( {{ f.input('name', __('room.name'), {
'name', 'required': true,
__('room.name'), 'required_icon': true,
null, 'value': f.formData('room', room ? room.name : ''),
{'required': true, 'entry_required_icon': true, 'value': f.formData('room', room ? room.name : '')} }) }}
) }}
{{ f.input('dect', __('room.dect'), null, {'value': f.formData('dect', room ? room.dect : '')}) }} {{ f.input('dect', __('room.dect'), {
{{ f.input( 'value': f.formData('dect', room ? room.dect : ''),
'map_url', }) }}
__('room.map_url'), {{ f.input('map_url', __('room.map_url'), {
'url', 'type': 'url',
{'value': f.formData('map_url', room ? room.map_url : ''), 'info': __('room.map_url.info')} 'value': f.formData('map_url', room ? room.map_url : ''),
) }} 'info': __('room.map_url.info'),
}) }}
{{ f.textarea( {{ f.textarea('description', __('room.description'), {
'description', 'value': f.formData('description', room ? room.description : ''),
__('room.description'), 'rows': 5,
{'value': f.formData('description', room ? room.description : ''), 'rows': 5, 'info': __('form.markdown')} 'info': __('form.markdown')
) }} }) }}
</div> </div>
<div class="col-lg-6"> <div class="col-lg-6">
@ -41,11 +41,11 @@
{% set needed = needed_angel_types ? needed_angel_types.where('angel_type_id', angel_type.id).first() : null %} {% set needed = needed_angel_types ? needed_angel_types.where('angel_type_id', angel_type.id).first() : null %}
{% set name = 'angel_type_' ~ angel_type.id %} {% set name = 'angel_type_' ~ angel_type.id %}
<div class="col-md-4"> <div class="col-md-4">
{{ f.number( {{ f.number(name, angel_type.name, {
name, 'value': f.formData(name, needed ? needed.count : 0),
angel_type.name, 'min': 0,
{'value': f.formData(name, needed ? needed.count : 0), 'min': 0, 'step': 1} 'step': 1,
) }} }) }}
</div> </div>
{% endfor %} {% endfor %}
</div> </div>

View File

@ -15,13 +15,30 @@
{{ csrf() }} {{ csrf() }}
<div class="col-lg-12"> <div class="col-lg-12">
{{ f.input('name', __('schedule.name'), null, {'required': true, 'value': schedule ? schedule.name : ''}) }} {{ f.input('name', __('schedule.name'), {
{{ f.input('url', __('schedule.url'), 'url', {'required': true, 'value': schedule ? schedule.url : ''}) }} 'required': true,
'value': schedule ? schedule.name : '',
}) }}
{{ f.input('url', __('schedule.url'), {
'type': 'url',
'required': true,
'value': schedule ? schedule.url : ''
}) }}
{{ f.select('shift_type', shift_types|default([]), __('schedule.shift-type'), schedule ? schedule.shift_type : '') }} {{ f.select('shift_type', __('schedule.shift-type'), shift_types|default([]), {
'selected': schedule ? schedule.shift_type : '',
}) }}
{{ f.input('minutes_before', __('schedule.minutes-before'), 'number', {'required': true, 'value': schedule ? schedule.minutes_before : 15}) }} {{ f.input('minutes_before', __('schedule.minutes-before'), {
{{ f.input('minutes_after', __('schedule.minutes-after'), 'number', {'required': true, 'value': schedule ? schedule.minutes_after : 15}) }} 'type': 'number',
'required': true,
'value': schedule ? schedule.minutes_before : 15
}) }}
{{ f.input('minutes_after', __('schedule.minutes-after'), {
'type': 'number',
'required': true,
'value': schedule ? schedule.minutes_after : 15
}) }}
{{ f.submit(__('form.save')) }} {{ f.submit(__('form.save')) }}
</div> </div>

View File

@ -18,19 +18,31 @@
<div class="row"> <div class="row">
{% if is_tshirt %} {% if is_tshirt %}
<div class="col-md-6"> <div class="col-md-6">
{{ f.select('shirt_size', config('tshirt_sizes'), __('user.shirt_size'), userdata.personalData.shirt_size) }} {{ f.select('shirt_size', __('user.shirt_size'), config('tshirt_sizes'), {
'selected': userdata.personalData.shirt_size,
}) }}
</div> </div>
{% endif %} {% endif %}
<div class="col-md-6"> <div class="col-md-6">
{{ f.switch('arrived', __('user.arrived'), userdata.state.arrived, {'disabled': not has_permission_to('admin_arrive')}) }} {{ f.switch('arrived', __('user.arrived'), {
'checked': userdata.state.arrived,
'disabled': not has_permission_to('admin_arrive'),
}) }}
{% if userdata.state.force_active %} {% if userdata.state.force_active %}
{{ f.switch('force_active', __('user.force_active'), true, {'disabled': true}) }} {{ f.switch('force_active', __('user.force_active'), {
'checked': true,
'disabled': true,
}) }}
{% endif %} {% endif %}
{{ f.switch('active', __('user.active'), userdata.state.active) }} {{ f.switch('active', __('user.active'), {
'checked': userdata.state.active,
}) }}
{{ f.switch('got_shirt', is_tshirt ? __('user.got_shirt') : __('user.got_goodie'), userdata.state.got_shirt) }} {{ f.switch('got_shirt', is_tshirt ? __('user.got_shirt') : __('user.got_goodie'), {
'checked': userdata.state.got_shirt,
}) }}
</div> </div>
<div class="col-md-12"> <div class="col-md-12">
{{ f.submit(__('form.save')) }} {{ f.submit(__('form.save')) }}

View File

@ -23,24 +23,23 @@
{{ m.user(user, {'pronoun': true}) }} {{ m.user(user, {'pronoun': true}) }}
</div> </div>
<div class="col-12"> <div class="col-12">
{{ f.input( {{ f.input('work_date', __('worklog.date'), {
'work_date', 'type': 'date',
__('worklog.date'), 'value': work_date.format('Y-m-d'),
'date', 'required': true,
{'value': work_date.format('Y-m-d'), 'required': true} }) }}
) }} {{ f.input('work_hours', __('worklog.hours'), {
{{ f.input( 'type': 'number',
'work_hours', 'value': work_hours,
__('worklog.hours'), 'required': true,
'number', 'step': '0.01',
{'value': work_hours, 'required': true, 'step': '0.01', 'min': 0} 'min': 0,
) }} }) }}
{{ f.input( {{ f.input('comment', __('worklog.comment'), {
'comment', 'value': comment,
__('worklog.comment'), 'required': true,
'text', 'max_length': 200,
{'value': comment, 'required': true, 'max_length': 200} }) }}
) }}
{{ f.submit(__('form.save')) }} {{ f.submit(__('form.save')) }}
</div> </div>
</div> </div>

View File

@ -6,12 +6,36 @@
<span class="bi bi-info-circle-fill text-info" data-bs-toggle="tooltip" title="{{ text | e('html_attr') }}"></span> <span class="bi bi-info-circle-fill text-info" data-bs-toggle="tooltip" title="{{ text | e('html_attr') }}"></span>
{%- endmacro %} {%- endmacro %}
{% macro input(name, label, type, opt) %} {#
Renders an input field wrapped in a DIV with mb-3.
@param {string} name - Will be used as value for "id" and "name" attributes.
@param {string} label - If not empty a "label" element with this text will be rendered.
@param {string} [opt.type="text"] - Optional type of the input field. Defaults to "text".
@param {bool} [opt.hide_label=false] - If true the label will be hidden. This could be useful for screenreders.
Defaults to false.
@param {bool} [opt.required_icon=false] - Whether an asterisk should be displayed after the label
to indicate that this field is mandatory.
Won't be displayed without a label. Defaults to false.
@param {string} [opt.info] - If set an additional info icon will be added to the label with the text as tooltip.
Won't be displayed without a label.
@param {string} [opt.value=""] - Optional value to set. Defaults to empty string.
@param {int} [opt.min_length] - Optional "minlength" attribute value.
@param {int} [opt.max_length] - Optional "maxlength" attribute value.
@param {int|float|string} [opt.min] - Optional "min" attribute value.
@param {int|float|string} [opt.max] - Optional "max" attribute value.
@param {int|float} [opt.step] - Optional "step" attribute value.
@param {string} [opt.autocomplete] - Optional "autocomplete" attribute value.
@param {bool} [opt.required=false] - Whether to add the "required" attribute. Defaults to false.
@param {bool} [opt.disabled=false] - Whether to add the "disabled" attribute. Defaults to false.
@param {bool} [opt.readonly=false] - Whether to add the "readonly" attribute. Defaults to false.
#}
{% macro input(name, label, opt) %}
<div class="mb-3"> <div class="mb-3">
{% if label -%} {% if label -%}
<label for="{{ name }}" class="form-label {% if opt.hide_label|default(false) %}sr-only{% endif %}"> <label for="{{ name }}" class="form-label {% if opt.hide_label|default(false) %}sr-only{% endif %}">
{{ label }} {{ label }}
{% if opt.entry_required_icon|default(false) %} {% if opt.required_icon|default(false) %}
{{ _self.entry_required() }} {{ _self.entry_required() }}
{% endif %} {% endif %}
{% if opt.info is defined %} {% if opt.info is defined %}
@ -20,7 +44,7 @@
</label> </label>
{%- endif %} {%- endif %}
<input <input
type="{{ type|default('text') }}" class="form-control" type="{{ opt.type|default('text') }}" class="form-control"
id="{{ name }}" name="{{ name }}" id="{{ name }}" name="{{ name }}"
value="{{ opt.value|default('')|escape('html_attr') }}" value="{{ opt.value|default('')|escape('html_attr') }}"
{%- if opt.min_length is defined %} minlength="{{ opt.min_length }}"{% endif %} {%- if opt.min_length is defined %} minlength="{{ opt.min_length }}"{% endif %}
@ -42,11 +66,30 @@
</div> </div>
{%- endmacro %} {%- endmacro %}
{#
Renders a "number" type input field wrapped in a DIV with mb-3.
Also adds buttons to increment / decrement the value.
@param {string} name - Will be used as value for "id" and "name" attributes.
@param {string} label - If not empty a "label" element with this text will be rendered.
@param {bool} [opt.required_icon=false] - Whether an asterisk should be displayed after the label
to indicate that this field is mandatory.
Won't be displayed without a label. Defaults to false.
@param {string} [opt.info] - If set an additional info icon will be added to the label with the text as tooltip.
Won't be displayed without a label.
@param {string} [opt.value=""] - Optional value to set. Defaults to empty string.
@param {int|float|string} [opt.min] - Optional "min" attribute value.
@param {int|float|string} [opt.max] - Optional "max" attribute value.
@param {int|float} [opt.step] - Optional "step" attribute value.
@param {bool} [opt.required=false] - Whether to add the "required" attribute. Defaults to false.
@param {bool} [opt.disabled=false] - Whether to add the "disabled" attribute. Defaults to false.
@param {bool} [opt.readonly=false] - Whether to add the "readonly" attribute. Defaults to false.
#}
{% macro number(name, label, opt) %} {% macro number(name, label, opt) %}
<div class="mb-3"> <div class="mb-3">
{% if label -%} {% if label is defined -%}
<label class="form-label" for="{{ name }}">{{ label }}</label> <label class="form-label" for="{{ name }}">{{ label }}</label>
{% if opt.entry_required_icon|default(false) %} {% if opt.required_icon|default(false) %}
{{ _self.entry_required() }} {{ _self.entry_required() }}
{% endif %} {% endif %}
{% if opt.info is defined %} {% if opt.info is defined %}
@ -84,11 +127,24 @@
</div> </div>
{% endmacro %} {% endmacro %}
{#
Renders a "textarea" element wrapped in a DIV with mb-3.
Also adds buttons to increment / decrement the value.
@param {string} name - Will be used as value for "id" and "name" attributes.
@param {string} label - If not empty a "label" element with this text will be rendered.
@param {bool} [opt.required_icon=false] - Whether an asterisk should be displayed after the label
to indicate that this field is mandatory.
Won't be displayed without a label. Defaults to false.
@param {bool} [opt.required] - Whether to add the "required" attribute. Defaults to false.
@param {int} [opt.rows=0] - Optional value of the "rows" attriute. Defaults to 0.
@param {string} [opt.value=""] - Optional value to set. Defaults to empty string.
#}
{% macro textarea(name, label, opt) %} {% macro textarea(name, label, opt) %}
<div class="mb-3"> <div class="mb-3">
{% if label -%} {% if label is defined -%}
<label class="form-label" for="{{ name }}">{{ label }}</label> <label class="form-label" for="{{ name }}">{{ label }}</label>
{% if opt.entry_required_icon|default(false) %} {% if opt.required_icon|default(false) %}
{{ _self.entry_required() }} {{ _self.entry_required() }}
{% endif %} {% endif %}
{% if opt.info is defined %} {% if opt.info is defined %}
@ -106,12 +162,28 @@
</div> </div>
{%- endmacro %} {%- endmacro %}
{% macro select(name, data, label, selected, opt) %} {#
Renders a select element wrapped in a DIV with mb-3.
@param {string} name - Will be used as value for "id" and "name" attributes.
@param {string} label - If not empty a "label" element with this text will be rendered.
@param {{value, description}} data - Select options. "value" will be the option value, "description" the label.
@param {string} [opt.selected] - Optional value of an option to initially set as "selected".
@param {bool} [opt.required_icon=false] - Whether an asterisk should be displayed after the label
to indicate that this field is mandatory.
Won't be displayed without a label. Defaults to false.
@param {string} [opt.info] - If set an additional info icon will be added to the label with the text as tooltip.
Won't be displayed without a label.
@param {string} [opt.class] - Optional additional CSS classes to be added to the actual "select" element.
@param {bool} [opt.required=false] - Whether to add the "required" attribute. Defaults to false.
@param {bool} [opt.default_option] - If set a default option with the param as label and an empty value will be added.
#}
{% macro select(name, label, data, opt) %}
<div class="mb-3"> <div class="mb-3">
{% if label -%} {% if label is defined -%}
<label class="form-label" for="{{ name }}"> <label class="form-label" for="{{ name }}">
{{ label }} {{ label }}
{% if opt.entry_required_icon|default(false) %} {% if opt.required_icon|default(false) %}
{{ _self.entry_required() }} {{ _self.entry_required() }}
{% endif %} {% endif %}
{% if opt.info is defined %} {% if opt.info is defined %}
@ -126,21 +198,32 @@
<option value="">{{ opt.default_option }}</option> <option value="">{{ opt.default_option }}</option>
{% endif %} {% endif %}
{% for value,decription in data -%} {% for value,decription in data -%}
<option value="{{ value }}"{% if value == selected %} selected{% endif %}>{{ decription }}</option> <option value="{{ value }}"{% if opt.selected is defined and value == opt.selected %} selected{% endif %}>{{ decription }}</option>
{% endfor %} {% endfor %}
</select> </select>
</div> </div>
{%- endmacro %} {%- endmacro %}
{% macro checkbox(name, label, checked, value, disabled, raw_label, opt) %} {#
Renders a Bootstrap checkbox element with mb-3.
@param {string} name - Will be used as value for "id" and "name" attributes.
@param {string} label - Checkbox label
@param {string} [opt.value="1"] - Optional value to set. Defaults to "1".
@param {bool} [opt.checked=false] - Whether to add the "checked" attribute. Defaults to false.
@param {bool} [opt.disabled=false] - Whether to add the "disabled" attribute. Defaults to false.
@param {bool} [opt.raw_label=false] - Whether to use the raw label value (=do not escape). Defaults to false.
@param {string} [opt.info] - If set an additional info icon will be added to the label with the text as tooltip.
#}
{% macro checkbox(name, label, opt) %}
<div class="form-check mb-3"> <div class="form-check mb-3">
<input class="form-check-input" type="checkbox" id="{{ name }}" name="{{ name }}" <input class="form-check-input" type="checkbox" id="{{ name }}" name="{{ name }}"
value="{{ value|default('1') }}" value="{{ opt.value|default('1') }}"
{%- if checked|default(false) %} checked{% endif %} {%- if opt.checked|default(false) %} checked{% endif %}
{%- if disabled|default(false) %} disabled{% endif %} {%- if opt.disabled|default(false) %} disabled{% endif %}
> >
<label class="form-check-label" for="{{ name }}"> <label class="form-check-label" for="{{ name }}">
{%- if raw_label|default(false) -%} {%- if opt.raw_label|default(false) -%}
{{ label|raw }} {{ label|raw }}
{%- else -%} {%- else -%}
{{ label }} {{ label }}
@ -152,10 +235,32 @@
</div> </div>
{%- endmacro %} {%- endmacro %}
{#
Renders a "hidden" type input field.
@param {string} name - Will be used as value for "id" and "name" attributes.
@param {string} value - Field value
#}
{% macro hidden(name, value) %} {% macro hidden(name, value) %}
<input type="hidden" id="{{ name }}" name="{{ name }}" value="{{ value|escape('html_attr') }}"> <input type="hidden" id="{{ name }}" name="{{ name }}" value="{{ value|escape('html_attr') }}">
{%- endmacro %} {%- endmacro %}
{#
Renders a button.
@param {string} label - Button label
@param {string} [opt.btn_type="secondary"] - Bootstrap button type. Defaults to "secondary".
@param {string} [opt.size] - Optional Bootstrap button size to apply, such as "sm", "lg".
@param {string} [opt.type] - Optional value for the "type" attribute.
@param {string} [opt.name] - Optional value for the "name" attribute.
@param {string} [opt.title] - Optional value for the "title" attribute.
@param {string} [opt.value] - Optional value for the "value" attribute.
Defaults to "1" if only opt.name is provided.
@param {string} [opt.icon_left] - Optional icon to be added before the button label.
Must be a Bootstrap icon class without prefix, such as "info" or "check".
@param {string} [opt.icon_right] - Optional icon to be added after the button label.
Must be a Bootstrap icon class without prefix, such as "info" or "check".
#}
{% macro button(label, opt) %} {% macro button(label, opt) %}
<button <button
class="btn btn-{{ opt.btn_type|default('secondary') }} class="btn btn-{{ opt.btn_type|default('secondary') }}
@ -175,11 +280,20 @@
{{ _self.button(label|default(__('form.submit')), {'type': 'submit', 'btn_type': 'primary'}|merge(opt|default({}))) }} {{ _self.button(label|default(__('form.submit')), {'type': 'submit', 'btn_type': 'primary'}|merge(opt|default({}))) }}
{%- endmacro %} {%- endmacro %}
{% macro switch(name, label, checked, opt) %} {#
Renders a "checkbox" element that will be styled as switch.
@param {string} name - Will be used as value for "id" and "name" attributes.
@param {string} label - Switch label
@param {string} [opt.value="1"] - Optional value to set. Defaults to "1".
@param {bool} [opt.checked=false] - Whether to add the "checked" attribute. Defaults to false.
@param {bool} [opt.disabled=false] - Whether to add the "disabled" attribute. Defaults to false.
#}
{% macro switch(name, label, opt) %}
<div class="form-check form-switch mb-3"> <div class="form-check form-switch mb-3">
<input class="form-check-input" type="checkbox" id="{{ name }}" name="{{ name }}" <input class="form-check-input" type="checkbox" id="{{ name }}" name="{{ name }}"
value="{{ opt.value|default('1') }}" value="{{ opt.value|default('1') }}"
{%- if checked|default(false) %} checked{% endif %} {%- if opt.checked|default(false) %} checked{% endif %}
{%- if opt.disabled|default(false) %} disabled{% endif %} {%- if opt.disabled|default(false) %} disabled{% endif %}
> >
<label class="form-check-label" for="{{ name }}">{{ label }}</label> <label class="form-check-label" for="{{ name }}">{{ label }}</label>

View File

@ -217,51 +217,147 @@
<div class="row"> <div class="row">
<div class="col-md-3 col-lg-2"> <div class="col-md-3 col-lg-2">
{{ f.input('form-input-text', 'Text', 'text', {'value': 'Value'}) }} <h5>Text</h5>
<code>f.input(id, label, opt)</code>
{{ f.input('form-input-text', 'Text field', {
'value': 'Value',
}) }}
{{ f.input('form-input-text-label-icons', 'Text field with required and info icon', {
'value': 'Value',
'required_icon': true,
'info': 'Very important field info!',
}) }}
{{ f.input('form-input-text-hidden-label', 'Hidden label', {
'value': 'Hidden label',
'hide_label': true,
}) }}
{{ f.input('form-input-text-disabled', 'Disabled', {
'disabled': true,
'value': 'Value',
}) }}
{{ f.input('form-input-text-readonly', null, {
'type': 'Readonly',
'readonly': true,
'value': 'w/o label',
}) }}
</div> </div>
<div class="col-md-3 col-lg-2"> <div class="col-md-3 col-lg-2">
{{ f.input('form-input-text-hidden-label', 'Hidden label', 'text', {'value': 'Hidden label', 'hide_label': true}) }} <h5>Password</h5>
<code>f.password(id, label, opt)</code>
{{ f.input('form-input-password', 'Password', {
'type': 'password',
'value': 'Value',
}) }}
</div> </div>
<div class="col-md-3 col-lg-2"> <div class="col-md-3 col-lg-2">
{{ f.input('form-input-text-disabled', 'Disabled', 'text', {'disabled': true, 'value': 'Value'}) }} <h5>Number</h5>
<code>f.number(id, label, opt)</code>
{{ f.number('form-input-number', 'Number field', {
'type': 'number',
'value': 42,
}) }}
{{ f.number('form-input-number-label-icons', 'Number field with required and info icon', {
'type': 'number',
'value': 42,
'required_icon': true,
'info': 'Very important field info!',
}) }}
{{ f.number('form-input-number-disabled', 'Disabled', {
'disabled': true,
'value': 42,
}) }}
{{ f.number('form-input-number-readonly', 'Readonly', {
'readonly': true,
'value': 42,
}) }}
{{ f.number('form-input-number-wo-label', null, {
'type': 'number',
'value': 42,
}) }}
</div> </div>
<div class="col-md-3 col-lg-2"> <div class="col-md-3 col-lg-2">
{{ f.input('form-input-text-readonly', 'Readonly', 'text', {'readonly': true, 'value': 'Value'}) }} <h5>Textarea</h5>
<code>f.textarea(id, label, opt)</code>
{{ f.textarea('form-input-textarea', 'Textarea', {
'rows': 2,
'value': lipsum,
}) }}
{{ f.textarea('form-input-textarea-label-icons', 'Textarea with required and info icon', {
'required_icon': true,
'info': 'Very important field info!',
'rows': 2,
'value': lipsum,
}) }}
{{ f.textarea('form-input-textarea-wo-label', null, {
'required_icon': true,
'rows': 2,
'value': 'w/o label',
}) }}
</div> </div>
<div class="col-md-3 col-lg-2"> <div class="col-md-3 col-lg-2">
{{ f.input('form-input-password', 'Password', 'password', {'value': 'Value'}) }} <h5>Select</h5>
<code>f.textarea(id, label, data, opt)</code>
{{ f.select('form-input-select-1', 'Select 1', {
'opt1': 'Option 1',
'opt2': 'Option 2',
'opt3': 'Another option',
'opt4': 'A looooooooong item item item item',
}) }}
{{ f.select(
'form-input-select-2',
'Select 2',
{
'sh': 'Bash',
'js': 'JavaScript',
'p': 'PHP',
'py': 'Python',
},
{
'selected': 'js',
},
) }}
{{ f.select('form-input-select-2', 'Select 3', selectOptions, {
'selected': 'option_7',
}) }}
{{ f.select('date-select', 'Date select', dateSelectOptions) }}
</div> </div>
<div class="col-md-3 col-lg-2"> <div class="col-md-3 col-lg-2">
{{ f.input('form-input-number', 'Number', 'number', {'value': 42}) }} <h5>Buttons</h5>
</div> <code>f.button(label, opt)</code>
</div> <div class="mb-3">
<div class="row">
<div class="col-md-3 col-lg-2">
{{ f.textarea('form-input-textarea', 'Textarea', {'rows': 2, 'value': lipsum}) }}
</div>
<div class="col-md-3 col-lg-2">
{{ f.select('form-input-select-1', {'opt1': 'Option 1', 'opt2': 'Option 2', 'opt3': 'Another option', 'opt4': 'A looooooooong item item item item'}, 'Select 1', 'opt1') }}
{{ f.select('form-input-select-2', {'sh': 'Bash', 'js': 'JavaScript', 'p': 'PHP', 'py': 'Python'}, 'Select 2', 'js') }}
{{ f.select('form-input-select-2', selectOptions, 'Select 3', 'Option 7') }}
{{ f.select('date-select', dateSelectOptions, 'Date select') }}
</div>
<div class="col-md-3 col-lg-2">
<label class="form-label">Button</label>
<div>
{{ f.button('Button') }} {{ f.button('Button') }}
</div> </div>
<div class="mb-3">
{{ f.button('Small button with icons', {
'size': 'sm',
'icon_left': 'check',
'icon_right': 'info',
'title': 'Click me!',
}) }}
</div> </div>
<div class="col-md-3 col-lg-2"> <code>f.submit(label)</code>
Form submit
<form id="form"> <form id="form">
{{ f.submit() }} {{ f.submit('Go!') }}
</form> </form>
</div> </div>
<div id="checkboxes" class="col-md-3 col-lg-2"> <div id="checkboxes" class="col-md-3 col-lg-2">
Checkbox<br> <h5>Checkbox</h5>
{{ f.checkbox('form-input-checkbox', 'Checkbox 1', true, '1') }} <code>f.checkbox(id, label, opt)</code>
{{ f.checkbox('form-input-checkbox-2', 'Checkbox 2', false, '2') }} {{ f.checkbox('form-input-checkbox', 'Checkbox 1', {
{{ f.checkbox('form-input-checkbox-3', 'Checkbox 3', false, '3') }} 'checked': true, 'value': '1',
}) }}
{{ f.checkbox('form-input-checkbox-2', 'Checkbox 2', {
'checked': false, 'value': '2',
}) }}
{{ f.checkbox('form-input-checkbox-3', 'Checkbox 3', {
'checked': false, 'value': '3',
}) }}
<div class="d-grid gap-2"> <div class="d-grid gap-2">
<button type="button" class="btn btn-secondary d-print-none checkbox-selection" data-id="checkboxes" data-value="true"> <button type="button" class="btn btn-secondary d-print-none checkbox-selection" data-id="checkboxes" data-value="true">
Select all Select all
@ -273,9 +369,37 @@
Unselect all Unselect all
</button> </button>
</div> </div>
<hr>
{{ f.checkbox('form-input-checkbox-disabled', 'Disabled', {
'disabled': true,
}) }}
{{ f.checkbox('form-input-checkbox-raw-label', '<i>Raw label</i>', {
'raw_label': true,
}) }}
</div> </div>
<div id="checkboxes" class="col-md-3 col-lg-2">
<h5>Switch</h5>
<code>f.switch(id, label, opt)</code>
{{ f.switch('form-switch', 'Switch') }}
{{ f.switch('form-switch-checked', 'Switch (checked)', {
'checked': true,
}) }}
{{ f.switch('form-switch-disabled', 'Switch (disabled)', {
'disabled': true,
}) }}
</div>
<div class="col-md-3 col-lg-2">
<h5>Hidden</h5>
<code>hidden(name, value)</code>
<p>
{{ f.hidden('hidden-name', 'hidden value') | escape }}
</p>
</div>
<div class="col-md-3 col-lg-2 checkbox-inline"> <div class="col-md-3 col-lg-2 checkbox-inline">
Radio<br> <h5>Radio</h5>
<div class="form-check form-check-inline"> <div class="form-check form-check-inline">
<input class="form-check-input" type="radio" id="yey" checked="checked" name="form-input-radio" value="1"> <input class="form-check-input" type="radio" id="yey" checked="checked" name="form-input-radio" value="1">
<label class="form-check-label" for="yey">Yey</label> <label class="form-check-label" for="yey">Yey</label>
@ -285,23 +409,25 @@
<label class="form-check-label" for="nay">Nay</label> <label class="form-check-label" for="nay">Nay</label>
</div> </div>
</div> </div>
</div>
<div class="row">
<div class="col-md-3 col-lg-2"> <div class="col-md-3 col-lg-2">
<h5>Date / time</h5>
<div class="mb-3">
<label class="form-label" for="input_date">Date</label> <label class="form-label" for="input_date">Date</label>
<input id="input_date" type="date" placeholder="YYYY-MM-DD" pattern="[0-9]{4}-[0-9]{2}-[0-9]{2}" name="design-date" class="form-control" value="2021-09-15"> <input id="input_date" type="date" placeholder="YYYY-MM-DD" pattern="[0-9]{4}-[0-9]{2}-[0-9]{2}" name="design-date" class="form-control" value="2021-09-15">
</div> </div>
<div class="col-md-3 col-lg-2"> <div class="mb-3">
<label class="form-label" for="input_datetime_local">Datetime</label> <label class="form-label" for="input_datetime_local">Datetime</label>
<input id="input_datetime_local" type="datetime-local" placeholder="YYYY-MM-DD HH:MM" pattern="[0-9]{4}-[0-9]{2}-[0-9]{2} ([01][0-9]|2[0-3]):[0-5][0-9]" name="design-datetime" class="form-control" value="2021-09-15T13:37"> <input id="input_datetime_local" type="datetime-local" placeholder="YYYY-MM-DD HH:MM" pattern="[0-9]{4}-[0-9]{2}-[0-9]{2} ([01][0-9]|2[0-3]):[0-5][0-9]" name="design-datetime" class="form-control" value="2021-09-15T13:37">
</div> </div>
<div class="col-md-3 col-lg-2"> <div class="mb-3">
<label class="form-label" for="input_time">Time</label> <label class="form-label" for="input_time">Time</label>
<input type="time" class="form-control" id="input_time" name="input_time" size="5" pattern="^\d{1,2}:\d{2}$" placeholder="HH:MM" maxlength="5" value="13:37"> <input type="time" class="form-control" id="input_time" name="input_time" size="5" pattern="^\d{1,2}:\d{2}$" placeholder="HH:MM" maxlength="5" value="13:37">
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div>
<span id="other" class="ref-id"></span> <span id="other" class="ref-id"></span>
<h3>Other <a href="#other" class="ref-link">{{ m.icon('link') }}</a></h3> <h3>Other <a href="#other" class="ref-link">{{ m.icon('link') }}</a></h3>
@ -380,52 +506,6 @@
</div> </div>
</div> </div>
<h3>form.twig</h3>
<div class="row mb-4">
<div class="col-md-3">
<h4><code>input(name, label, type, opt)</code></h4>
<p>{{ f.input('input-name', 'Label', 'text', {'required': true, 'value': 'Value'}) }}</p>
</div>
<div class="col-md-3">
<h4><code>textarea(name, label, opt)</code></h4>
<p>{{ f.textarea('textarea-name', 'Label', {'required': true, 'rows': 2, 'value': lipsum}) }}</p>
</div>
<div class="col-md-3">
<h4><code>select(name, data, label, selected)</code></h4>
<p>{{ f.select('select-name', {'foo': 'Foo', 'bar': 'Bar'}, 'Label', 'bar') }}</p>
</div>
<div class="col-md-3">
<h4><code>checkbox(name, label, checked, value)</code></h4>
<p>
{{ f.checkbox('checkbox-name', 'Label', false) }}<br>
{{ f.checkbox('checkbox-name', 'Label', true, 'on') }}
</p>
</div>
<div class="col-md-3">
<h4><code>hidden(name, value)</code></h4>
<p>
{{ f.hidden('hidden-name', 'hidden value') | escape }}
</p>
</div>
<div class="col-md-3">
<h4><code>button(label, opt)</code></h4>
<p>
{{ f.button('Label', {'name': 'button-name', 'value': 'buton-value'}) }}
</p>
</div>
<div class="col-md-3">
<h4><code>submit(label, opt)</code></h4>
<p>
{{ f.submit() }}
</p>
</div>
</div>
<span id="bar_chart" class="ref-id"></span> <span id="bar_chart" class="ref-id"></span>
<h3>Bar Chart <a href="#bar_chart" class="ref-link">{{ m.icon('link') }}</a></h3> <h3>Bar Chart <a href="#bar_chart" class="ref-link">{{ m.icon('link') }}</a></h3>
{{ bar_chart | raw }} {{ bar_chart | raw }}

View File

@ -31,10 +31,17 @@
<div class="row mb-4"> <div class="row mb-4">
<div class="col-md-12"> <div class="col-md-12">
{{ f.input('question', __('faq.question'), null, {'required': true, 'value': faq ? faq.question : ''}) }} {{ f.input('question', __('faq.question'), {
'required': true,
'value': faq ? faq.question : '',
}) }}
</div> </div>
<div class="col-md-12"> <div class="col-md-12">
{{ f.textarea('text', __('faq.message'), {'required': true, 'rows': 10, 'value': faq ? faq.text : ''}) }} {{ f.textarea('text', __('faq.message'), {
'required': true,
'rows': 10,
'value': faq ? faq.text : '',
}) }}
{{ f.submit() }} {{ f.submit() }}

View File

@ -71,7 +71,10 @@
{{ csrf() }} {{ csrf() }}
<div class="col-md-12"> <div class="col-md-12">
<h4>{{ __('question.add') }}</h4> <h4>{{ __('question.add') }}</h4>
{{ f.textarea('text', __('question.question'), {'required': true, 'rows': 5}) }} {{ f.textarea('text', __('question.question'), {
'required': true,
'rows': 5,
}) }}
{{ f.submit() }} {{ f.submit() }}
</div> </div>
</form> </form>

View File

@ -15,8 +15,11 @@
{{ csrf() }} {{ csrf() }}
<div class="row gx-2 mb-3"> <div class="row gx-2 mb-3">
<div class="col-auto"> <div class="col-auto">
{{ f.select('user_id', users, null, null, {{ f.select('user_id', null, users, {
{ 'class': 'pe-5', 'required': true, 'default_option': __('message.choose_angel') }) }} 'class': 'pe-5',
'required': true,
'default_option': __('message.choose_angel'),
}) }}
</div> </div>
<div class="col"> <div class="col">
{{ f.submit(__('message.to_conversation'), {'btn_type': 'secondary'}) }} {{ f.submit(__('message.to_conversation'), {'btn_type': 'secondary'}) }}

View File

@ -36,20 +36,34 @@
{{ f.input( {{ f.input(
'title', 'title',
__('news.edit.subject'), __('news.edit.subject'),
null, {
{'required': true, 'value': news ? news.title : ''} 'required': true,
'value': news ? news.title : '',
}
) }} ) }}
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
{{ f.checkbox('is_meeting', __('news.edit.is_meeting'), is_meeting) }} {{ f.checkbox('is_meeting', __('news.edit.is_meeting'), {
{{ f.checkbox('is_pinned', __('news.edit.is_pinned'), is_pinned) }} 'checked': is_meeting,
{% if has_permission_to('news.important') %} {{ f.checkbox('is_important', __('news.edit.is_important'), is_important) }}{% endif %} }) }}
{{ f.checkbox('is_pinned', __('news.edit.is_pinned'), {
'checked': is_pinned,
}) }}
{% if has_permission_to('news.important') %}
{{ f.checkbox('is_important', __('news.edit.is_important'), {
'checked': is_important,
}) }}
{% endif %}
</div> </div>
</div> </div>
<div class="row mb-4"> <div class="row mb-4">
<div class="col-md-12"> <div class="col-md-12">
{{ f.textarea('text', __('news.edit.message'), {'required': true, 'rows': 10, 'value': news ? news.text : ''}) }} {{ f.textarea('text', __('news.edit.message'), {
'required': true,
'rows': 10,
'value': news ? news.text : '',
}) }}
<p>{{ m.info(__('news.edit.hint')) }}</p> <p>{{ m.info(__('news.edit.hint')) }}</p>

View File

@ -47,7 +47,9 @@
<form action="" enctype="multipart/form-data" method="post"> <form action="" enctype="multipart/form-data" method="post">
{{ csrf() }} {{ csrf() }}
{{ f.textarea('comment', __('news.comments.message'), {'required': true}) }} {{ f.textarea('comment', __('news.comments.message'), {
'required': true,
}) }}
{{ f.submit() }} {{ f.submit() }}
</form> </form>
</div> </div>

View File

@ -7,8 +7,16 @@
<form action="" enctype="multipart/form-data" method="post"> <form action="" enctype="multipart/form-data" method="post">
{{ csrf() }} {{ csrf() }}
{{ f.input('password', __('Password'), 'password', {'min_length': min_length, 'required': true}) }} {{ f.input('password', __('Password'), {
{{ f.input('password_confirmation', __('Confirm password'), 'password', {'min_length': min_length, 'required': true}) }} 'type': 'password',
'min_length': min_length,
'required': true,
}) }}
{{ f.input('password_confirmation', __('Confirm password'), {
'type': 'password',
'min_length': min_length,
'required': true,
}) }}
{{ f.submit(__('Save')) }} {{ f.submit(__('Save')) }}
</form> </form>

View File

@ -17,7 +17,10 @@
{{ csrf() }} {{ csrf() }}
{{ __('We will send you an e-mail with a password recovery link. Please use the email address you used for registration.') }} {{ __('We will send you an e-mail with a password recovery link. Please use the email address you used for registration.') }}
{{ f.input('email', __('E-Mail'), 'email', {'required': true}) }} {{ f.input('email', __('E-Mail'), {
'type': 'email',
'required': true,
}) }}
{{ f.submit(__('Recover')) }} {{ f.submit(__('Recover')) }}
</form> </form>

View File

@ -31,11 +31,18 @@
<div class="row"> <div class="row">
<div class="col-md-12"> <div class="col-md-12">
{{ f.textarea('text', __('question.question'), {'required': true, 'rows': 10, 'value': question ? question.text : ''}) }} {{ f.textarea('text', __('question.question'), {
'required': true,
'rows': 10,
'value': question ? question.text : '',
}) }}
</div> </div>
<div class="col-md-12"> <div class="col-md-12">
{% if is_admin|default(false) %} {% if is_admin|default(false) %}
{{ f.textarea('answer', __('question.answer'), {'required': true, 'rows': 10, 'value': question ? question.answer : ''}) }} {{ f.textarea('answer', __('question.answer'), {
'required': true,
'rows': 10, 'value': question ? question.answer : '',
}) }}
{% endif %} {% endif %}
{{ f.submit() }} {{ f.submit() }}

View File

@ -11,7 +11,9 @@
<div class="row"> <div class="row">
<div class="col-md-12"> <div class="col-md-12">
{{ m.info(__('settings.language.info')) }} {{ m.info(__('settings.language.info')) }}
{{ f.select('select_language', languages, __('settings.language'), current_language) }} {{ f.select('select_language', __('settings.language'), languages, {
'selected': current_language,
}) }}
{{ f.submit(__('form.save')) }} {{ f.submit(__('form.save')) }}
</div> </div>
</div> </div>

View File

@ -13,25 +13,24 @@
{{ m.info(__('settings.password.info')) }} {{ m.info(__('settings.password.info')) }}
{% if user.password %} {% if user.password %}
{{ f.input( {{ f.input('password', __('settings.password.password'), {
'password', 'type': 'password',
__('settings.password.password'), 'required': true,
'password', 'autocomplete': 'current-password',
{'required': true, 'autocomplete': 'current-password'} }) }}
) }}
{% endif %} {% endif %}
{{ f.input( {{ f.input('new_password', __('settings.password.new_password'), {
'new_password', 'type': 'password',
__('settings.password.new_password'), 'min_length': min_length,
'password', 'required': true,
{'min_length': min_length, 'required': true, 'autocomplete': 'new-password'} 'autocomplete': 'new-password',
) }} }) }}
{{ f.input( {{ f.input('new_password2', __('settings.password.new_password2'), {
'new_password2', 'type': 'password',
__('settings.password.new_password2'), 'min_length': min_length,
'password', 'required': true,
{'min_length': min_length, 'required': true, 'autocomplete': 'new-password'} 'autocomplete': 'new-password',
) }} }) }}
{{ f.submit(__('form.save')) }} {{ f.submit(__('form.save')) }}
</div> </div>
</div> </div>

View File

@ -18,21 +18,17 @@
<div class="row g-4"> <div class="row g-4">
<div class="col-lg-6"> <div class="col-lg-6">
{{ f.input( {{ f.input('nick', __('settings.profile.nick'), {
'nick', 'value': user.name,
__('settings.profile.nick'), 'disabled': true,
'text', }) }}
{'value': user.name, 'disabled': true}
) }}
</div> </div>
{% if config('enable_pronoun') %} {% if config('enable_pronoun') %}
<div class="col-lg-6"> <div class="col-lg-6">
{{ f.input( {{ f.input('pronoun', __('settings.profile.pronoun'), {
'pronoun', 'value': user.personalData.pronoun,
__('settings.profile.pronoun'), 'max_length': 15,
'text', }) }}
{'value': user.personalData.pronoun ,'max_length': 15}
) }}
{{ m.info(__('settings.profile.pronoun.info')) }} {{ m.info(__('settings.profile.pronoun.info')) }}
</div> </div>
{% endif %} {% endif %}
@ -41,20 +37,16 @@
{% if config('enable_user_name') %} {% if config('enable_user_name') %}
<div class="row g-4"> <div class="row g-4">
<div class="col-sm-6"> <div class="col-sm-6">
{{ f.input( {{ f.input('first_name', __('settings.profile.firstname'), {
'first_name', 'value': user.personalData.first_name,
__('settings.profile.firstname'), 'max_length': 64,
'text', }) }}
{'value': user.personalData.first_name, 'max_length': 64}
) }}
</div> </div>
<div class="col-sm-6"> <div class="col-sm-6">
{{ f.input( {{ f.input('last_name', __('settings.profile.lastname'), {
'last_name', 'value': user.personalData.last_name,
__('settings.profile.lastname'), 'max_length': 64,
'text', }) }}
{'value': user.personalData.last_name, 'max_length': 64}
) }}
</div> </div>
</div> </div>
{% endif %} {% endif %}
@ -62,31 +54,23 @@
{% if config('enable_planned_arrival') %} {% if config('enable_planned_arrival') %}
<div class="row g-4"> <div class="row g-4">
<div class="col-sm-6"> <div class="col-sm-6">
{{ f.input( {{ f.input('planned_arrival_date', __('settings.profile.planned_arrival_date'), {
'planned_arrival_date', 'type': 'date',
__('settings.profile.planned_arrival_date'),
'date',
{
'value': user.personalData.planned_arrival_date.format('Y-m-d'), 'value': user.personalData.planned_arrival_date.format('Y-m-d'),
'required': true, 'required': true,
'entry_required_icon': true, 'required_icon': true,
'min': config('buildup_start') ? config('buildup_start').format('Y-m-d') : '', 'min': config('buildup_start') ? config('buildup_start').format('Y-m-d') : '',
'max': config('teardown_end') ? config('teardown_end').format('Y-m-d') : '', 'max': config('teardown_end') ? config('teardown_end').format('Y-m-d') : '',
} }) }}
) }}
</div> </div>
<div class="col-sm-6"> <div class="col-sm-6">
{% set planned_departure_date = user.personalData.planned_departure_date %} {% set planned_departure_date = user.personalData.planned_departure_date %}
{{ f.input( {{ f.input('planned_departure_date', __('settings.profile.planned_departure_date'), {
'planned_departure_date', 'type': 'date',
__('settings.profile.planned_departure_date'),
'date',
{
'value': planned_departure_date ? planned_departure_date.format('Y-m-d') : '', 'value': planned_departure_date ? planned_departure_date.format('Y-m-d') : '',
'min': config('buildup_start') ? config('buildup_start').format('Y-m-d') : '', 'min': config('buildup_start') ? config('buildup_start').format('Y-m-d') : '',
'max': config('teardown_end') ? config('teardown_end').format('Y-m-d') : '', 'max': config('teardown_end') ? config('teardown_end').format('Y-m-d') : '',
} }) }}
) }}
</div> </div>
</div> </div>
{% endif %} {% endif %}
@ -94,75 +78,60 @@
<div class="row g-4"> <div class="row g-4">
{% if config('enable_dect') %} {% if config('enable_dect') %}
<div class="col-md-6"> <div class="col-md-6">
{{ f.input( {{ f.input('dect', __('settings.profile.dect'), {
'dect', 'value': user.contact.dect,
__('settings.profile.dect'), 'max_length': 40,
'text', }) }}
{'value': user.contact.dect, 'max_length': 40}
) }}
</div> </div>
{% endif %} {% endif %}
<div class="col-md-6"> <div class="col-md-6">
{{ f.input( {{ f.input('mobile', __('settings.profile.mobile'), {
'mobile', 'value': user.contact.mobile,
__('settings.profile.mobile'), 'max_length': 40,
'text', }) }}
{'value': user.contact.mobile, 'max_length': 40}
) }}
{% if config('enable_mobile_show') %} {% if config('enable_mobile_show') %}
{{ f.checkbox( {{ f.checkbox('mobile_show', __('settings.profile.mobile_show'), {
'mobile_show', 'checked': user.settings.mobile_show,
__('settings.profile.mobile_show'), }) }}
user.settings.mobile_show
) }}
{% endif %} {% endif %}
</div> </div>
</div> </div>
<div class="row g-4"> <div class="row g-4">
<div class="col-md-6"> <div class="col-md-6">
{{ f.input( {{ f.input('email', __('settings.profile.email'), {
'email', 'type': 'email',
__('settings.profile.email'), 'value': user.email,
'email', 'max_length': 254,
{'value': user.email, 'max_length': 254, 'required': true, 'entry_required_icon': true} 'required': true,
) }} 'required_icon': true,
}) }}
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
{{ f.checkbox( {{ f.checkbox('email_shiftinfo', __('settings.profile.email_shiftinfo'), {
'email_shiftinfo', 'checked': [config('app_name')],
__('settings.profile.email_shiftinfo', [config('app_name')]), 'value': user.settings.email_shiftinfo,
user.settings.email_shiftinfo }) }}
) }} {{ f.checkbox('email_news', __('settings.profile.email_news'), {
{{ f.checkbox( 'checked': user.settings.email_news,
'email_news', }) }}
__('settings.profile.email_news'), {{ f.checkbox('email_messages', __('settings.profile.email_messages'), {
user.settings.email_news 'checked': user.settings.email_messages,
) }} }) }}
{{ f.checkbox( {{ f.checkbox('email_human', __('settings.profile.email_by_human_allowed'), {
'email_messages', 'checked': user.settings.email_human,
__('settings.profile.email_messages'), }) }}
user.settings.email_messages
) }}
{{ f.checkbox(
'email_human',
__('settings.profile.email_by_human_allowed'),
user.settings.email_human
) }}
{% if goodie_enabled %} {% if goodie_enabled %}
{% set privacy_email = config('privacy_email') %} {% set privacy_email = config('privacy_email') %}
{% set email_goody_label = __('settings.profile.email_goody') ~ {% set email_goody_label = __('settings.profile.email_goody') ~
(privacy_email ? ' ' ~ __('settings.profile.privacy', [privacy_email]) : '') (privacy_email ? ' ' ~ __('settings.profile.privacy', [privacy_email]) : '')
%} %}
{{ f.checkbox( {{ f.checkbox('email_goody', email_goody_label, {
'email_goody', 'checked': user.settings.email_goody,
email_goody_label, 'value': user.settings.email_goody,
user.settings.email_goody, 'raw_label': true,
user.settings.email_goody, }) }}
false,
true
) }}
{% endif %} {% endif %}
</div> </div>
</div> </div>
@ -170,13 +139,11 @@
<div class="row g-4"> <div class="row g-4">
{% if goodie_tshirt %} {% if goodie_tshirt %}
<div class="col-12"> <div class="col-12">
{{ f.select( {{ f.select('shirt_size', __('settings.profile.shirt_size'), config('tshirt_sizes'), {
'shirt_size', 'selected': user.personalData.shirt_size,
config('tshirt_sizes'), 'required': true,
__('settings.profile.shirt_size'), 'required_icon': true,
user.personalData.shirt_size, }) }}
{'required': true, 'entry_required_icon': true}
) }}
</div> </div>
{% endif %} {% endif %}

View File

@ -11,7 +11,9 @@
<div class="row"> <div class="row">
<div class="col-md-12"> <div class="col-md-12">
{{ m.info(__('settings.theme.info')) }} {{ m.info(__('settings.theme.info')) }}
{{ f.select('select_theme', themes, __('settings.theme'), current_theme) }} {{ f.select('select_theme', __('settings.theme'), themes, {
'selected': current_theme,
}) }}
{{ f.submit(__('form.save')) }} {{ f.submit(__('form.save')) }}
</div> </div>
</div> </div>