Structure Web Application Framework
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

185 lines
7.8 KiB

{% macro message(type, content, raw=false, discreet=false) %}
<div class="message{{ ' message-discreet' if discreet }}" data-type="{{ type }}">
<i class="icon"></i>
<span class="content">
{{ content|safe if raw else content }}
</span>
</div>
{% endmacro %}
{% macro messages(flash) %}
{% set flashed = flash() %}
{% set display = 0 %}
{% for type, bag in flashed %}
{% if bag|length %}
{% set display = 1 %}
{% endif %}
{% endfor %}
{% if display %}
<div class="messages">
{% for type, bag in flashed %}
{% for content in bag %}
{{ message(type, content) }}
{% endfor %}
{% endfor %}
</div>
{% endif %}
{% endmacro %}
{% macro csrf(getCsrfToken) %}
<input type="hidden" name="csrf" value="{{ getCsrfToken() }}">
{% endmacro %}
{% macro field(_locals, type, name, value, placeholder, hint, validation_attributes='', extraData='', icon=null) %}
{% set validation = _locals.validation() %}
{% set validation = validation[name] if validation[name] or null %}
{% set previousFormData = _locals.previousFormData() %}
{% set value = previousFormData[name] or value or validation.value or '' %}
{% set prefix = _locals.getFormPrefix() | default('') %}
{% if type == 'hidden' %}
{% if validation %}
{{ message('error', validation.message) }}
{% endif %}
<input type="hidden" name="{{ name }}" value="{{ value }}">
{% else %}
<div class="form-field{{ ' inline' if type == 'checkbox' }}">
<div class="control">
{% if icon != null %}
{% if icon.startsWith('fa') %}
<i class="{{ icon }} feather icon"></i>
{% else %}
<i data-feather="{{ icon }}" class="icon"></i>
{% endif %}
{% endif %}
{% if type == 'duration' %}
<div class="input-group">
{% for f in extraData %}
<div class="time-input">
{% if previousFormData[name] %}
{% set v = value[f] %}
{% else %}
{% set v = (value % 60) if f == 's' else (((value - value % 60) / 60 % 60) if f == 'm' else ((value - value % 3600) / 3600 if f == 'h')) %}
{% endif %}
<input type="number" name="{{ name }}[{{ f }}]" id="field-{{ prefix }}{{ name }}-{{ f }}"
value="{{ v }}"
min="0" {{ 'max=60' if (f == 's' or f == 'm') }}
{{ validation_attributes }}>
<label for="field-{{ prefix }}{{ name }}-{{ f }}">{{ f }}</label>
</div>
{% endfor %}
</div>
{% elseif type == 'select' %}
<select name="{{ name }}" id="field-{{ prefix }}{{ name }}" {{ validation_attributes|safe }}>
{% for option in extraData %}
<option value="{% if option.display === undefined or option.value !== undefined %}{{ option.value | default(option) }}{% endif %}"
{{ 'selected' if value == (option.value | default(option)) }}>{{ option.display | default(option) }}</option>
{% endfor %}
</select>
<i data-feather="chevron-down"></i>
{% elseif type == 'textarea' %}
<textarea name="{{ name }}" id="field-{{ prefix }}{{ name }}"
{{ validation_attributes|safe }} value="{{ value }}">{{ value }}</textarea>
{% else %}
<input type="{{ type }}" name="{{ name }}" id="field-{{ prefix }}{{ name }}"
{% if type != 'checkbox' %} value="{{ value }}" {% endif %}
{{ 'checked' if (type == 'checkbox' and value == 'on') }}
{{ validation_attributes|safe }}>
{% endif %}
<label for="field-{{ prefix }}{{ name }}{{ '-' + extraData[0] if type == 'duration' }}">{{ placeholder }}</label>
</div>
{{ fieldError(_locals, name) }}
{% if hint %}
<div class="hint"><i data-feather="info"></i> {{ hint }}</div>
{% endif %}
</div>
{% endif %}
{% endmacro %}
{% macro fieldError(_locals, name) %}
{% set validation = _locals.validation() %}
{% set validation = validation[name] if validation[name] or null %}
{% if validation %}
<div class="error"><i data-feather="x-circle"></i> {{ validation.message }}</div>
{% endif %}
{% endmacro %}
{% macro websocket(websocketUrl, listener, reconnectOnClose = 1, checkFunction = 0) %}
<script>
document.addEventListener('DOMContentLoaded', () => {
{% if checkFunction %}
if (!{{ checkFunction }}()) return;
{% endif %}
const run = () => {
const websocket = new WebSocket('{{ websocketUrl }}');
websocket.onopen = (e) => {
console.debug('Websocket connected');
};
websocket.onmessage = (e) => {
{{ listener }}(websocket, e);
};
websocket.onerror = (e) => {
console.error('Websocket error', e);
};
websocket.onclose = (e) => {
console.debug('Websocket closed', e.code, e.reason);
{% if reconnectOnClose %}
setTimeout(run, 1000);
{% endif %}
};
};
run();
});
</script>
{% endmacro %}
{% macro paginate(pagination, routeName, contextSize) %}
{% if pagination.hasPrevious() or pagination.hasNext() %}
<nav class="pagination">
<ul>
{% if pagination.hasPrevious() %}
<li><a href="{{ route(routeName, {page: pagination.page - 1}) }}"><i data-feather="chevron-left"></i> Previous</a></li>
{% for i in pagination.previousPages(contextSize) %}
{% if i == -1 %}
<li class="ellipsis">...</li>
{% else %}
<li><a href="{{ route(routeName, {page: i}) }}">{{ i }}</a></li>
{% endif %}
{% endfor %}
{% endif %}
<li class="active"><span>{{ pagination.page }}</span></li>
{% if pagination.hasNext() %}
{% for i in pagination.nextPages(contextSize) %}
{% if i == -1 %}
<li class="ellipsis">...</li>
{% else %}
<li><a href="{{ route(routeName, {page: i}) }}">{{ i }}</a></li>
{% endif %}
{% endfor %}
<li><a href="{{ route(routeName, {page: pagination.page + 1}) }}">Next <i data-feather="chevron-right"></i></a></li>
{% endif %}
</ul>
</nav>
{% endif %}
{% endmacro %}
{% macro breadcrumb(currentPageTitle, pages=[]) %}
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
{% for page in pages %}
<li><a href="{{ page.link }}">{{ page.title }}</a></li>
{% endfor %}
<li class="active" aria-current="page">{{ currentPageTitle }}</li>
</ol>
</nav>
{% endmacro %}