chg: [requestProcessor] UI improvements and simplified creation of

processors
pull/41/head
mokaddem 2021-03-18 14:01:14 +01:00
parent 0a1294bbee
commit f3f73a475b
9 changed files with 161 additions and 93 deletions

View File

@ -8,7 +8,7 @@ interface GenericProcessorActionI
{
public function create($requestData);
public function process($requestID, $serverRequest);
public function discard($requestID);
public function discard($requestID ,$requestData);
public function setViewVariables($controller, $request);
}
@ -89,11 +89,6 @@ class GenericRequestProcessor
}
}
public function checkLoading()
{
return 'Assimilation successful!';
}
protected function setViewVariablesConfirmModal($controller, $id, $title='', $question='', $actionName='')
{
$controller->set('title', !empty($title) ? $title : __('Process request {0}', $id));
@ -102,6 +97,63 @@ class GenericRequestProcessor
$controller->set('path', ['controller' => 'inbox', 'action' => 'process', $id]);
}
protected function genActionResult($data, $success, $message, $errors=[])
{
return [
'data' => $data,
'success' => $success,
'message' => $message,
'errors' => $errors,
];
}
public function genHTTPReply($controller, $processResult, $request, $redirect=null)
{
if (is_array($request)) {
$scope = $request['scope'];
$action = $request['action'];
} else {
$scope = $request->scope;
$action = $request->action;
}
if ($processResult['success']) {
$message = !empty($processResult['message']) ? $processResult['message'] : __('Request {0} successfully processed.', $id);
if ($controller->ParamHandler->isRest()) {
$response = $controller->RestResponse->viewData($processResult, 'json');
} else if ($controller->ParamHandler->isAjax()) {
$response = $controller->RestResponse->ajaxSuccessResponse('RequestProcessor', "{$scope}.{$action}", $processResult['data'], $message);
} else {
$controller->Flash->success($message);
if (!is_null($redirect)) {
$response = $controller->redirect($redirect);
} else {
$response = $controller->redirect(['action' => 'index']);
}
}
} else {
$message = !empty($processResult['message']) ? $processResult['message'] : __('Request {0} could not be processed.', $id);
if ($controller->ParamHandler->isRest()) {
$response = $controller->RestResponse->viewData($processResult, 'json');
} else if ($controller->ParamHandler->isAjax()) {
$response = $controller->RestResponse->ajaxFailResponse('RequestProcessor', "{$scope}.{$action}", $processResult['data'], $message, $processResult['errors']);
} else {
$controller->Flash->error($message);
if (!is_null($redirect)) {
$response = $controller->redirect($redirect);
} else {
$response = $controller->redirect(['action' => 'index']);
}
}
}
return $response;
}
public function checkLoading()
{
return 'Assimilation successful!';
}
public function create($requestData)
{
$requestData['scope'] = $this->scope;
@ -109,17 +161,22 @@ class GenericRequestProcessor
$requestData['description'] = $this->description;
$request = $this->generateRequest($requestData);
$savedRequest = $this->Inbox->save($request);
if ($savedRequest !== false) {
// log here
}
return $this->genActionResult(
$savedRequest,
$savedRequest !== false,
__('{0} request for {1} created', $this->scope, $this->action),
$request->getErrors()
);
}
public function discard($requestData)
public function discard($id, $requestData)
{
$request = $this->generateRequest($requestData);
$savedRequest = $this->Inbox->save($request);
if ($savedRequest !== false) {
// log here
}
$request = $this->Inbox->get($id);
$this->Inbox->delete($request);
return $this->genActionResult(
[],
true,
__('{0}.{1} request #{2} discarded', $this->scope, $this->action, $id)
);
}
}

View File

@ -18,7 +18,7 @@ class UserRequestProcessor extends GenericRequestProcessor
public function create($requestData)
{
parent::create($requestData);
return parent::create($requestData);
}
}
@ -47,7 +47,7 @@ class RegistrationProcessor extends UserRequestProcessor implements GenericProce
public function create($requestData) {
$this->validateRequestData($requestData);
$requestData['title'] = __('User account creation requested for {0}', $requestData['data']['email']);
parent::create($requestData);
return parent::create($requestData);
}
public function setViewVariables($controller, $request)
@ -77,39 +77,42 @@ class RegistrationProcessor extends UserRequestProcessor implements GenericProce
$controller->set(compact('dropdownData'));
}
public function process($id, $serverRequest)
public function process($id, $requestData)
{
$data = $serverRequest->getData();
if ($data['individual_id'] == -1) {
if ($requestData['individual_id'] == -1) {
$individual = $this->Users->Individuals->newEntity([
'uuid' => $data['uuid'],
'email' => $data['email'],
'first_name' => $data['first_name'],
'last_name' => $data['last_name'],
'position' => $data['position'],
'uuid' => $requestData['uuid'],
'email' => $requestData['email'],
'first_name' => $requestData['first_name'],
'last_name' => $requestData['last_name'],
'position' => $requestData['position'],
]);
$individual = $this->Users->Individuals->save($individual);
} else {
$individual = $this->Users->Individuals->get($data['individual_id']);
$individual = $this->Users->Individuals->get($requestData['individual_id']);
}
$user = $this->Users->newEntity([
'individual_id' => $individual->id,
'username' => $data['username'],
'username' => $requestData['username'],
'password' => '~PASSWORD_TO_BE_REPLACED~',
'role_id' => $data['role_id'],
'disabled' => $data['disabled'],
'role_id' => $requestData['role_id'],
'disabled' => $requestData['disabled'],
]);
$user = $this->Users->save($user);
return [
'data' => $user,
'success' => $user !== false,
'message' => $user !== false ? __('User `{0}` created', $user->username) : __('Could not create user `{0}`.', $user->username),
'errors' => $user->getErrors()
];
if ($user !== false) {
$this->discard($id, $requestData);
}
return $this->genActionResult(
$user,
$user !== false,
$user !== false ? __('User `{0}` created', $user->username) : __('Could not create user `{0}`.', $user->username),
$user->getErrors()
);
}
public function discard($id)
public function discard($id, $requestData)
{
parent::discard($id);
return parent::discard($id, $requestData);
}
}

View File

@ -59,6 +59,13 @@ class InboxController extends AppController
public function delete($id)
{
if ($this->request->is('post')) {
$request = $this->Inbox->get($id);
$this->requestProcessor = TableRegistry::getTableLocator()->get('RequestProcessor');
$processor = $this->requestProcessor->getProcessor($request->scope, $request->action);
$discardResult = $processor->discard($id, $request);
return $processor->genHTTPReply($this, $discardResult, $request);
}
$this->set('deletionTitle', __('Discard request'));
$this->set('deletionText', __('Are you sure you want to discard request #{0}?', $id));
$this->set('deletionConfirm', __('Discard'));
@ -75,17 +82,10 @@ class InboxController extends AppController
$scope = $request->scope;
$action = $request->action;
$this->requestProcessor = TableRegistry::getTableLocator()->get('RequestProcessor');
$processor = $this->requestProcessor->getProcessor($scope, $action);
$processor = $this->requestProcessor->getProcessor($request->scope, $request->action);
if ($this->request->is('post')) {
$processResult = $processor->process($id, $this->request);
if ($processResult['success']) {
$message = !empty($processResult['message']) ? $processResult['message'] : __('Request {0} processed.', $id);
$response = $this->RestResponse->ajaxSuccessResponse('RequestProcessor', "{$scope}.{$action}", $processResult['data'], $message);
} else {
$message = !empty($processResult['message']) ? $processResult['message'] : __('Request {0} could not be processed.', $id);
$response = $this->RestResponse->ajaxFailResponse('RequestProcessor', "{$scope}.{$action}", $processResult['data'], $message, $processResult['errors']);
}
return $response;
$processResult = $processor->process($id, $this->request->getData());
return $processor->genHTTPReply($this, $processResult, $request);
} else {
$this->requestProcessor->render($this, $processor, $request);
}

View File

@ -150,8 +150,7 @@ class UsersController extends AppController
'last_name' => 'bar',
],
];
$processor->create($data);
$this->Flash->success(__('Entry created'));
return $this->redirect(['controller' => 'Inbox', 'action' => 'index']);
$processorResult = $processor->create($data);
return $processor->genHTTPReply($this, $processorResult, ['scope' => 'User', 'action' => 'Registration'], ['controller' => 'Inbox', 'action' => 'index']);
}
}

View File

@ -721,7 +721,7 @@ class BoostrapModal extends BootstrapGeneric {
'footerClass' => [''],
'type' => 'ok-only',
'variant' => '',
'confirmFunction' => '',
'confirmFunction' => '', // Will be called with the following arguments confirmFunction(modalObject, tmpApi)
'cancelFunction' => ''
];
@ -847,10 +847,10 @@ class BoostrapModal extends BootstrapGeneric {
$buttonConfirm = (new BoostrapButton([
'variant' => $variant,
'text' => h($this->options['confirmText']),
'class' => 'modal-confirm-button',
'params' => [
'data-dismiss' => $this->options['confirmFunction'] ? '' : 'modal',
// 'onclick' => sprintf('(function(clicked) { %s.finally( () => { $(clicked).closest(\'.modal\').data(\'modalObject\').hide() }) }(this))', $this->options['confirmFunction'])
'onclick' => sprintf('closeModalOnFunctionCompletion(this, function(clicked) { return %s })', $this->options['confirmFunction'])
'data-confirmFunction' => sprintf('%s', $this->options['confirmFunction'])
]
]))->button();
return $buttonCancel . $buttonConfirm;

View File

@ -77,17 +77,20 @@ echo $this->element('genericElements/IndexTable/index_table', [
[
'url' => '/inbox/view',
'url_params_data_paths' => ['id'],
'icon' => 'eye'
'icon' => 'eye',
'title' => __('View request')
],
[
'open_modal' => '/inbox/process/[onclick_params_data_path]',
'modal_params_data_path' => 'id',
'icon' => 'cogs'
'icon' => 'cogs',
'title' => __('Process request')
],
[
'open_modal' => '/inbox/delete/[onclick_params_data_path]',
'modal_params_data_path' => 'id',
'icon' => 'trash'
'icon' => 'trash',
'title' => __('Discard request')
],
]
]

View File

@ -81,17 +81,14 @@
$formIndividual
),
'confirmText' => __('Create user'),
'confirmFunction' => 'submitRegistration(clicked)'
'confirmFunction' => 'submitRegistration'
]);
?>
</div>
<script>
function submitRegistration(clicked) {
const tmpApi = new AJAXApi({
statusNode: clicked
})
const $forms = $(clicked).closest('.modal').find('form')
function submitRegistration(modalObject, tmpApi) {
const $forms = modalObject.$modal.find('form')
const url = $forms[0].action
const data1 = getFormData($forms[0])
const data2 = getFormData($forms[1])

View File

@ -688,8 +688,11 @@ class ModalFactory {
}
/** Attach the submission click listener for modals that have been generated by raw HTML */
findSubmitButtonAndAddListener(clearOnclick=true) {
const $submitButton = this.$modal.find('.modal-footer #submitButton')
findSubmitButtonAndAddListener() {
let $submitButton = this.$modal.find('.modal-footer #submitButton')
if (!$submitButton[0]) {
$submitButton = this.$modal.find('.modal-footer .modal-confirm-button')
}
if ($submitButton[0]) {
const formID = $submitButton.data('form-id')
let $form
@ -698,26 +701,43 @@ class ModalFactory {
} else {
$form = this.$modal.find('form')
}
if (clearOnclick) {
if ($submitButton.data('confirmfunction') !== undefined && $submitButton.data('confirmfunction') !== '') {
const clickHandler = window[$submitButton.data('confirmfunction')]
this.options.APIConfirm = (tmpApi) => {
return clickHandler(this, tmpApi)
.then((data) => {
if (data.success) {
this.options.POSTSuccessCallback(data)
} else { // Validation error
this.injectFormValidationFeedback(form, data.errors)
return Promise.reject('Validation error');
}
})
.catch((errorMessage) => {
this.options.POSTFailCallback(errorMessage)
return Promise.reject(errorMessage);
})
}
} else {
$submitButton[0].removeAttribute('onclick')
}
this.options.APIConfirm = (tmpApi) => {
return tmpApi.postForm($form[0])
.then((data) => {
if (data.success) {
this.options.POSTSuccessCallback(data)
} else { // Validation error
this.injectFormValidationFeedback(form, data.errors)
return Promise.reject('Validation error');
}
})
.catch((errorMessage) => {
this.options.POSTFailCallback(errorMessage)
return Promise.reject(errorMessage);
})
this.options.APIConfirm = (tmpApi) => {
return tmpApi.postForm($form[0])
.then((data) => {
if (data.success) {
this.options.POSTSuccessCallback(data)
} else { // Validation error
this.injectFormValidationFeedback(form, data.errors)
return Promise.reject('Validation error');
}
})
.catch((errorMessage) => {
this.options.POSTFailCallback(errorMessage)
return Promise.reject(errorMessage);
})
}
}
$submitButton.click(this.getConfirmationHandlerFunction())
}
}
}

View File

@ -66,17 +66,6 @@ function attachTestConnectionResultHtml(result, $container) {
return $testResultDiv
}
function closeModalOnFunctionCompletion(clicked, fun) {
const result = fun(clicked)
if (result === undefined) {
$(clicked).closest('.modal').data('modalObject').hide()
} else {
result.finally( () => {
$(clicked).closest('.modal').data('modalObject').hide()
})
}
}
var UI
$(document).ready(() => {
if (typeof UIFactory !== "undefined") {