Skip to content

Commit

Permalink
feat(form): section display mode
Browse files Browse the repository at this point in the history
  • Loading branch information
btry committed Jun 23, 2022
1 parent ae994a1 commit 544e097
Show file tree
Hide file tree
Showing 11 changed files with 326 additions and 1 deletion.
12 changes: 12 additions & 0 deletions css/print_form.css
Original file line number Diff line number Diff line change
Expand Up @@ -133,3 +133,15 @@ label[for] {
height:16px;
width:16px;
}

#plugin_formcreator_form.plugin_formcreator_form li.plugin_formcreator_section {
position: inherit;
top: inherit;
left: inherit;
display: inherit !important;
}

#plugin_formcreator_form.plugin_formcreator_form li.plugin_formcreator_section .next_button,
#plugin_formcreator_form.plugin_formcreator_form li.plugin_formcreator_section .previous_button {
display: none;
}
22 changes: 22 additions & 0 deletions css/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -225,12 +225,34 @@
list-style-type: none;
text-align: left;
padding-left: 0;
overflow: hidden;
}

[data-itemtype = "PluginFormcreatorQuestion"]:not([hidden]), .plugin_formcreator_gap {
vertical-align: top;
display: inline-block;
}

li.plugin_formcreator_section {
position: relative;
width: 100%;
top: 0;
left: 0;
transition-property: left;
transition-duration: 0.3s;
}

.plugin_formcreator_section_navigate {
padding-bottom: 8px;
.previous_button {
margin-left: 8px;
float: inherit;
}

.next_button {
float: right;
}
}
}

.form_answer h1 {
Expand Down
39 changes: 38 additions & 1 deletion inc/form.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ class PluginFormcreatorForm extends CommonDBTM implements
const VALIDATION_USER = 1;
const VALIDATION_GROUP = 2;

const SECTION_DISPLAY_VERTICAL_STACK = 0;
const SECTION_DISPLAY_WIZARD = 1;
const SECTION_DISPLAY_ACCORDION = 2;

public static function getEnumAccessType() {
return [
self::ACCESS_PUBLIC => __('Public access', 'formcreator'),
Expand All @@ -69,6 +73,14 @@ public static function getEnumAccessType() {
];
}

public static function getEnumSectionDisplayMode() {
return [
self::SECTION_DISPLAY_VERTICAL_STACK => __('Vertical stack', 'formcreator'),
self::SECTION_DISPLAY_WIZARD => __('Wizard', 'formcreator'),
self::SECTION_DISPLAY_ACCORDION => __('Accordion', 'formcreator'),
];
}

public static function getEnumShowRule() : array {
return PluginFormcreatorCondition::getEnumShowRule();
}
Expand Down Expand Up @@ -958,7 +970,20 @@ public function displayUserForm() : void {
}
$formanswer = new PluginFormcreatorFormAnswer();
$formanswer->loadAnswersFromSession();
TemplateRenderer::getInstance()->display('@formcreator/pages/userform.html.twig', [

switch ($this->fields['section_display_mode']) {
default:
$template = '@formcreator/pages/userform_stack.html.twig';
break;
case self::SECTION_DISPLAY_WIZARD :
$template = '@formcreator/pages/userform_wizard.html.twig';
break;
case self::SECTION_DISPLAY_ACCORDION :
$template = '@formcreator/pages/userform_acordion.html.twig';
break;
}

TemplateRenderer::getInstance()->display($template, [
'item' => $this,
'options' => [
'columns' => PluginFormcreatorSection::COLUMNS,
Expand Down Expand Up @@ -2572,4 +2597,16 @@ public function getExtraHeader(): string {

return $extra_header;
}

/**
* Show a section display mode dropdown
*
* @param string $name
* @param array $options
* @return void
*/
public static function dropdownSectionDisplayMode(string $name, array $options): void {
$modes = self::getEnumSectionDisplayMode();
Dropdown::showFromArray($name, $modes, $options);
}
}
20 changes: 20 additions & 0 deletions inc/section.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,26 @@ public static function getSectionsFromForm($formId): \Generator {
}
}

/**
* Counts sections in a form
* @param int $formId ID of a form
* @return int
*/
public static function getSectionsCountFromForm($formId): int {
global $DB;

$count = $DB->request([
'COUNT' => 'c',
'FROM' => self::getTable(),
'WHERE' => [
'plugin_formcreator_forms_id' => $formId
],
'ORDER' => 'order ASC'
])->current();

return $count['c'];
}

public function showForm($ID, $options = []) {
$this->initForm($ID, $options);
$options['candel'] = false;
Expand Down
1 change: 1 addition & 0 deletions install/mysql/plugin_formcreator_empty.sql
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ CREATE TABLE IF NOT EXISTS `glpi_plugin_formcreator_forms` (
`show_rule` int(11) NOT NULL DEFAULT '1' COMMENT 'Conditions setting to show the submit button',
`formanswer_name` varchar(255) NOT NULL DEFAULT '',
`is_visible` tinyint NOT NULL DEFAULT 1,
`section_display_mode` int(11) NOT NULL DEFAULT '0',
`uuid` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
INDEX `entities_id` (`entities_id`),
Expand Down
6 changes: 6 additions & 0 deletions install/upgrade_to_2.14.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ public function upgrade(Migration $migration) {
$this->addRights();
$this->addPropertiesToCategories();
$this->addTargetActorUnicity();
$this->addSectionDisplayMode();
}

public function addTtoToIssues() {
Expand Down Expand Up @@ -131,4 +132,9 @@ public function addTargetActorUnicity() {
// Set unicity
$this->migration->addKey($table, $unicity, 'unicity', 'UNIQUE');
}

public function addSectionDisplayMode() {
$table = (new DBUtils())->getTableForItemType(PluginFormcreatorForm::class);
$this->migration->addField($table, 'section_display_mode', 'integer', ['after' => 'is_visible']);
}
}
21 changes: 21 additions & 0 deletions templates/components/form/fields_macros.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -324,3 +324,24 @@
{% endset %}
{{ fields.field(name, field, label, options) }}
{% endmacro %}

{% macro dropdownSectionDisplayMode(name, value, label = '', options = {}) %}
{% import 'components/form/fields_macros.html.twig' as fields %}
{% set options = {'rand': random()}|merge(options) %}

{% if options.disabled %}
{% set options = options|merge({specific_tags: {'disabled': 'disabled'}}) %}
{% endif %}
{% if options.fields_template.isMandatoryField(name) %}
{% set options = {'specific_tags': {'required': true}}|merge(options) %}
{% endif %}

{% set field %}
{% do call('PluginFormcreatorForm::dropdownSectionDisplayMode', [name, {
'value': value,
'rand': rand,
'width': '100%'
}|merge(options)]) %}
{% endset %}
{{ fields.field(name, field, label, options) }}
{% endmacro %}
2 changes: 2 additions & 0 deletions templates/pages/form.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -98,4 +98,6 @@
{% set visible = item.fields['is_visible'] %}
{% endif %}
{{ fields.dropdownYesNo('is_visible', visible, __('Visible', 'formcreator'), { 'add_field_html': tooltip }) }}

{{ formcreatorFields.dropdownSectionDisplayMode('section_display_mode', item.fields['section_display_mode'], __('Section display mode', 'formcreator')) }}
{% endblock %}
File renamed without changes.
194 changes: 194 additions & 0 deletions templates/pages/userform_wizard.html.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
{#
# ---------------------------------------------------------------------
# Formcreator is a plugin which allows creation of custom forms of
# easy access.
# ---------------------------------------------------------------------
# LICENSE
#
# This file is part of Formcreator.
#
# Formcreator is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# Formcreator is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Formcreator. If not, see <http://www.gnu.org/licenses/>.
# ---------------------------------------------------------------------
# @copyright Copyright © 2011 - 2021 Teclib'
# @license http://www.gnu.org/licenses/gpl.txt GPLv3+
# @link https://github.com/pluginsGLPI/formcreator/
# @link https://pluginsglpi.github.io/formcreator/
# @link http://plugins.glpi-project.org/#/plugin/formcreator
# ---------------------------------------------------------------------
#}

{% import 'components/form/fields_macros.html.twig' as fields %}

<style>
{% set widthPercent = 100 / options.columns %}
{% for i in range(1, options.columns ) %}
{% set width = i * widthPercent %}
#plugin_formcreator_form.plugin_formcreator_form [data-itemtype = "PluginFormcreatorQuestion"][gs-w="{{ i }}"],
#plugin_formcreator_form.plugin_formcreator_form .plugin_formcreator_gap[gs-w="{{ i }}"] {
min-width: {{ widthPercent }}%;
width: {{ width }}%;
margin-left: -0.25em;
}
{% endfor %}
</style>

<div class="asset">
{% set formName = 'plugin_formcreator_form' %}
<form name="{{ formName }}" method="post" role="form" enctype="multipart/form-data" class="plugin_formcreator_form" action={{ item.getFormURL() }} id="plugin_formcreator_form" data-itemtype="PluginFormcreatorForm" data-id="{{ item.fields['id'] }}">
<h1 class='form-title'>
{{ __(item.fields['name'], options.domain) }}
<i class="fas fa-print" style="cursor: pointer;" onclick="window.print();"></i>
</h1>
{% if item.fields['content'] != '' or item.getExtraHeader() != "" %}
<div class="form_header">
{{ __(item.fields['content'], options.domain)|safe_html }}
{{ item.getExtraHeader()|safe_html }}
</div>
{% endif %}
<ol>

<script type="text/javascript">
function plugin_formcreator_wizard_next(target) {
var current = $(target.closest('li.plugin_formcreator_section'));
var next = current.next('li.plugin_formcreator_section');
if (next.length < 1) {
return;
}
next.css('left', '100%');
next.show();
current.css('left', '-100%');
next.css('left', '0');
current.hide();
}
function plugin_formcreator_wizard_prev(target) {
var current = $(target.closest('li.plugin_formcreator_section'));
var prev = current.prev('li.plugin_formcreator_section');
if (prev.length < 1) {
return;
}
prev.css('left', '-100%');
prev.show();
current.css('left', '100%');
prev.css('left', '0');
current.hide();
}
</script>

{% set sections = call('PluginFormcreatorSection::getSectionsFromForm', [
item.fields['id']
]) %}
{% set sectionsCount = call('PluginFormcreatorSection::getSectionsCountFromForm', [
item.fields['id']
]) %}
{% set currentSection = 0 %}
{% for section in sections %}
{% set currentSection = currentSection + 1 %}
{% set sectionId = section.fields['id'] %}
<li class="card plugin_formcreator_section plugin_formcreator_section_wizard" data-itemtype="PluginFormcreatorSection" data-id={{ sectionId }} >
<div class="card-header">
<h2 class="card-title">
{% if section.fields['name'] == '' %}
({{ sectionId }})
{% else %}
{{ __(section.fields['name'], options.domain) }}
{% endif %}
</h2>
</div>
<div class="card-body">
{% set lastQuestion = null %}
{% set questions = call('PluginFormcreatorQuestion::getQuestionsFromSection', [
sectionId
]) %}
{% for question in questions %}
{% if not (lastQuestion is null) %}
{% if lastQuestion.fields['row'] < question.fields['row'] %}
<div class="plugin_formcreator_newRow"></div>
{% else %}
{% set x = lastQuestion.fields['col'] + lastQuestion.fields['width'] %}
{% set width = question.fields['col'] - x %}
{% if x < question.fields['col'] %}
<div class="plugin_formcreator_gap" gs-x="{{ x }}" gs-w="{{ width }}"></div>
{% endif %}
{% endif %}
{% endif %}
{% if not options.public or question.getSubField().isPublicFormCompatible() %}
{% set sessionData = session('formcreator') %}
{{ question.getRenderedHtml(options.domain, true, options.formanswer)|raw }}
{% endif %}
{% set lastQuestion = question %}
{% endfor %}
</div>

{% if currentSection == sectionsCount %}
{% if options.use_captcha %}
{% set captchaTime = call('time') %}
{% set catchaId = call('md5', [captchaTime ~ item.fields['id']]) %}
{% set captcha = call('PluginFormcreatorCommon::getCaptcha', [captchaId]) %}
<div id="plugin_formcreator_captcha_section">
<div class="card-header">{{ __('Are you a robot ?', 'formcreator') }}</div>
<div class="card-body"><label for="plugin_formcreator_captcha">{{ __('Are you a robot ?', 'formcreator') }}</label>
<div><i onclick="plugin_formcreator_refreshCaptcha()" class="fas fa-sync-alt"></i>&nbsp;<img src="{{ captcha['img']|raw }}">
<div style="width: 50%; float: right" class="form_field"><span class="no-wrap">
{{ fields.textField('plugin_formcreator_captcha', '', '', { 'no_label': true}) }}
{{ fields.hiddenField('plugin_formcreator_captcha_id', captchaId) }}
</div>
</div>
</div>
</div>
{% endif %}

{{ call('PluginFormcreatorForm_Validator::dropdownValidator', [
item
])|raw }}
{% endif %}

<div class='plugin_formcreator_section_navigate'>
{% if currentSection > 1%}
<button class="btn btn-outline-secondary me-2 previous_button" type="button" name="action" value="previous" onclick="plugin_formcreator_wizard_prev(this)">
<i class="fa-solid fa-circle-left"></i>
<span>{{ _x('button', 'Previous') }}</span>
</button>
{% else %}
{% endif %}
{% if currentSection < sectionsCount %}
<button class="btn btn-primary me-2 next_button" type="button" name="action" value="next" onclick="plugin_formcreator_wizard_next(this)">
<i class="fa-solid fa-circle-right"></i>
<span>{{ _x('button', 'Next') }}</span>
</button>
{% else %}
{{ call('Html::submit', [
__('Send'),
{'name': 'submit_formcreator',
'class': 'btn btn-primary me-2 next_button',
'icon': 'far fa-save'}
])|raw }}
{% endif %}
</div>
</li>
{% endfor %}
</ol>
<script>
$(
function() {
$('#plugin_formcreator_form.plugin_formcreator_form li.plugin_formcreator_section').hide();
$('#plugin_formcreator_form.plugin_formcreator_form li.plugin_formcreator_section:first').show();
plugin_formcreator.showFields($("form[name='{{ formName }}']"));
}
)
</script>

{{ fields.hiddenField('plugin_formcreator_forms_id', item.fields['id']) }}
<input type="hidden" name="_glpi_csrf_token" value="{{ csrf_token() }}" />
</form>
</div>
Loading

0 comments on commit 544e097

Please sign in to comment.