N°635 Portal: Forms now have 2 differents layout (display_mode), see online documentation (when released) for more information.

Note: This is a first step, some refactoring could be done soon.

SVN:trunk[4735]
This commit is contained in:
Guillaume Lajarige
2017-05-15 12:50:09 +00:00
parent 17fbc504e2
commit 50970810d2
15 changed files with 427 additions and 230 deletions

View File

@@ -1,6 +1,6 @@
<?php
// Copyright (C) 2010-2015 Combodo SARL
// Copyright (C) 2010-2017 Combodo SARL
//
// This file is part of iTop.
//
@@ -661,6 +661,7 @@ class ObjectController extends AbstractController
$aFormData['renderer'] = $oFormManager->GetRenderer();
$aFormData['object_name'] = $oFormManager->GetObject()->GetName();
$aFormData['fieldset'] = $aFieldSetData;
$aFormData['display_mode'] = (isset($aFormProperties['properties'])) ? $aFormProperties['properties']['display_mode'] : ApplicationHelper::FORM_DEFAULT_DISPLAY_MODE;
return $aFormData;
}

View File

@@ -1,10 +1,10 @@
<?php
// Copyright (C) 2010-2016 Combodo SARL
// Copyright (C) 2010-2017 Combodo SARL
//
// This file is part of iTop.
//
// iTop is free software; you can redistribute it and/or modify
// iTop is free software; you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
@@ -19,6 +19,7 @@
namespace Combodo\iTop\Portal\Form;
use Combodo\iTop\Form\Field\Field;
use \Exception;
use \Silex\Application;
use \utils;
@@ -136,7 +137,7 @@ class ObjectFormManager extends FormManager
}
/**
*
*
* @return \Silex\Application
*/
public function GetApplication()
@@ -277,7 +278,7 @@ class ObjectFormManager extends FormManager
$aJson['formmode'] = $this->sMode;
$aJson['formactionrulestoken'] = $this->sActionRulesToken;
$aJson['formproperties'] = $this->aFormProperties;
return $aJson;
}
@@ -384,12 +385,20 @@ class ObjectFormManager extends FormManager
{
$oFieldNode->setAttribute('data-form-path', $oForm->GetId());
}
// Checking if field should be displayed opened (For linked set)
// Checking if field should be displayed opened (For linked set)
if($oFieldNode->hasAttribute('data-field-opened') && ($oFieldNode->getAttribute('data-field-opened') === 'true') )
{
$aFieldsExtraData[$sFieldId]['opened'] = true;
}
// Checking field display mode
if($oFieldNode->hasAttribute('data-field-display-mode') && $oFieldNode->getAttribute('data-field-display-mode') !== '')
{
$aFieldsExtraData[$sFieldId]['display_mode'] = $oFieldNode->getAttribute('data-field-display-mode');
}
else
{
$aFieldsExtraData[$sFieldId]['display_mode'] = $this->aFormProperties['properties']['display_mode'];
}
// Settings field flags from the data-field-flags attribute
foreach (explode(' ', $sFieldFlags) as $sFieldFlag)
@@ -436,7 +445,7 @@ class ObjectFormManager extends FormManager
{
$iFieldFlags = $this->oObject->GetAttributeFlags($sAttCode);
}
// Merging flags with those from the form definition
// - only if the field if it's in fields list
if (array_key_exists($sAttCode, $aFieldsAtts))
@@ -459,12 +468,12 @@ class ObjectFormManager extends FormManager
foreach ($aFieldsAtts as $sAttCode => $iFieldFlags)
{
$oAttDef = MetaModel::GetAttributeDef(get_class($this->oObject), $sAttCode);
// Failsafe for AttributeType that would not have MakeFormField and therefore could not be used in a form
if (is_callable(get_class($oAttDef) . '::MakeFormField'))
{
$oField = $oAttDef->MakeFormField($this->oObject);
if ($this->sMode !== static::ENUM_MODE_VIEW)
{
// Field dependencies
@@ -510,7 +519,7 @@ class ObjectFormManager extends FormManager
{
// Normal field
}
// Specific operation on field
// - Field that require a transaction id
if (in_array(get_class($oField), array('Combodo\\iTop\\Form\\Field\\TextAreaField', 'Combodo\\iTop\\Form\\Field\\CaseLogField')))
@@ -546,7 +555,7 @@ class ObjectFormManager extends FormManager
if ($this->oApp !== null)
{
$oScopeOriginal = ($oField->GetSearch() !== null) ? $oField->GetSearch() : DBSearch::FromOQL($oAttDef->GetValuesDef()->GetFilterExpression());
$oScopeSearch = $this->oApp['scope_validator']->GetScopeFilterForProfiles(UserRights::ListProfiles(), $oScopeOriginal->GetClass(), UR_ACTION_READ);
if ($oScopeSearch === null)
{
@@ -638,8 +647,6 @@ class ObjectFormManager extends FormManager
$oField->SetDisplayOpened(true);
}
}
$oForm->AddField($oField);
}
else
{
@@ -648,10 +655,18 @@ class ObjectFormManager extends FormManager
->SetHidden(false)
->SetCurrentValue(get_class($oAttDef) . ' : Sorry, that AttributeType is not implemented yet.')
->SetLabel($oAttDef->GetLabel());
$oForm->AddField($oField);
}
// Setting field display mode
if(array_key_exists($sAttCode, $aFieldsExtraData) && array_key_exists('display_mode', $aFieldsExtraData[$sAttCode]))
{
$sFieldDisplayMode = ($aFieldsExtraData[$sAttCode]['display_mode'] === ApplicationHelper::FORM_ENUM_DISPLAY_MODE_COSY) ? Field::ENUM_DISPLAY_MODE_VERTICAL : Field::ENUM_DISPLAY_MODE_HORIZONTAL;
$oField->SetDisplayMode($sFieldDisplayMode);
}
$oForm->AddField($oField);
}
// Checking dependencies to ensure that all needed fields are in the form
// (This is kind of a garbage collector for dependancies)
foreach ($oForm->GetDependencies() as $sImpactedFieldId => $aDependancies)
@@ -663,7 +678,7 @@ class ObjectFormManager extends FormManager
$oAttDef = MetaModel::GetAttributeDef(get_class($this->oObject), $sDependancyFieldId);
$oField = $oAttDef->MakeFormField($this->oObject);
$oField->SetHidden(true);
$oForm->AddField($oField);
}
}
@@ -683,7 +698,7 @@ class ObjectFormManager extends FormManager
break;
}
}
// Adding attachment field
if ($bClassAllowed)
{
@@ -916,7 +931,7 @@ class ObjectFormManager extends FormManager
$aData['valid'] = false;
$aData['messages']['error'] += $this->oForm->GetErrorMessages();
}
return $aData;
}
@@ -1036,7 +1051,7 @@ class ObjectFormManager extends FormManager
}
$this->oObject->DoComputeValues();
}
// Then we retrieve properties of the form to build
if (isset($aArgs['formProperties']))
{

View File

@@ -1,6 +1,6 @@
<?php
// Copyright (C) 2010-2015 Combodo SARL
// Copyright (C) 2010-2017 Combodo SARL
//
// This file is part of iTop.
//
@@ -46,6 +46,10 @@ use \Combodo\iTop\Portal\Brick\AbstractBrick;
*/
class ApplicationHelper
{
const FORM_ENUM_DISPLAY_MODE_COSY = 'cosy';
const FORM_ENUM_DISPLAY_MODE_COMPACT = 'compact';
const FORM_DEFAULT_DISPLAY_MODE = self::FORM_ENUM_DISPLAY_MODE_COSY;
const FORM_DEFAULT_ALWAYS_SHOW_SUBMIT = false;
/**
* Loads classes from the base portal
@@ -853,7 +857,8 @@ class ApplicationHelper
// Parsing properties
$aFormProperties = array(
'always_show_submit' => false,
'display_mode' => static::FORM_DEFAULT_DISPLAY_MODE,
'always_show_submit' => static::FORM_DEFAULT_ALWAYS_SHOW_SUBMIT,
);
if($oFormNode->GetOptionalElement('properties') !== null)
{
@@ -861,6 +866,9 @@ class ApplicationHelper
{
switch($oPropertyNode->nodeName)
{
case 'display_mode':
$aFormProperties['display_mode'] = $oPropertyNode->GetText(static::FORM_DEFAULT_DISPLAY_MODE);
break;
case 'always_show_submit':
$aFormProperties['always_show_submit'] = ($oPropertyNode->GetText('false') === 'true') ? true : false;
break;

View File

@@ -2,10 +2,11 @@
{# Object brick create layout #}
{% set sFormId = (form.id is defined and form.id is not null) ? form.id : 'object_form' %}
{% set sFormClass = (form.display_mode is defined and form.display_mode is not null) ? 'form_' ~ form.display_mode : '' %}
{% set sFormIdSanitized = sFormId|replace({'-': ''}) %}
{% set tIsModal = (tIsModal is defined and tIsModal == true) ? true : false %}
<form id="{{ sFormId }}" method="POST" action="{{ form.renderer.GetEndpoint()|raw }}">
<form id="{{ sFormId }}" class="{{ sFormClass }}" method="POST" action="{{ form.renderer.GetEndpoint()|raw }}">
<input type="hidden" name="transaction_id" value="{{ form.transaction_id }}" />
<div class="form_alerts">
{% block pFormAlerts %}

View File

@@ -66,7 +66,7 @@ img {
height: auto;
}
.img-rounded {
border-radius: 6px;
border-radius: 0px;
}
.img-thumbnail {
padding: 4px;
@@ -375,7 +375,7 @@ kbd {
font-size: 90%;
color: #fff;
background-color: #333;
border-radius: 3px;
border-radius: 0px;
-webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25);
box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25);
}
@@ -1388,7 +1388,7 @@ input[type="radio"][disabled], input[type="checkbox"][disabled], input[type="rad
padding: 5px 10px;
font-size: 12px;
line-height: 1.5;
border-radius: 3px;
border-radius: 0px;
}
select.input-sm {
height: 30px;
@@ -1402,7 +1402,7 @@ textarea.input-sm, select[multiple].input-sm {
padding: 5px 10px;
font-size: 12px;
line-height: 1.5;
border-radius: 3px;
border-radius: 0px;
}
.form-group-sm select.form-control {
height: 30px;
@@ -1423,7 +1423,7 @@ textarea.input-sm, select[multiple].input-sm {
padding: 14px 16px;
font-size: 17px;
line-height: 1.33333;
border-radius: 6px;
border-radius: 0px;
}
select.input-lg {
height: 53px;
@@ -1437,7 +1437,7 @@ textarea.input-lg, select[multiple].input-lg {
padding: 14px 16px;
font-size: 17px;
line-height: 1.33333;
border-radius: 6px;
border-radius: 0px;
}
.form-group-lg select.form-control {
height: 53px;
@@ -1906,19 +1906,19 @@ a.btn.disabled, fieldset[disabled] a.btn {
padding: 14px 16px;
font-size: 17px;
line-height: 1.33333;
border-radius: 6px;
border-radius: 0px;
}
.btn-sm, .btn-group-sm > .btn {
padding: 5px 10px;
font-size: 12px;
line-height: 1.5;
border-radius: 3px;
border-radius: 0px;
}
.btn-xs, .btn-group-xs > .btn {
padding: 1px 5px;
font-size: 12px;
line-height: 1.5;
border-radius: 3px;
border-radius: 0px;
}
.btn-block {
display: block;
@@ -2271,7 +2271,7 @@ tbody.collapse.in {
padding: 14px 16px;
font-size: 17px;
line-height: 1.33333;
border-radius: 6px;
border-radius: 0px;
}
select.input-group-lg > .form-control, select.input-group-lg > .input-group-addon, select.input-group-lg > .input-group-btn > .btn {
height: 53px;
@@ -2285,7 +2285,7 @@ textarea.input-group-lg > .form-control, textarea.input-group-lg > .input-group-
padding: 5px 10px;
font-size: 12px;
line-height: 1.5;
border-radius: 3px;
border-radius: 0px;
}
select.input-group-sm > .form-control, select.input-group-sm > .input-group-addon, select.input-group-sm > .input-group-btn > .btn {
height: 30px;
@@ -2313,18 +2313,18 @@ textarea.input-group-sm > .form-control, textarea.input-group-sm > .input-group-
color: #777;
text-align: center;
background-color: #ddd;
border: 1px solid #ddd;
border: 1px solid #c7c7c7;
border-radius: 0px;
}
.input-group-addon.input-sm {
padding: 5px 10px;
font-size: 12px;
border-radius: 3px;
border-radius: 0px;
}
.input-group-addon.input-lg {
padding: 14px 16px;
font-size: 17px;
border-radius: 6px;
border-radius: 0px;
}
.input-group-addon input[type="radio"], .input-group-addon input[type="checkbox"] {
margin-top: 0;
@@ -3334,7 +3334,7 @@ a.badge:hover, a.badge:focus {
border-top-color: #dbdbdb;
}
.container .jumbotron, .container-fluid .jumbotron {
border-radius: 6px;
border-radius: 0px;
}
.jumbotron .container {
max-width: 100%;
@@ -4022,11 +4022,11 @@ a.list-group-item-danger.active, button.list-group-item-danger.active, a.list-gr
}
.well-lg {
padding: 24px;
border-radius: 6px;
border-radius: 0px;
}
.well-sm {
padding: 9px;
border-radius: 3px;
border-radius: 0px;
}
.close {
float: right;
@@ -4324,7 +4324,7 @@ button.close {
background-clip: padding-box;
border: 1px solid #ccc;
border: 1px solid rgba(0, 0, 0, 0.2);
border-radius: 6px;
border-radius: 0px;
-webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
}
@@ -4929,7 +4929,37 @@ label {
box-shadow: -1px 1px 2px rgba(0, 0, 0, 0.4);
}
/* Help blocks in forms */
.form_fields .form-group > .help-block {
.form_fields .form-group .help-block {
margin-top: 0px;
margin-bottom: 0px;
}
/* Overriding Twitter Typeahead */
.input-group span.twitter-typeahead {
height: initial;
}
.input-group span.twitter-typeahead:first-child .form-control, .input-group span.twitter-typeahead:last-child .form-control, .input-group span.twitter-typeahead .form-control {
border-radius: 0px;
}
.input-group span.twitter-typeahead .tt-suggestion.tt-cursor, .input-group span.twitter-typeahead .tt-suggestion:hover, .input-group span.twitter-typeahead .tt-suggestion:focus {
color: #fff;
background-color: #ea7d1e;
}
/* Compact form display */
.form_compact .form-group.form_group_small {
margin-bottom: 10px;
}
.form_compact .form-group.form_group_small .control-label {
margin-right: 0.5em;
}
.form_compact .form-group.form_group_small .form-control-static {
display: inline;
}
.form_compact .form-group.form_group_small .form-control {
height: 28px;
padding: 4px 5px;
font-size: 12px;
}
.form_compact .form-group.form_group_small .input-group-addon {
padding: 4px 10px;
font-size: 12px;
}

View File

@@ -2995,7 +2995,7 @@ select[multiple].input-group-sm>.input-group-btn>.btn {
color: $gray;
text-align: center;
background-color: #dddddd;
border: 1px solid #dddddd;
border: 1px solid #c7c7c7;
border-radius: $border-radius-base
}
.input-group-addon.input-sm {
@@ -6012,7 +6012,42 @@ label {
box-shadow: -1px 1px 2px rgba(0, 0, 0, 0.4);
}
/* Help blocks in forms */
.form_fields .form-group > .help-block{
.form_fields .form-group .help-block{
margin-top: 0px;
margin-bottom: 0px;
}
/* Overriding Twitter Typeahead */
.input-group span.twitter-typeahead{
height: initial;
}
.input-group span.twitter-typeahead:first-child .form-control,
.input-group span.twitter-typeahead:last-child .form-control,
.input-group span.twitter-typeahead .form-control{
border-radius: $border-radius-base;
}
.input-group span.twitter-typeahead .tt-suggestion.tt-cursor,
.input-group span.twitter-typeahead .tt-suggestion:hover,
.input-group span.twitter-typeahead .tt-suggestion:focus{
color: $btn-primary-color;
background-color: $btn-primary-bg;
}
/* Compact form display */
.form_compact .form-group.form_group_small{
margin-bottom: 10px;
.control-label{
margin-right: 0.5em;
}
.form-control-static{
display: inline;
}
.form-control{
height: 28px;
padding: 4px 5px;
font-size: 12px;
}
.input-group-addon {
padding: 4px 10px;
font-size: 12px;
}
}

View File

@@ -258,10 +258,6 @@ footer {
padding-right: 0px;
/* To align all actions on the right without indent */
}
/* Custom "glyphicons" */
.glyphicon-ext-hierarchy:before {
content: url('../img/icons/hierarchy-white-13px.png');
}
/******************/
/* Modal settings */
/******************/
@@ -853,6 +849,10 @@ table .group-actions {
color: #ea7d1e;
font-size: 0.9em;
}
/* ExternalKey */
.selectobject .input-group-addon {
cursor: pointer;
}
/* InlineImage */
.inline-image {
cursor: pointer;

View File

@@ -272,11 +272,6 @@ footer{
padding-right: 0px; /* To align all actions on the right without indent */
}
/* Custom "glyphicons" */
.glyphicon-ext-hierarchy:before {
content: url('../img/icons/hierarchy-white-13px.png');
}
/******************/
/* Modal settings */
/******************/
@@ -920,6 +915,10 @@ table .group-actions .item-action-wrapper .panel-body > p:last-child{
color: $brand-primary;
font-size: 0.9em;
}
/* ExternalKey */
.selectobject .input-group-addon{
cursor: pointer;
}
/* InlineImage */
.inline-image{
cursor: pointer;
@@ -1242,4 +1241,4 @@ table .group-actions .item-action-wrapper .panel-body > p:last-child{
/* Wiki text (hyperlinks) */
.wiki_broken_link {
text-decoration: line-through;
}
}

View File

@@ -130,8 +130,8 @@ $line-height-large: 1.3333333 !default; // extra decimals for Win 8.1 Ch
$line-height-small: 1.5 !default;
$border-radius-base: 0px !default;
$border-radius-large: 6px !default;
$border-radius-small: 3px !default;
$border-radius-large: $border-radius-base; // Default: 6px !default;
$border-radius-small: $border-radius-base; // Default: 3px !default;
//** Global color for active items (e.g., navs or dropdowns).
$component-active-color: #fff !default;