mirror of
https://github.com/Combodo/iTop.git
synced 2026-04-23 10:38:45 +02:00
poc form SDK (extends to form)
This commit is contained in:
@@ -79,10 +79,13 @@ const Collection = function(oForm, objectFormUrl){
|
||||
);
|
||||
|
||||
// create item element
|
||||
const item = oToolkit.createElementFromHtml(text);
|
||||
const fragment = oToolkit.createElementFromHtml(text);
|
||||
collectionHolder.appendChild(fragment);
|
||||
|
||||
// form handling
|
||||
const item = collectionHolder.querySelector('tr:last-child');
|
||||
listenRemoveItem(item);
|
||||
oForm.handleElement(item);
|
||||
collectionHolder.appendChild(item);
|
||||
|
||||
// store new index
|
||||
collectionHolder.dataset.index++;
|
||||
|
||||
116
js/DI/dynamic.js
Normal file
116
js/DI/dynamic.js
Normal file
@@ -0,0 +1,116 @@
|
||||
/**
|
||||
* Dynamics handling.
|
||||
*
|
||||
* @returns {{handleElement: handleElement}}
|
||||
* @constructor
|
||||
*/
|
||||
const Dynamic = function(){
|
||||
|
||||
const aSelectors = {
|
||||
dataHideWhen: '[data-hide-when]',
|
||||
dataDisableWhen: '[data-disable-when]',
|
||||
dataAttCode: '[data-att-code="{0}"]',
|
||||
dataBlockContainer: '[data-block="container"]',
|
||||
};
|
||||
|
||||
/**
|
||||
* hideEmptyContainers.
|
||||
*
|
||||
* The purpose of this function is to hide empty containers.
|
||||
* Ex: FieldSetType with no children
|
||||
*
|
||||
*/
|
||||
function hideEmptyContainers(oElement){
|
||||
$('.combodo-field-set', oElement).each(function(){
|
||||
$(this).parent().toggle($(this).children().length !== 0);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* initDynamicsInvisible.
|
||||
*
|
||||
* @param oElement
|
||||
*/
|
||||
function initDynamicsInvisible(oElement){
|
||||
|
||||
// get all dynamic hide fields
|
||||
const aInvisibleFields = oElement.querySelectorAll(aSelectors.dataHideWhen);
|
||||
|
||||
// iterate throw fields...
|
||||
aInvisibleFields.forEach(function (oInvisibleField) {
|
||||
|
||||
// retrieve condition
|
||||
const aHideWhenCondition = JSON.parse(oInvisibleField.dataset.hideWhen);
|
||||
|
||||
// retrieve condition data
|
||||
const oHideWhenElement = oElement.querySelector(String.format(aSelectors.dataAttCode, aHideWhenCondition.att_code));
|
||||
|
||||
// initial hidden state
|
||||
oInvisibleField.closest(aSelectors.dataBlockContainer).hidden = (oHideWhenElement.value === aHideWhenCondition.value);
|
||||
|
||||
// listen for changes
|
||||
oHideWhenElement.addEventListener('change', (e) => {
|
||||
oInvisibleField.closest(aSelectors.dataBlockContainer).hidden = (e.target.value === aHideWhenCondition.value);
|
||||
oInvisibleField.closest(aSelectors.dataBlockContainer).style.visibility = (e.target.value === aHideWhenCondition.value) ? 'hidden' : '';
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* initDynamicsDisable.
|
||||
*
|
||||
* @param oElement
|
||||
*/
|
||||
function initDynamicsDisable(oElement){
|
||||
|
||||
// get all dynamic hide fields
|
||||
const aDisabledFields = oElement.querySelectorAll(aSelectors.dataDisableWhen);
|
||||
|
||||
// iterate throw fields...
|
||||
aDisabledFields.forEach(function (oDisabledField) {
|
||||
|
||||
// retrieve condition
|
||||
const aDisableWhenCondition = JSON.parse(oDisabledField.dataset.disableWhen);
|
||||
|
||||
// retrieve condition data
|
||||
const oDisableWhenElement = oElement.querySelector(`[data-att-code="${aDisableWhenCondition.att_code}"]`);
|
||||
|
||||
// initial disabled state
|
||||
oDisabledField.closest(aSelectors.dataBlockContainer).disabled = (oDisableWhenElement.value === aDisableWhenCondition.value);
|
||||
|
||||
// listen for changes
|
||||
oDisableWhenElement.addEventListener('change', (e) => {
|
||||
oDisabledField.closest(aSelectors.dataBlockContainer).disabled = (e.target.value === aDisableWhenCondition.value);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* handleElement.
|
||||
*
|
||||
* @param element
|
||||
*/
|
||||
function handleElement(element){
|
||||
hideEmptyContainers(element);
|
||||
initDynamicsInvisible(element);
|
||||
initDynamicsDisable(element);
|
||||
}
|
||||
|
||||
return {
|
||||
handleElement,
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,17 +2,16 @@
|
||||
* Forms handling.
|
||||
*
|
||||
* @param oWidget
|
||||
* @param oDynamic
|
||||
* @returns {{handleElement: handleElement}}
|
||||
* @constructor
|
||||
*/
|
||||
const Form = function(oWidget){
|
||||
const Form = function(oWidget, oDynamic){
|
||||
|
||||
const DEPENDS_ON_SEPARATOR = ' ';
|
||||
|
||||
const aSelectors = {
|
||||
dataDependsOn: '[data-depends-on]',
|
||||
dataHideWhen: '[data-hide-when]',
|
||||
dataDisableWhen: '[data-disable-when]',
|
||||
dataBlockContainer: '[data-block="container"]',
|
||||
dataAttCode: '[data-att-code="{0}"]'
|
||||
};
|
||||
@@ -261,11 +260,9 @@ const Form = function(oWidget){
|
||||
* @param element
|
||||
*/
|
||||
function handleElement(element){
|
||||
hideEmptyContainers(element);
|
||||
initDependencies(element);
|
||||
initDynamicsInvisible(element);
|
||||
initDynamicsDisable(element);
|
||||
oWidget.handleElement(element);
|
||||
oDynamic.handleElement(element);
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
34
sources/DI/Controller/ConfigurationController.php
Normal file
34
sources/DI/Controller/ConfigurationController.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Combodo\iTop\DI\Controller;
|
||||
|
||||
use Combodo\iTop\DI\Form\Type\Compound\ConfigurationType;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
/**
|
||||
* Configuration controller.
|
||||
*
|
||||
*/
|
||||
class ConfigurationController extends AbstractController
|
||||
{
|
||||
|
||||
/**
|
||||
* @Route("/configuration/edit", name="configuration_edit")
|
||||
*/
|
||||
public function configurationEdit(Request $request) : Response
|
||||
{
|
||||
// create object form
|
||||
$oForm = $this->createForm(ConfigurationType::class, []);
|
||||
|
||||
// handle HTTP request
|
||||
$oForm->handleRequest($request);
|
||||
|
||||
// return object form
|
||||
return $this->renderForm('DI/configuration/edit.html.twig', [
|
||||
'form' => $oForm
|
||||
]);
|
||||
}
|
||||
}
|
||||
31
sources/DI/Controller/DefaultController.php
Normal file
31
sources/DI/Controller/DefaultController.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Combodo\iTop\DI\Controller;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
/**
|
||||
* Default controller.
|
||||
*
|
||||
*/
|
||||
class DefaultController extends AbstractController
|
||||
{
|
||||
/**
|
||||
* @Route ("/", name="root")
|
||||
*/
|
||||
public function root(): Response
|
||||
{
|
||||
return $this->redirectToRoute('home');
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route ("/home", name="home")
|
||||
*/
|
||||
public function home(): Response
|
||||
{
|
||||
return $this->render('DI/home.html.twig');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace Combodo\iTop\DI\Controller;
|
||||
|
||||
use Combodo\iTop\DI\Form\Type\Compound\ConfigurationType;
|
||||
use Combodo\iTop\DI\Form\Type\Compound\PartialObjectType;
|
||||
use Combodo\iTop\DI\Form\Type\Compound\ObjectType;
|
||||
use Combodo\iTop\DI\Services\ObjectService;
|
||||
@@ -15,25 +14,14 @@ use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Stopwatch\Stopwatch;
|
||||
|
||||
class Controller extends AbstractController
|
||||
/**
|
||||
* Object controller.
|
||||
*
|
||||
*/
|
||||
class ObjectController extends AbstractController
|
||||
{
|
||||
/**
|
||||
* @Route ("/", name="root")
|
||||
*/
|
||||
public function root(): Response
|
||||
{
|
||||
return $this->redirectToRoute('home');
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route ("/home", name="home")
|
||||
*/
|
||||
public function home(): Response
|
||||
{
|
||||
return $this->render('DI/home.html.twig');
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route ("/{class<\w+>}/{id<\d+>}/view", name="object_view")
|
||||
@@ -83,7 +71,7 @@ class Controller extends AbstractController
|
||||
{
|
||||
// retrieve object
|
||||
try{
|
||||
$oObject= $oObjectService->getObject($class, $id);
|
||||
$oObject = $oObjectService->getObject($class, $id);
|
||||
}
|
||||
catch(Exception $e){
|
||||
throw $this->createNotFoundException("The $class $id does not exist");
|
||||
@@ -103,15 +91,19 @@ class Controller extends AbstractController
|
||||
// submitted and valid
|
||||
if ($oForm->isSubmitted() && $oForm->isValid()) {
|
||||
|
||||
// retrieve object
|
||||
$oObject = $oForm->getData();
|
||||
|
||||
try {
|
||||
|
||||
// handle link set (apply DbInsert, DbDelete, DbUpdate) could be automatic ?
|
||||
$oObjectService->handleLinkSetDB($oObject);
|
||||
|
||||
// save object
|
||||
$oObject->DBUpdate();
|
||||
if($id === 0){
|
||||
$id = $oObject->DBInsert();
|
||||
}
|
||||
else{
|
||||
$oObject->DBUpdate();
|
||||
}
|
||||
|
||||
}
|
||||
catch(Exception $e){
|
||||
throw new HttpException(500, 'Error while trying to save object');
|
||||
@@ -141,7 +133,7 @@ class Controller extends AbstractController
|
||||
{
|
||||
// retrieve object
|
||||
try{
|
||||
$oObject= $oObjectService->getObject($class, $id);
|
||||
$oObject = $oObjectService->getObject($class, $id);
|
||||
}
|
||||
catch(Exception $e){
|
||||
throw $this->createNotFoundException("The $class $id does not exist");
|
||||
@@ -168,9 +160,6 @@ class Controller extends AbstractController
|
||||
// submitted and valid
|
||||
if ($oForm->isSubmitted() && $oForm->isValid()) {
|
||||
|
||||
// retrieve object
|
||||
$oObject = $oForm->getData();
|
||||
|
||||
try {
|
||||
// handle link set (apply DbInsert, DbDelete, DbUpdate) could be automatic ?
|
||||
$oObjectService->handleLinkSetDB($oObject);
|
||||
@@ -203,7 +192,7 @@ class Controller extends AbstractController
|
||||
{
|
||||
// retrieve object
|
||||
try{
|
||||
$oObject= $oObjectService->getObject($class, $id);
|
||||
$oObject = $oObjectService->getObject($class, $id);
|
||||
}
|
||||
catch(Exception $e){
|
||||
throw $this->createNotFoundException("The $class $id does not exist");
|
||||
@@ -233,20 +222,4 @@ class Controller extends AbstractController
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/configuration/edit", name="configuration_edit")
|
||||
*/
|
||||
public function configurationEdit(Request $request) : Response
|
||||
{
|
||||
// create object form
|
||||
$oForm = $this->createForm(ConfigurationType::class, []);
|
||||
|
||||
// handle HTTP request
|
||||
$oForm->handleRequest($request);
|
||||
|
||||
// return object form
|
||||
return $this->renderForm('DI/configuration/edit.html.twig', [
|
||||
'form' => $oForm
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -24,9 +24,6 @@
|
||||
{# JS #}
|
||||
<script src="{{ asset_js('DI/toolkit.js') }}"></script>
|
||||
<script src="{{ asset_js('DI/app.js') }}"></script>
|
||||
<script src="{{ asset_js('DI/collection.js') }}"></script>
|
||||
<script src="{{ asset_js('DI/form.js') }}"></script>
|
||||
<script src="{{ asset_js('DI/widget.js') }}"></script>
|
||||
|
||||
{# - BLOCK HEAD - #}
|
||||
{% block head %}{% endblock %}
|
||||
@@ -58,6 +55,17 @@
|
||||
<li><a class="dropdown-item" href="{{ path('object_edit', {'class': 'UserRequest', 'id': 1}) }}">UserRequest</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
New Object
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" href="{{ path('object_edit', {'class': 'Organization', 'id': 0}) }}">Organization</a></li>
|
||||
<li><a class="dropdown-item" href="{{ path('object_edit', {'class': 'Person', 'id': 0}) }}">Person</a></li>
|
||||
<li><a class="dropdown-item" href="{{ path('object_edit', {'class': 'User', 'id': 0}) }}">User</a></li>
|
||||
<li><a class="dropdown-item" href="{{ path('object_edit', {'class': 'UserRequest', 'id': 0}) }}">UserRequest</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="{{ path('configuration_edit') }}" class="nav-link">Edit Configuration</a>
|
||||
</li>
|
||||
@@ -107,7 +115,7 @@
|
||||
<script>
|
||||
|
||||
// Toolkit
|
||||
const oToolkit = new Toolkit();
|
||||
var oToolkit = new Toolkit();
|
||||
oToolkit.init();
|
||||
|
||||
// App initialization
|
||||
|
||||
@@ -6,13 +6,19 @@
|
||||
|
||||
{% block head %}
|
||||
|
||||
<script src="{{ asset_js('DI/widget.js') }}"></script>
|
||||
<script src="{{ asset_js('DI/dynamic.js') }}"></script>
|
||||
<script src="{{ asset_js('DI/form.js') }}"></script>
|
||||
<script src="{{ asset_js('DI/collection.js') }}"></script>
|
||||
<script src="{{ asset_js('DI/widget/text_widget.js') }}"></script>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block actions %}
|
||||
<a href="{{ path('object_edit', {'class': class, 'id': id - 1}) }}" class="btn btn-secondary btn {% if id <= 1 %} disabled {% endif %}"><i class="fa-solid fa-arrow-left"></i></a>
|
||||
<a href="{{ path('object_edit', {'class': class, 'id': id + 1}) }}" class="btn btn-secondary btn"><i class="fa-solid fa-arrow-right"></i></a>
|
||||
{% if id != 0 %}
|
||||
<a href="{{ path('object_edit', {'class': class, 'id': id - 1}) }}" class="btn btn-secondary btn {% if id <= 1 %} disabled {% endif %}"><i class="fa-solid fa-arrow-left"></i></a>
|
||||
<a href="{{ path('object_edit', {'class': class, 'id': id + 1}) }}" class="btn btn-secondary btn"><i class="fa-solid fa-arrow-right"></i></a>
|
||||
{% endif %}
|
||||
<button type="reset" class="btn-secondary btn" form="object_form">Reset</button>
|
||||
<button type="submit" class="btn-primary btn" form="object_form">Save</button>
|
||||
{% endblock %}
|
||||
@@ -42,10 +48,12 @@
|
||||
|
||||
{# Widget #}
|
||||
const oWidget = new Widget();
|
||||
oWidget.handleElement(document);
|
||||
|
||||
{# Dynamic #}
|
||||
const oDynamic = new Dynamic();
|
||||
|
||||
{# Form #}
|
||||
const oForm = new Form(oWidget);
|
||||
const oForm = new Form(oWidget, oDynamic);
|
||||
document.querySelectorAll('form').forEach((formEl) => {
|
||||
oForm.handleElement(formEl);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user