chg: [controllers] Bug fixes and usage of UI factory

pull/37/head
mokaddem 2021-01-11 16:28:07 +01:00
parent a5e3ded892
commit 974d3197e8
25 changed files with 151 additions and 122 deletions

View File

@ -36,10 +36,8 @@ class AlignmentsController extends AppController
throw new NotFoundException(__('Invalid alignment.'));
}
$individual = $this->Alignments->get($id);
if ($this->ParamHandler->isRest()) {
if ($this->ParamHandler->isRest() || $this->ParamHandler->isAjax()) {
return $this->RestResponse->viewData($individual, 'json');
} else {
}
$this->set('metaGroup', 'ContactDB');
$this->set('alignment', $individual);
@ -50,12 +48,11 @@ class AlignmentsController extends AppController
if (empty($id)) {
throw new NotFoundException(__('Invalid alignment.'));
}
$individual = $this->Alignments->get($id);
$alignment = $this->Alignments->get($id);
if ($this->request->is('post') || $this->request->is('delete')) {
if ($this->Alignments->delete($individual)) {
$message = __('Individual deleted.');
if ($this->ParamHandler->isRest()) {
$individual = $this->Alignments->get($id);
if ($this->Alignments->delete($alignment)) {
$message = __('Alignments deleted.');
if ($this->ParamHandler->isRest() || $this->ParamHandler->isAjax()) {
return $this->RestResponse->saveSuccessResponse('Alignments', 'delete', $id, 'json', $message);
} else {
$this->Flash->success($message);
@ -65,8 +62,8 @@ class AlignmentsController extends AppController
}
$this->set('metaGroup', 'ContactDB');
$this->set('scope', 'alignments');
$this->set('id', $individual['id']);
$this->set('alignment', $individual);
$this->set('id', $alignment['id']);
$this->set('alignment', $alignment);
$this->viewBuilder()->setLayout('ajax');
$this->render('/genericTemplates/delete');
}
@ -86,18 +83,20 @@ class AlignmentsController extends AppController
} else {
$alignment['organisation_id'] = $source_id;
}
if ($this->Alignments->save($alignment)) {
$alignment = $this->Alignments->save($alignment);
if ($alignment) {
$message = __('Alignment added.');
if ($this->ParamHandler->isRest()) {
$alignment = $this->Alignments->get($this->Alignments->id);
return $this->RestResponse->viewData($alignment, 'json');
} else if($this->ParamHandler->isAjax()) {
return $this->RestResponse->ajaxSuccessResponse('Alignment', 'add', $alignment, $message);
} else {
$this->Flash->success($message);
$this->redirect($this->referer());
}
} else {
$message = __('Alignment could not be added.');
if ($this->ParamHandler->isRest()) {
if ($this->ParamHandler->isRest() || $this->ParamHandler->isAjax()) {
return $this->RestResponse->saveFailResponse('Individuals', 'addAlignment', false, $message);
} else {
$this->Flash->error($message);

View File

@ -22,8 +22,9 @@ class AuthKeysController extends AppController
'contain' => ['Users'],
'exclude_fields' => ['authkey']
]);
if ($this->ParamHandler->isRest()) {
return $this->restResponsePayload;
$responsePayload = $this->CRUD->getResponsePayload();
if (!empty($responsePayload)) {
return $responsePayload;
}
$this->set('metaGroup', $this->isAdmin ? 'Administration' : 'Cerebrate');
}
@ -31,8 +32,9 @@ class AuthKeysController extends AppController
public function delete($id)
{
$this->CRUD->delete($id);
if ($this->ParamHandler->isRest()) {
return $this->restResponsePayload;
$responsePayload = $this->CRUD->getResponsePayload();
if (!empty($responsePayload)) {
return $responsePayload;
}
$this->set('metaGroup', $this->isAdmin ? 'Administration' : 'Cerebrate');
}
@ -43,8 +45,9 @@ class AuthKeysController extends AppController
$this->CRUD->add([
'displayOnSuccess' => 'authkey_display'
]);
if ($this->ParamHandler->isRest()) {
return $this->restResponsePayload;
$responsePayload = $this->CRUD->getResponsePayload();
if (!empty($responsePayload)) {
return $responsePayload;
}
$this->loadModel('Users');
$dropdownData = [

View File

@ -19,6 +19,11 @@ class EncryptionKeysController extends AppController
$this->CRUD->index([
'quickFilters' => ['encryption_key'],
'filters' => ['owner_type', 'organisation_id', 'individual_id', 'encryption_key'],
'contextFilters' => [
'fields' => [
'type'
]
],
'contain' => ['Individuals', 'Organisations']
]);
if ($this->ParamHandler->isRest()) {

View File

@ -18,15 +18,15 @@ class IndividualsController extends AppController
'filters' => ['uuid', 'email', 'first_name', 'last_name', 'position', 'Organisations.id', 'Alignments.type'],
'quickFilters' => ['uuid', 'email', 'first_name', 'last_name', 'position'],
'contextFilters' => [
'allow_all' => true,
'fields' => [
'Alignments.type'
]
],
'contain' => ['Alignments' => 'Organisations']
]);
if ($this->ParamHandler->isRest()) {
return $this->restResponsePayload;
$responsePayload = $this->CRUD->getResponsePayload();
if (!empty($responsePayload)) {
return $responsePayload;
}
$this->set('alignmentScope', 'individuals');
$this->set('metaGroup', 'ContactDB');

View File

@ -37,7 +37,6 @@ class MetaTemplatesController extends AppController
'filters' => ['name', 'uuid', 'scope', 'namespace'],
'quickFilters' => ['name', 'uuid', 'scope'],
'contextFilters' => [
'allow_all' => true,
'fields' => ['scope'],
'custom' => [
[

View File

@ -19,8 +19,9 @@ class OrganisationsController extends AppController
'quickFilters' => ['name', 'uuid', 'nationality', 'sector', 'type', 'url'],
'contain' => ['Alignments' => 'Individuals']
]);
if ($this->ParamHandler->isRest()) {
return $this->restResponsePayload;
$responsePayload = $this->CRUD->getResponsePayload();
if (!empty($responsePayload)) {
return $responsePayload;
}
$this->set('alignmentScope', 'individuals');
$this->set('metaGroup', 'ContactDB');
@ -29,8 +30,9 @@ class OrganisationsController extends AppController
public function add()
{
$this->CRUD->add();
if ($this->ParamHandler->isRest()) {
return $this->restResponsePayload;
$responsePayload = $this->CRUD->getResponsePayload();
if (!empty($responsePayload)) {
return $responsePayload;
}
$this->set('metaGroup', 'ContactDB');
}
@ -38,8 +40,9 @@ class OrganisationsController extends AppController
public function view($id)
{
$this->CRUD->view($id, ['contain' => ['Alignments' => 'Individuals']]);
if ($this->ParamHandler->isRest()) {
return $this->restResponsePayload;
$responsePayload = $this->CRUD->getResponsePayload();
if (!empty($responsePayload)) {
return $responsePayload;
}
$this->set('metaGroup', 'ContactDB');
}
@ -47,8 +50,9 @@ class OrganisationsController extends AppController
public function edit($id)
{
$this->CRUD->edit($id);
if ($this->ParamHandler->isRest()) {
return $this->restResponsePayload;
$responsePayload = $this->CRUD->getResponsePayload();
if (!empty($responsePayload)) {
return $responsePayload;
}
$this->set('metaGroup', 'ContactDB');
$this->render('add');
@ -57,8 +61,9 @@ class OrganisationsController extends AppController
public function delete($id)
{
$this->CRUD->delete($id);
if ($this->ParamHandler->isRest()) {
return $this->restResponsePayload;
$responsePayload = $this->CRUD->getResponsePayload();
if (!empty($responsePayload)) {
return $responsePayload;
}
$this->set('metaGroup', 'ContactDB');
}

View File

@ -64,8 +64,8 @@ echo $this->element('genericElements/IndexTable/index_table', [
'pull' => 'right',
'actions' => [
[
'onclick' => 'populateAndLoadModal(\'/authKeys/delete/[onclick_params_data_path]\');',
'onclick_params_data_path' => 'id',
'open_modal' => '/authKeys/delete/[onclick_params_data_path]',
'modal_params_data_path' => 'id',
'icon' => 'trash'
]
]

View File

@ -18,6 +18,10 @@ echo $this->element('genericElements/IndexTable/index_table', [
]
]
],
[
'type' => 'context_filters',
'context_filters' => $filteringContexts
],
[
'type' => 'search',
'button' => __('Filter'),
@ -60,20 +64,20 @@ echo $this->element('genericElements/IndexTable/index_table', [
'pull' => 'right',
'actions' => [
[
'onclick' => 'populateAndLoadModal(\'/encryptionKeys/view/[onclick_params_data_path]\');',
'onclick_params_data_path' => 'id',
'url' => '/encryptionKeys/view',
'url_params_data_paths' => ['id'],
'icon' => 'eye'
],
[
'onclick' => 'populateAndLoadModal(\'/encryptionKeys/edit/[onclick_params_data_path]\');',
'onclick_params_data_path' => 'id',
'open_modal' => '/encryptionKeys/edit/[onclick_params_data_path]',
'modal_params_data_path' => 'id',
'icon' => 'edit'
],
[
'onclick' => 'populateAndLoadModal(\'/encryptionKeys/delete/[onclick_params_data_path]\');',
'onclick_params_data_path' => 'id',
'open_modal' => '/encryptionKeys/delete/[onclick_params_data_path]',
'modal_params_data_path' => 'id',
'icon' => 'trash'
]
],
]
]
]);

View File

@ -72,15 +72,15 @@ echo $this->element('genericElements/IndexTable/index_table', [
'icon' => 'eye'
],
[
'onclick' => 'openModalFromURL(\'/individuals/edit/[onclick_params_data_path]\');',
'onclick_params_data_path' => 'id',
'open_modal' => '/individuals/edit/[onclick_params_data_path]',
'modal_params_data_path' => 'id',
'icon' => 'edit'
],
[
'onclick' => 'openModalFromURL(\'/individuals/delete/[onclick_params_data_path]\');',
'onclick_params_data_path' => 'id',
'open_modal' => '/individuals/delete/[onclick_params_data_path]',
'modal_params_data_path' => 'id',
'icon' => 'trash'
]
],
]
]
]);

View File

@ -56,16 +56,6 @@ echo $this->element('genericElements/IndexTable/index_table', [
'url' => '/individuals/view',
'url_params_data_paths' => ['id'],
'icon' => 'eye'
],
[
'onclick' => 'populateAndLoadModal(\'/individuals/edit/[onclick_params_data_path]\');',
'onclick_params_data_path' => 'id',
'icon' => 'edit'
],
[
'onclick' => 'populateAndLoadModal(\'/individuals/delete/[onclick_params_data_path]\');',
'onclick_params_data_path' => 'id',
'icon' => 'trash'
]
]
]

View File

@ -77,16 +77,6 @@ echo $this->element('genericElements/IndexTable/index_table', [
'url' => '/organisations/view',
'url_params_data_paths' => ['id'],
'icon' => 'eye'
],
[
'onclick' => 'populateAndLoadModal(\'/organisations/edit/[onclick_params_data_path]\');',
'onclick_params_data_path' => 'id',
'icon' => 'edit'
],
[
'onclick' => 'populateAndLoadModal(\'/organisations/delete/[onclick_params_data_path]\');',
'onclick_params_data_path' => 'id',
'icon' => 'trash'
]
]
]

View File

@ -78,15 +78,15 @@ echo $this->element('genericElements/IndexTable/index_table', [
'icon' => 'eye'
],
[
'onclick' => 'populateAndLoadModal(\'/organisations/edit/[onclick_params_data_path]\');',
'onclick_params_data_path' => 'id',
'open_modal' => '/organisations/edit/[onclick_params_data_path]',
'modal_params_data_path' => 'id',
'icon' => 'edit'
],
[
'onclick' => 'populateAndLoadModal(\'/organisations/delete/[onclick_params_data_path]\');',
'onclick_params_data_path' => 'id',
'open_modal' => '/organisations/delete/[onclick_params_data_path]',
'modal_params_data_path' => 'id',
'icon' => 'trash'
]
],
]
]
]);

View File

@ -64,15 +64,15 @@ echo $this->element('genericElements/IndexTable/index_table', [
'icon' => 'eye'
],
[
'onclick' => 'populateAndLoadModal(\'/roles/edit/[onclick_params_data_path]\');',
'onclick_params_data_path' => 'id',
'icon' => 'edit',
'open_modal' => '/roles/edit/[onclick_params_data_path]',
'modal_params_data_path' => 'id',
'icon' => 'edit'
],
[
'onclick' => 'populateAndLoadModal(\'/roles/delete/[onclick_params_data_path]\');',
'onclick_params_data_path' => 'id',
'open_modal' => '/roles/delete/[onclick_params_data_path]',
'modal_params_data_path' => 'id',
'icon' => 'trash'
]
],
]
]
]);

View File

@ -60,15 +60,15 @@ echo $this->element('genericElements/IndexTable/index_table', [
'icon' => 'eye'
],
[
'onclick' => 'populateAndLoadModal(\'/sharingGroups/edit/[onclick_params_data_path]\');',
'onclick_params_data_path' => 'id',
'open_modal' => '/sharingGroups/edit/[onclick_params_data_path]',
'modal_params_data_path' => 'id',
'icon' => 'edit'
],
[
'onclick' => 'populateAndLoadModal(\'/sharingGroups/delete/[onclick_params_data_path]\');',
'onclick_params_data_path' => 'id',
'open_modal' => '/sharingGroups/delete/[onclick_params_data_path]',
'modal_params_data_path' => 'id',
'icon' => 'trash'
]
],
]
]
]);

View File

@ -52,10 +52,10 @@ echo $this->element('genericElements/IndexTable/index_table', [
'icon' => 'eye'
],
[
'onclick' => 'populateAndLoadModal(\'/sharingGroups/removeOrg/' . h($sharing_group_id) . '/[onclick_params_data_path]\');',
'onclick_params_data_path' => 'id',
'open_modal' => '/sharingGroups/removeOrg/' . h($sharing_group_id) . '/[onclick_params_data_path]',
'modal_params_data_path' => 'id',
'icon' => 'trash'
]
],
]
]
]);

View File

@ -86,15 +86,15 @@ echo $this->element('genericElements/IndexTable/index_table', [
'icon' => 'eye'
],
[
'onclick' => 'openModalFromURL(\'/users/edit/[onclick_params_data_path]\');',
'onclick_params_data_path' => 'id',
'open_modal' => '/users/edit/[onclick_params_data_path]',
'modal_params_data_path' => 'id',
'icon' => 'edit'
],
[
'onclick' => 'openModalFromURL(\'/users/delete/[onclick_params_data_path]\');',
'onclick_params_data_path' => 'id',
'open_modal' => '/users/delete/[onclick_params_data_path]',
'modal_params_data_path' => 'id',
'icon' => 'trash'
]
],
]
]
]);

View File

@ -80,6 +80,14 @@
$action['onclick']
);
} else if (!empty($action['open_modal']) && !empty($action['modal_params_data_path'])) {
$modal_url = str_replace(
'[onclick_params_data_path]',
h(Cake\Utility\Hash::extract($row, $action['modal_params_data_path'])[0]),
$action['open_modal']
);
$reload_url = !empty($action['reload_url']) ? $action['reload_url'] : $this->Url->build(['action' => 'index']);
$action['onclick'] = sprintf('UI.openModalFromURL(\'%s\', \'%s\', \'%s\')', $modal_url, $reload_url, $tableRandomValue);
}
echo sprintf(
'<a href="%s" title="%s" aria-label="%s" %s %s class="link-unstyled"><i class="%s"></i></a> ',

View File

@ -13,10 +13,10 @@ if ($field['scope'] === 'individuals') {
h($alignment['organisation']['name'])
),
!$canRemove ? '' : sprintf(
"populateAndLoadModal(%s);",
"UI.openModalFromURL(%s);",
sprintf(
"'/alignments/delete/%s'",
$alignment['id']
h($alignment['id'])
)
)
);
@ -32,10 +32,10 @@ if ($field['scope'] === 'individuals') {
h($alignment['individual']['email'])
),
!$canRemove ? '' : sprintf(
"populateAndLoadModal(%s);",
"UI.openModalFromURL(%s);",
sprintf(
"'/alignments/delete/%s'",
$alignment['id']
h($alignment['id'])
)
)
);

View File

@ -2,7 +2,7 @@
if (!isset($data['requirement']) || $data['requirement']) {
if (!empty($data['popover_url'])) {
$onClick = sprintf(
'onClick="openModalFromURL(%s)"',
'onClick="openModalForButton(%s)"',
sprintf("'%s'", h($data['popover_url']))
);
}
@ -60,8 +60,8 @@
empty($data['fa-icon']) ? '' : sprintf(
'<i class="%s fa-%s"></i> ',
empty($data['fa-source']) ? 'fas' : h($data['fa-source']),
$data['fa-icon']
), // this has to be sanitised beforehand!
h($data['fa-icon'])
),
empty($data['html']) ? '' : $data['html'], // this has to be sanitised beforehand!
empty($data['text']) ? '' : h($data['text'])
);
@ -69,9 +69,7 @@
?>
<script>
function openModalFromURL(url) {
UI.modalFromURL(url, (data) => {
UI.reload('<?= $this->Url->build(['action' => 'index']); ?>', $('#table-container-<?= $tableRandomValue ?>'), $('#table-container-<?= $tableRandomValue ?> table.table'))
})
function openModalForButton(url) {
UI.openModalFromURL(url, '<?= $this->Url->build(['action' => 'index']); ?>', '<?= $tableRandomValue ?>')
}
</script>

View File

@ -9,8 +9,16 @@
];
$currentQuery = $this->request->getQuery();
unset($currentQuery['page'], $currentQuery['limit'], $currentQuery['sort']);
if (!empty($filteringContext['filterCondition'])) { // PHP replaces `.` by `_` when fetching the request parameter
$currentFilteringContextKey = array_key_first($filteringContext['filterCondition']);
$currentFilteringContext = [
str_replace('.', '_', $currentFilteringContextKey) => $filteringContext['filterCondition'][$currentFilteringContextKey]
];
} else {
$currentFilteringContext = $filteringContext['filterCondition'];
}
$contextArray[] = [
'active' => $currentQuery == $filteringContext['filterCondition'],
'active' => $currentQuery == $currentFilteringContext,
'isFilter' => true,
'onClick' => 'UI.reload',
'onClickParams' => [

View File

@ -19,7 +19,7 @@ if ($field['scope'] === 'individuals') {
h($alignment['organisation']['name'])
),
sprintf(
"populateAndLoadModal(%s);",
"UI.openModalFromURL(%s);",
sprintf(
"'/alignments/delete/%s'",
$alignment['id']
@ -38,7 +38,7 @@ if ($field['scope'] === 'individuals') {
h($alignment['individual']['email'])
),
sprintf(
"populateAndLoadModal(%s);",
"UI.openModalFromURL(%s);",
sprintf(
"'/alignments/delete/%s'",
$alignment['id']
@ -51,7 +51,7 @@ echo sprintf(
'<div class="alignments-list">%s</div><div class="alignments-add-container"><button class="alignments-add-button btn btn-primary btn-sm" onclick="%s">%s</button></div>',
$alignments,
sprintf(
"populateAndLoadModal('/alignments/add/%s/%s');",
"UI.openModalFromURL('/alignments/add/%s/%s');",
h($field['scope']),
h($extracted['id'])
),

View File

@ -28,6 +28,7 @@
* ]);
*
*/
$tableRandomValue = Cake\Utility\Security::randomString(8);
$listElements = '';
if (!empty($fields)) {
foreach ($fields as $field) {
@ -109,18 +110,20 @@
__('{0} view', \Cake\Utility\Inflector::singularize(\Cake\Utility\Inflector::humanize($this->request->getParam('controller')))) :
$title;
echo sprintf(
"<div>
"<div id=\"single-view-table-container-%s\">
<h2>%s</h2>
%s%s
<div class=\"px-3\">
<table class=\"table table-striped col-sm-8\">%s</table>
<table id=\"single-view-table-%s\" class=\"table table-striped col-sm-8\">%s</table>
</div>
<div id=\"metaTemplates\" class=\"col-lg-8 px-0\">%s</div>
<div id=\"accordion\">%s</div>
</div>",
$tableRandomValue,
h($title),
empty($description) ? '' : sprintf('<p>%s</p>', h($description)),
empty($description_html) ? '' : sprintf('<p>%s</p>', $description_html),
$tableRandomValue,
$listElements,
$metaTemplateTabs,
$ajaxLists

View File

@ -35,7 +35,7 @@ if (isset($menu[$metaGroup])) {
}
$active = ($scope === $this->request->getParam('controller') && $action === $this->request->getParam('action'));
if (!empty($data['popup'])) {
$link_template = '<a href="#" onClick="openModalFromURL(\'%s\')" class="list-group-item list-group-item-action %s %s pl-3 border-0 %s">%s</a>';
$link_template = '<a href="#" onClick="UI.openModalFromURL(\'%s\')" class="list-group-item list-group-item-action %s %s pl-3 border-0 %s">%s</a>';
} else {
$link_template = '<a href="%s" class="list-group-item list-group-item-action %s %s pl-3 border-0 %s">%s</a>';
}

View File

@ -45,6 +45,35 @@ class UIFactory {
})
}
/**
* Create and display a modal where the modal's content is fetched from the provided URL. Reload the table after a successful operation
* @param {string} url - The URL from which the modal's content should be fetched
* @param {string} tableId - The table ID which should be reloaded on success
* @return {Promise<Object>} Promise object resolving to the ModalFactory object
*/
openModalFromURL(url, reloadUrl=false, tableId=false) {
UI.modalFromURL(url, () => {
if (reloadUrl === false || tableId === false) { // Try to get information from the DOM
let $elligibleTable = $('table.table')
let currentModel = location.pathname.split('/')[1]
if ($elligibleTable.length == 1 && currentModel.length > 0) {
let $container = $elligibleTable.closest('div[id^="table-container-"]')
if ($container.length == 1) {
return UI.reload(`/${currentModel}/index`, $container, $elligibleTable)
} else {
$container = $elligibleTable.closest('div[id^="single-view-table-container-"]')
if ($container.length == 1) {
return UI.reload(location.pathname, $container, $elligibleTable)
}
}
}
} else {
return UI.reload(reloadUrl, $(`#table-container-${tableId}`), $(`#table-container-${tableId} table.table`))
}
location.reload()
})
}
/**
* Fetch HTML from the provided URL and override the $container's content. $statusNode allows to specify another HTML node to display the loading
* @param {string} url - The URL from which the $container's content should be fetched
@ -495,7 +524,7 @@ class ModalFactory {
this.hide()
}
})
.catch(() => {
.catch((err) => {
this.options.APIError(() => { this.hide() }, this, evt)
})
}

View File

@ -1,15 +1,3 @@
function populateAndLoadModal(url) {
$.ajax({
dataType:"html",
cache: false,
success:function (data, textStatus) {
$("#mainModal").html(data);
$("#mainModal").modal('show');
},
url:url,
});
}
function executePagination(randomValue, url) {
var target = '#table-container-' + randomValue
$.ajax({