chg: [component:CRUD] Improved flexibility
parent
2d26bc597f
commit
899fa27a45
|
@ -48,6 +48,23 @@ class CRUDComponent extends Component
|
||||||
$this->Controller->set('data', $data);
|
$this->Controller->set('data', $data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* getResponsePayload Returns the adaquate response payload based on the request context
|
||||||
|
*
|
||||||
|
* @return false or Array
|
||||||
|
*/
|
||||||
|
public function getResponsePayload()
|
||||||
|
{
|
||||||
|
if ($this->Controller->ParamHandler->isRest()) {
|
||||||
|
return $this->Controller->restResponsePayload;
|
||||||
|
} else if ($this->Controller->ParamHandler->isAjax() && $this->request->is(['post', 'put'])) {
|
||||||
|
if (empty($this->Controller->isFailResponse) || empty($this->Controller->ajax_with_html_on_failure)) {
|
||||||
|
return $this->Controller->ajaxResponsePayload;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private function getMetaTemplates()
|
private function getMetaTemplates()
|
||||||
{
|
{
|
||||||
|
@ -301,8 +318,9 @@ class CRUDComponent extends Component
|
||||||
if ($this->Table->delete($data)) {
|
if ($this->Table->delete($data)) {
|
||||||
$message = __('{0} deleted.', $this->ObjectAlias);
|
$message = __('{0} deleted.', $this->ObjectAlias);
|
||||||
if ($this->Controller->ParamHandler->isRest()) {
|
if ($this->Controller->ParamHandler->isRest()) {
|
||||||
$data = $this->Table->get($id);
|
$this->Controller->restResponsePayload = $this->RestResponse->viewData($data, 'json');
|
||||||
$this->Controller->restResponsePayload = $this->RestResponse->saveSuccessResponse($this->TableAlias, 'delete', $id, 'json', $message);
|
} else if ($this->Controller->ParamHandler->isAjax()) {
|
||||||
|
$this->Controller->ajaxResponsePayload = $this->Controller->RestResponse->ajaxSuccessResponse($this->ObjectAlias, 'delete', $data, $message);
|
||||||
} else {
|
} else {
|
||||||
$this->Controller->Flash->success($message);
|
$this->Controller->Flash->success($message);
|
||||||
$this->Controller->redirect($this->Controller->referer());
|
$this->Controller->redirect($this->Controller->referer());
|
||||||
|
@ -493,8 +511,17 @@ class CRUDComponent extends Component
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getFilteringContextFromField($context)
|
private function getFilteringContextFromField($field)
|
||||||
{
|
{
|
||||||
return $this->Table->find()->distinct([$context])->all()->extract($context)->toList();
|
$exploded = explode('.', $field);
|
||||||
|
if (count($exploded) > 1) {
|
||||||
|
$model = $exploded[0];
|
||||||
|
$subField = $exploded[1];
|
||||||
|
return $this->Table->{$model}->find()
|
||||||
|
->distinct([$subField])
|
||||||
|
->extract($subField)->toList();
|
||||||
|
} else {
|
||||||
|
return $this->Table->find()->distinct([$field])->all()->extract($field)->toList();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,8 +15,14 @@ class IndividualsController extends AppController
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
$this->CRUD->index([
|
$this->CRUD->index([
|
||||||
'filters' => ['uuid', 'email', 'first_name', 'last_name', 'position', 'Organisations.id'],
|
'filters' => ['uuid', 'email', 'first_name', 'last_name', 'position', 'Organisations.id', 'Alignments.type'],
|
||||||
'quickFilters' => ['uuid', 'email', 'first_name', 'last_name', 'position'],
|
'quickFilters' => ['uuid', 'email', 'first_name', 'last_name', 'position'],
|
||||||
|
'contextFilters' => [
|
||||||
|
'allow_all' => true,
|
||||||
|
'fields' => [
|
||||||
|
'Alignments.type'
|
||||||
|
]
|
||||||
|
],
|
||||||
'contain' => ['Alignments' => 'Organisations']
|
'contain' => ['Alignments' => 'Organisations']
|
||||||
]);
|
]);
|
||||||
if ($this->ParamHandler->isRest()) {
|
if ($this->ParamHandler->isRest()) {
|
||||||
|
@ -29,8 +35,9 @@ class IndividualsController extends AppController
|
||||||
public function add()
|
public function add()
|
||||||
{
|
{
|
||||||
$this->CRUD->add();
|
$this->CRUD->add();
|
||||||
if ($this->ParamHandler->isRest()) {
|
$responsePayload = $this->CRUD->getResponsePayload();
|
||||||
return $this->restResponsePayload;
|
if (!empty($responsePayload)) {
|
||||||
|
return $responsePayload;
|
||||||
}
|
}
|
||||||
$this->set('metaGroup', 'ContactDB');
|
$this->set('metaGroup', 'ContactDB');
|
||||||
}
|
}
|
||||||
|
@ -38,8 +45,9 @@ class IndividualsController extends AppController
|
||||||
public function view($id)
|
public function view($id)
|
||||||
{
|
{
|
||||||
$this->CRUD->view($id, ['contain' => ['Alignments' => 'Organisations']]);
|
$this->CRUD->view($id, ['contain' => ['Alignments' => 'Organisations']]);
|
||||||
if ($this->ParamHandler->isRest()) {
|
$responsePayload = $this->CRUD->getResponsePayload();
|
||||||
return $this->restResponsePayload;
|
if (!empty($responsePayload)) {
|
||||||
|
return $responsePayload;
|
||||||
}
|
}
|
||||||
$this->set('metaGroup', 'ContactDB');
|
$this->set('metaGroup', 'ContactDB');
|
||||||
}
|
}
|
||||||
|
@ -47,10 +55,9 @@ class IndividualsController extends AppController
|
||||||
public function edit($id)
|
public function edit($id)
|
||||||
{
|
{
|
||||||
$this->CRUD->edit($id);
|
$this->CRUD->edit($id);
|
||||||
if ($this->ParamHandler->isRest()) {
|
$responsePayload = $this->CRUD->getResponsePayload();
|
||||||
return $this->restResponsePayload;
|
if (!empty($responsePayload)) {
|
||||||
} else if($this->ParamHandler->isAjax() && $this->request->is(['post', 'put'])) {
|
return $responsePayload;
|
||||||
return $this->ajaxResponsePayload;
|
|
||||||
}
|
}
|
||||||
$this->set('metaGroup', 'ContactDB');
|
$this->set('metaGroup', 'ContactDB');
|
||||||
$this->render('add');
|
$this->render('add');
|
||||||
|
@ -59,8 +66,9 @@ class IndividualsController extends AppController
|
||||||
public function delete($id)
|
public function delete($id)
|
||||||
{
|
{
|
||||||
$this->CRUD->delete($id);
|
$this->CRUD->delete($id);
|
||||||
if ($this->ParamHandler->isRest()) {
|
$responsePayload = $this->CRUD->getResponsePayload();
|
||||||
return $this->restResponsePayload;
|
if (!empty($responsePayload)) {
|
||||||
|
return $responsePayload;
|
||||||
}
|
}
|
||||||
$this->set('metaGroup', 'ContactDB');
|
$this->set('metaGroup', 'ContactDB');
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,12 +23,9 @@ class UsersController extends AppController
|
||||||
public function add()
|
public function add()
|
||||||
{
|
{
|
||||||
$this->CRUD->add();
|
$this->CRUD->add();
|
||||||
if ($this->ParamHandler->isRest()) {
|
$responsePayload = $this->CRUD->getResponsePayload();
|
||||||
return $this->restResponsePayload;
|
if (!empty($responsePayload)) {
|
||||||
} else if ($this->ParamHandler->isAjax() && $this->request->is(['post', 'put'])) {
|
return $responsePayload;
|
||||||
if (empty($this->isFailResponse) || empty($this->ajax_with_html_on_failure)) {
|
|
||||||
return $this->ajaxResponsePayload;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
$dropdownData = [
|
$dropdownData = [
|
||||||
'role' => $this->Users->Roles->find('list', [
|
'role' => $this->Users->Roles->find('list', [
|
||||||
|
@ -78,8 +75,9 @@ class UsersController extends AppController
|
||||||
$params['fields'][] = 'role_id';
|
$params['fields'][] = 'role_id';
|
||||||
}
|
}
|
||||||
$this->CRUD->edit($id, $params);
|
$this->CRUD->edit($id, $params);
|
||||||
if ($this->ParamHandler->isRest()) {
|
$responsePayload = $this->CRUD->getResponsePayload();
|
||||||
return $this->restResponsePayload;
|
if (!empty($responsePayload)) {
|
||||||
|
return $responsePayload;
|
||||||
}
|
}
|
||||||
$dropdownData = [
|
$dropdownData = [
|
||||||
'role' => $this->Users->Roles->find('list', [
|
'role' => $this->Users->Roles->find('list', [
|
||||||
|
@ -94,11 +92,21 @@ class UsersController extends AppController
|
||||||
$this->render('add');
|
$this->render('add');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function toggle($id, $fieldName = 'disabled')
|
||||||
|
{
|
||||||
|
$this->CRUD->toggle($id, $fieldName);
|
||||||
|
$responsePayload = $this->CRUD->getResponsePayload();
|
||||||
|
if (!empty($responsePayload)) {
|
||||||
|
return $responsePayload;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function delete($id)
|
public function delete($id)
|
||||||
{
|
{
|
||||||
$this->CRUD->delete($id);
|
$this->CRUD->delete($id);
|
||||||
if ($this->ParamHandler->isRest()) {
|
$responsePayload = $this->CRUD->getResponsePayload();
|
||||||
return $this->restResponsePayload;
|
if (!empty($responsePayload)) {
|
||||||
|
return $responsePayload;
|
||||||
}
|
}
|
||||||
$this->set('metaGroup', $this->isAdmin ? 'Administration' : 'Cerebrate');
|
$this->set('metaGroup', $this->isAdmin ? 'Administration' : 'Cerebrate');
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,10 @@ echo $this->element('genericElements/IndexTable/index_table', [
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
'type' => 'context_filters',
|
||||||
|
'context_filters' => $filteringContexts
|
||||||
|
],
|
||||||
[
|
[
|
||||||
'type' => 'search',
|
'type' => 'search',
|
||||||
'button' => __('Filter'),
|
'button' => __('Filter'),
|
||||||
|
@ -68,12 +72,12 @@ echo $this->element('genericElements/IndexTable/index_table', [
|
||||||
'icon' => 'eye'
|
'icon' => 'eye'
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'onclick' => 'populateAndLoadModal(\'/individuals/edit/[onclick_params_data_path]\');',
|
'onclick' => 'openModalFromURL(\'/individuals/edit/[onclick_params_data_path]\');',
|
||||||
'onclick_params_data_path' => 'id',
|
'onclick_params_data_path' => 'id',
|
||||||
'icon' => 'edit'
|
'icon' => 'edit'
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'onclick' => 'populateAndLoadModal(\'/individuals/delete/[onclick_params_data_path]\');',
|
'onclick' => 'openModalFromURL(\'/individuals/delete/[onclick_params_data_path]\');',
|
||||||
'onclick_params_data_path' => 'id',
|
'onclick_params_data_path' => 'id',
|
||||||
'icon' => 'trash'
|
'icon' => 'trash'
|
||||||
]
|
]
|
||||||
|
|
|
@ -3,7 +3,6 @@ echo $this->element('genericElements/IndexTable/index_table', [
|
||||||
'data' => [
|
'data' => [
|
||||||
'data' => $data,
|
'data' => $data,
|
||||||
'top_bar' => [
|
'top_bar' => [
|
||||||
'pull' => 'right',
|
|
||||||
'children' => [
|
'children' => [
|
||||||
[
|
[
|
||||||
'type' => 'simple',
|
'type' => 'simple',
|
||||||
|
@ -31,6 +30,22 @@ echo $this->element('genericElements/IndexTable/index_table', [
|
||||||
'sort' => 'id',
|
'sort' => 'id',
|
||||||
'data_path' => 'id',
|
'data_path' => 'id',
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
'name' => __('Disabled'),
|
||||||
|
'sort' => 'disabled',
|
||||||
|
'data_path' => 'disabled',
|
||||||
|
'element' => 'toggle',
|
||||||
|
'url' => '/users/toggle/{{0}}',
|
||||||
|
'url_params_vars' => ['id'],
|
||||||
|
'toggle_data' => [
|
||||||
|
'editRequirement' => [
|
||||||
|
'function' => function($row, $options) {
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'skip_full_reload' => true
|
||||||
|
]
|
||||||
|
],
|
||||||
[
|
[
|
||||||
'name' => __('Username'),
|
'name' => __('Username'),
|
||||||
'sort' => 'username',
|
'sort' => 'username',
|
||||||
|
@ -71,12 +86,12 @@ echo $this->element('genericElements/IndexTable/index_table', [
|
||||||
'icon' => 'eye'
|
'icon' => 'eye'
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'onclick' => 'populateAndLoadModal(\'/users/edit/[onclick_params_data_path]\');',
|
'onclick' => 'openModalFromURL(\'/users/edit/[onclick_params_data_path]\');',
|
||||||
'onclick_params_data_path' => 'id',
|
'onclick_params_data_path' => 'id',
|
||||||
'icon' => 'edit'
|
'icon' => 'edit'
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'onclick' => 'populateAndLoadModal(\'/users/delete/[onclick_params_data_path]\');',
|
'onclick' => 'openModalFromURL(\'/users/delete/[onclick_params_data_path]\');',
|
||||||
'onclick_params_data_path' => 'id',
|
'onclick_params_data_path' => 'id',
|
||||||
'icon' => 'trash'
|
'icon' => 'trash'
|
||||||
]
|
]
|
||||||
|
|
|
@ -75,9 +75,6 @@
|
||||||
...correctOptions,
|
...correctOptions,
|
||||||
APIConfirm: (tmpApi) => {
|
APIConfirm: (tmpApi) => {
|
||||||
return submitForm(tmpApi, url)
|
return submitForm(tmpApi, url)
|
||||||
.catch(e => {
|
|
||||||
// Provide feedback inside modal?
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
UI.modal(modalOptions)
|
UI.modal(modalOptions)
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
empty($data['value']) ? '' : h($data['value'])
|
empty($data['value']) ? '' : h($data['value'])
|
||||||
);
|
);
|
||||||
echo sprintf(
|
echo sprintf(
|
||||||
'<div class="input-group" data-table-random-value="%s">%s%s</div>',
|
'<div class="input-group" data-table-random-value="%s" style="margin-left: auto;">%s%s</div>',
|
||||||
h($tableRandomValue),
|
h($tableRandomValue),
|
||||||
$input,
|
$input,
|
||||||
$button
|
$button
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
<?php
|
<?php
|
||||||
$groups = '';
|
$groups = '';
|
||||||
|
$hasGroupSearch = false;
|
||||||
foreach ($data['children'] as $group) {
|
foreach ($data['children'] as $group) {
|
||||||
$groups .= $this->element('/genericElements/ListTopBar/group_' . (empty($group['type']) ? 'simple' : h($group['type'])), array('data' => $group, 'tableRandomValue' => $tableRandomValue));
|
$groups .= $this->element('/genericElements/ListTopBar/group_' . (empty($group['type']) ? 'simple' : h($group['type'])), array('data' => $group, 'tableRandomValue' => $tableRandomValue));
|
||||||
|
$hasGroupSearch = $hasGroupSearch || (!empty($group['type']) && $group['type'] == 'search');
|
||||||
}
|
}
|
||||||
$tempClass = "btn-toolbar";
|
$tempClass = "btn-toolbar";
|
||||||
if (count($data['children']) > 1) {
|
if (count($data['children']) > 1 && !$hasGroupSearch) {
|
||||||
$tempClass .= ' justify-content-between';
|
$tempClass .= ' justify-content-between';
|
||||||
} else if (!empty($data['pull'])) {
|
} else if (!empty($data['pull'])) {
|
||||||
$tempClass .= ' float-' . h($data['pull']);
|
$tempClass .= ' float-' . h($data['pull']);
|
||||||
|
|
|
@ -35,7 +35,7 @@ if (isset($menu[$metaGroup])) {
|
||||||
}
|
}
|
||||||
$active = ($scope === $this->request->getParam('controller') && $action === $this->request->getParam('action'));
|
$active = ($scope === $this->request->getParam('controller') && $action === $this->request->getParam('action'));
|
||||||
if (!empty($data['popup'])) {
|
if (!empty($data['popup'])) {
|
||||||
$link_template = '<a href="#" onClick="populateAndLoadModal(\'%s\')" class="list-group-item list-group-item-action %s %s pl-3 border-0 %s">%s</a>';
|
$link_template = '<a href="#" onClick="openModalFromURL(\'%s\')" class="list-group-item list-group-item-action %s %s pl-3 border-0 %s">%s</a>';
|
||||||
} else {
|
} else {
|
||||||
$link_template = '<a href="%s" class="list-group-item list-group-item-action %s %s pl-3 border-0 %s">%s</a>';
|
$link_template = '<a href="%s" class="list-group-item list-group-item-action %s %s pl-3 border-0 %s">%s</a>';
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
<?= $this->Form->postLink(
|
<?= $this->Form->postLink(
|
||||||
'Delete',
|
'Delete',
|
||||||
['action' => 'delete', $id],
|
['action' => 'delete', $id],
|
||||||
['class' => 'btn btn-primary button-execute']
|
['class' => 'btn btn-primary button-execute', 'id' => 'submitButton']
|
||||||
)
|
)
|
||||||
?>
|
?>
|
||||||
<button type="button" class="btn btn-secondary cancel-button" data-dismiss="modal"><?= __('Cancel') ?></button>
|
<button type="button" class="btn btn-secondary cancel-button" data-dismiss="modal"><?= __('Cancel') ?></button>
|
||||||
|
|
|
@ -114,3 +114,8 @@
|
||||||
color: inherit;
|
color: inherit;
|
||||||
text-decoration: inherit;
|
text-decoration: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.btn-group > .btn:last-of-type:not(.dropdown-toggle), .btn-group > .btn-group:not(:last-of-type) > .btn {
|
||||||
|
border-top-right-radius: 0.2rem;
|
||||||
|
border-bottom-right-radius: 0.2rem;
|
||||||
|
}
|
|
@ -142,7 +142,7 @@ class AJAXApi {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(url, AJAXApi.genericRequestConfigGET);
|
const response = await fetch(url, AJAXApi.genericRequestConfigGET);
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error('Network response was not ok')
|
throw new Error(`Network response was not ok. \`${response.statusText}\``)
|
||||||
}
|
}
|
||||||
const dataHtml = await response.text();
|
const dataHtml = await response.text();
|
||||||
this.provideFeedback({
|
this.provideFeedback({
|
||||||
|
@ -179,7 +179,7 @@ class AJAXApi {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(url, AJAXApi.genericRequestConfigGET);
|
const response = await fetch(url, AJAXApi.genericRequestConfigGET);
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error('Network response was not ok')
|
throw new Error(`Network response was not ok. \`${response.statusText}\``)
|
||||||
}
|
}
|
||||||
const formHtml = await response.text();
|
const formHtml = await response.text();
|
||||||
let tmpNode = document.createElement("div");
|
let tmpNode = document.createElement("div");
|
||||||
|
@ -231,7 +231,7 @@ class AJAXApi {
|
||||||
};
|
};
|
||||||
const response = await fetch(form.action, options);
|
const response = await fetch(form.action, options);
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error('Network response was not ok')
|
throw new Error(`Network response was not ok. \`${response.statusText}\``)
|
||||||
}
|
}
|
||||||
const clonedResponse = response.clone()
|
const clonedResponse = response.clone()
|
||||||
try {
|
try {
|
||||||
|
@ -268,7 +268,7 @@ class AJAXApi {
|
||||||
}, true, feedbackShown);
|
}, true, feedbackShown);
|
||||||
toReturn = Promise.reject(error);
|
toReturn = Promise.reject(error);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) { // -> probably not useful
|
||||||
toReturn = Promise.reject(error);
|
toReturn = Promise.reject(error);
|
||||||
} finally {
|
} finally {
|
||||||
if (!skipRequestHooks) {
|
if (!skipRequestHooks) {
|
||||||
|
|
|
@ -503,7 +503,7 @@ class ModalFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Attach the submission click listener for modals that have been generated by raw HTML */
|
/** Attach the submission click listener for modals that have been generated by raw HTML */
|
||||||
findSubmitButtonAndAddListener() {
|
findSubmitButtonAndAddListener(clearOnclick=true) {
|
||||||
const $submitButton = this.$modal.find('.modal-footer #submitButton')
|
const $submitButton = this.$modal.find('.modal-footer #submitButton')
|
||||||
const formID = $submitButton.data('form-id')
|
const formID = $submitButton.data('form-id')
|
||||||
let $form
|
let $form
|
||||||
|
@ -512,6 +512,9 @@ class ModalFactory {
|
||||||
} else {
|
} else {
|
||||||
$form = this.$modal.find('form')
|
$form = this.$modal.find('form')
|
||||||
}
|
}
|
||||||
|
if (clearOnclick) {
|
||||||
|
$submitButton[0].removeAttribute('onclick')
|
||||||
|
}
|
||||||
|
|
||||||
this.options.APIConfirm = (tmpApi) => {
|
this.options.APIConfirm = (tmpApi) => {
|
||||||
tmpApi.mergeOptions({forceHTMLOnValidationFailure: true})
|
tmpApi.mergeOptions({forceHTMLOnValidationFailure: true})
|
||||||
|
|
Loading…
Reference in New Issue