commit
efbf5f0d2c
|
@ -98,7 +98,7 @@ class ACLComponent extends Component
|
||||||
'connectLocal' => ['perm_admin'],
|
'connectLocal' => ['perm_admin'],
|
||||||
'delete' => ['perm_admin'],
|
'delete' => ['perm_admin'],
|
||||||
'edit' => ['perm_admin'],
|
'edit' => ['perm_admin'],
|
||||||
'exposedTools' => ['perm_admin'],
|
'exposedTools' => ['OR' => ['perm_admin', 'perm_sync']],
|
||||||
'index' => ['perm_admin'],
|
'index' => ['perm_admin'],
|
||||||
'connectorIndex' => ['perm_admin'],
|
'connectorIndex' => ['perm_admin'],
|
||||||
'view' => ['perm_admin'],
|
'view' => ['perm_admin'],
|
||||||
|
|
|
@ -165,7 +165,8 @@ class CRUDComponent extends Component
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$this->Controller->isFailResponse = true;
|
$this->Controller->isFailResponse = true;
|
||||||
$validationMessage = $this->prepareValidationError($data);
|
$validationErrors = $data->getErrors();
|
||||||
|
$validationMessage = $this->prepareValidationMessage($validationErrors);
|
||||||
$message = __(
|
$message = __(
|
||||||
'{0} could not be added.{1}',
|
'{0} could not be added.{1}',
|
||||||
$this->ObjectAlias,
|
$this->ObjectAlias,
|
||||||
|
@ -174,7 +175,7 @@ class CRUDComponent extends Component
|
||||||
if ($this->Controller->ParamHandler->isRest()) {
|
if ($this->Controller->ParamHandler->isRest()) {
|
||||||
$this->Controller->restResponsePayload = $this->RestResponse->viewData($message, 'json');
|
$this->Controller->restResponsePayload = $this->RestResponse->viewData($message, 'json');
|
||||||
} else if ($this->Controller->ParamHandler->isAjax()) {
|
} else if ($this->Controller->ParamHandler->isAjax()) {
|
||||||
$this->Controller->ajaxResponsePayload = $this->RestResponse->ajaxFailResponse($this->ObjectAlias, 'add', $data, $message, $validationMessage);
|
$this->Controller->ajaxResponsePayload = $this->RestResponse->ajaxFailResponse($this->ObjectAlias, 'add', $data, $message, $validationErrors);
|
||||||
} else {
|
} else {
|
||||||
$this->Controller->Flash->error($message);
|
$this->Controller->Flash->error($message);
|
||||||
}
|
}
|
||||||
|
@ -183,6 +184,21 @@ class CRUDComponent extends Component
|
||||||
$this->Controller->set('entity', $data);
|
$this->Controller->set('entity', $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function prepareValidationMessage($errors)
|
||||||
|
{
|
||||||
|
$validationMessage = '';
|
||||||
|
if (!empty($errors)) {
|
||||||
|
if (count($errors) == 1) {
|
||||||
|
$field = array_keys($errors)[0];
|
||||||
|
$fieldError = implode(', ', array_values($errors[$field]));
|
||||||
|
$validationMessage = __('{0}: {1}', $field, $fieldError);
|
||||||
|
} else {
|
||||||
|
$validationMessage = __('There has been validation issues with multiple fields');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $validationMessage;
|
||||||
|
}
|
||||||
|
|
||||||
private function prepareValidationError($data)
|
private function prepareValidationError($data)
|
||||||
{
|
{
|
||||||
$validationMessage = '';
|
$validationMessage = '';
|
||||||
|
@ -192,7 +208,7 @@ class CRUDComponent extends Component
|
||||||
foreach ($errorData as $key => $value) {
|
foreach ($errorData as $key => $value) {
|
||||||
$errorMessages[] = $value;
|
$errorMessages[] = $value;
|
||||||
}
|
}
|
||||||
$validationMessage .= __(' {1}', $field, implode(',', $errorMessages));
|
$validationMessage .= __('{0}: {1}', $field, implode(',', $errorMessages));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $validationMessage;
|
return $validationMessage;
|
||||||
|
@ -261,14 +277,15 @@ class CRUDComponent extends Component
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$validationMessage = $this->prepareValidationError($data);
|
$validationErrors = $data->getErrors();
|
||||||
|
$validationMessage = $this->prepareValidationMessage($validationErrors);
|
||||||
$message = __(
|
$message = __(
|
||||||
__('{0} could not be modified.'),
|
__('{0} could not be modified.'),
|
||||||
$this->ObjectAlias
|
$this->ObjectAlias
|
||||||
);
|
);
|
||||||
if ($this->Controller->ParamHandler->isRest()) {
|
if ($this->Controller->ParamHandler->isRest()) {
|
||||||
} else if ($this->Controller->ParamHandler->isAjax()) {
|
} else if ($this->Controller->ParamHandler->isAjax()) {
|
||||||
$this->Controller->ajaxResponsePayload = $this->RestResponse->ajaxFailResponse($this->ObjectAlias, 'edit', $data, $message, $data->getErrors());
|
$this->Controller->ajaxResponsePayload = $this->RestResponse->ajaxFailResponse($this->ObjectAlias, 'edit', $data, $message, $validationErrors);
|
||||||
} else {
|
} else {
|
||||||
$this->Controller->Flash->error($message);
|
$this->Controller->Flash->error($message);
|
||||||
}
|
}
|
||||||
|
@ -699,7 +716,8 @@ class CRUDComponent extends Component
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$validationMessage = $this->prepareValidationError($data);
|
$validationErrors = $data->getErrors();
|
||||||
|
$validationMessage = $this->prepareValidationMessage($validationErrors);
|
||||||
$message = __(
|
$message = __(
|
||||||
'{0} could not be modified.{1}',
|
'{0} could not be modified.{1}',
|
||||||
$this->ObjectAlias,
|
$this->ObjectAlias,
|
||||||
|
@ -707,7 +725,7 @@ class CRUDComponent extends Component
|
||||||
);
|
);
|
||||||
if ($this->Controller->ParamHandler->isRest()) {
|
if ($this->Controller->ParamHandler->isRest()) {
|
||||||
} else if ($this->Controller->ParamHandler->isAjax()) {
|
} else if ($this->Controller->ParamHandler->isAjax()) {
|
||||||
$this->Controller->ajaxResponsePayload = $this->RestResponse->ajaxFailResponse($this->ObjectAlias, 'toggle', $message, $validationMessage);
|
$this->Controller->ajaxResponsePayload = $this->RestResponse->ajaxFailResponse($this->ObjectAlias, 'toggle', $message, $validationErrors);
|
||||||
} else {
|
} else {
|
||||||
$this->Controller->Flash->error($message);
|
$this->Controller->Flash->error($message);
|
||||||
if (empty($params['redirect'])) {
|
if (empty($params['redirect'])) {
|
||||||
|
|
|
@ -0,0 +1,171 @@
|
||||||
|
<?php
|
||||||
|
// set a namespace for the module
|
||||||
|
namespace SkeletonConnector;
|
||||||
|
|
||||||
|
// These can be left as is. We want to have access to the commonconnector tools as well as basic http / exception functions
|
||||||
|
require_once(ROOT . '/src/Lib/default/local_tool_connectors/CommonConnectorTools.php');
|
||||||
|
use CommonConnectorTools\CommonConnectorTools;
|
||||||
|
use Cake\Http\Client;
|
||||||
|
use Cake\Http\Exception\NotFoundException;
|
||||||
|
use Cake\Http\Exception\MethodNotAllowedException;
|
||||||
|
use Cake\Http\Client\Response;
|
||||||
|
|
||||||
|
class SkeletonConnector extends CommonConnectorTools
|
||||||
|
{
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* ====================================== Metainformation block ======================================
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public $description = '';
|
||||||
|
public $connectorName = 'SkeletonConnector';
|
||||||
|
public $name = 'Skeleton';
|
||||||
|
public $version = '0.1';
|
||||||
|
|
||||||
|
// exposed function list and configuration
|
||||||
|
public $exposedFunctions = [
|
||||||
|
'myIndexAction' => [
|
||||||
|
'type' => 'index',
|
||||||
|
'scope' => 'child',
|
||||||
|
'params' => [
|
||||||
|
'quickFilter',
|
||||||
|
'sort',
|
||||||
|
'direction',
|
||||||
|
'page',
|
||||||
|
'limit'
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'myFormAction' => [
|
||||||
|
'type' => 'formAction',
|
||||||
|
'scope' => 'childAction',
|
||||||
|
'params' => [
|
||||||
|
'setting',
|
||||||
|
'value'
|
||||||
|
],
|
||||||
|
'redirect' => 'serverSettingsAction'
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
public function health(Object $connection): array
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
returns an array with 2 keys:
|
||||||
|
[
|
||||||
|
status: the numeric response code (0: UNKNOWN, 1: OK, 2: ISSUES, 3: ERROR),
|
||||||
|
message: status message shown
|
||||||
|
]
|
||||||
|
*/
|
||||||
|
return $health;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* ====================================== Exposed custom functions ======================================
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
public function myIndexAction(array $params): array
|
||||||
|
{
|
||||||
|
// $data = get data from local tool
|
||||||
|
|
||||||
|
//if we want to filter it via the quicksearch
|
||||||
|
if (!empty($params['quickFilter'])) {
|
||||||
|
// filter $data
|
||||||
|
}
|
||||||
|
|
||||||
|
// return the data embedded in a generic index parameter array
|
||||||
|
|
||||||
|
return [
|
||||||
|
'type' => 'index',
|
||||||
|
'title' => false,
|
||||||
|
'description' => false,
|
||||||
|
'data' => [
|
||||||
|
'data' => $data,
|
||||||
|
'skip_pagination' => 1,
|
||||||
|
'top_bar' => [
|
||||||
|
'children' => [
|
||||||
|
[
|
||||||
|
'type' => 'search',
|
||||||
|
'button' => __('Filter'),
|
||||||
|
'placeholder' => __('Enter value to search'),
|
||||||
|
'data' => '',
|
||||||
|
'searchKey' => 'value',
|
||||||
|
'additionalUrlParams' => $urlParams
|
||||||
|
]
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'fields' => [
|
||||||
|
[
|
||||||
|
'name' => 'field1_name',
|
||||||
|
'sort' => 'field1.path',
|
||||||
|
'data_path' => 'field1.path',
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'pull' => 'right',
|
||||||
|
'actions' => [
|
||||||
|
[
|
||||||
|
'open_modal' => '/localTools/action/' . h($params['connection']['id']) . '/myForm?myKey={{0}}',
|
||||||
|
'modal_params_data_path' => ['myKey'],
|
||||||
|
'icon' => 'font_awesome_icon_name',
|
||||||
|
'reload_url' => '/localTools/action/' . h($params['connection']['id']) . '/myIndex'
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function myFormAction(array $params): array
|
||||||
|
{
|
||||||
|
if ($params['request']->is(['get'])) {
|
||||||
|
return [
|
||||||
|
'data' => [
|
||||||
|
'title' => __('My Form Title'),
|
||||||
|
'description' => __('My form description'),
|
||||||
|
'submit' => [
|
||||||
|
'action' => $params['request']->getParam('action')
|
||||||
|
],
|
||||||
|
'url' => ['controller' => 'localTools', 'action' => 'action', h($params['connection']['id']), 'myFormAction']
|
||||||
|
]
|
||||||
|
];
|
||||||
|
} elseif ($params['request']->is(['post'])) {
|
||||||
|
// handle posted data
|
||||||
|
if ($success) {
|
||||||
|
return ['success' => 1, 'message' => __('Action successful.')];
|
||||||
|
} else {
|
||||||
|
return ['success' => 0, 'message' => __('Action failed spectacularly.')];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new MethodNotAllowedException(__('Invalid http request type for the given action.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* ====================================== Inter connection functions ======================================
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
public function initiateConnection(array $params): array
|
||||||
|
{
|
||||||
|
// encode initial connection in local tool
|
||||||
|
// build and return initiation payload
|
||||||
|
return $payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function acceptConnection(array $params): array
|
||||||
|
{
|
||||||
|
// encode acceptance of the connection request in local tool, based on the payload from the initiation
|
||||||
|
// return payload for remote to encode the connection
|
||||||
|
return $payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function finaliseConnection(array $params): bool
|
||||||
|
{
|
||||||
|
// based on the payload from the acceptance, finalise the connection
|
||||||
|
// return true on success
|
||||||
|
return $success;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
|
@ -26,7 +26,12 @@ class BroodsTable extends AppTable
|
||||||
|
|
||||||
public function validationDefault(Validator $validator): Validator
|
public function validationDefault(Validator $validator): Validator
|
||||||
{
|
{
|
||||||
return $validator;
|
return $validator
|
||||||
|
->requirePresence(['name', 'url', 'organisation_id'], 'create')
|
||||||
|
->notEmptyString('name')
|
||||||
|
->notEmptyString('url')
|
||||||
|
->url('url', __('The provided value is not a valid URL'))
|
||||||
|
->naturalNumber('organisation_id', false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function genHTTPClient(Object $brood, array $options=[]): Object
|
public function genHTTPClient(Object $brood, array $options=[]): Object
|
||||||
|
|
|
@ -26,7 +26,8 @@
|
||||||
'field' => 'organisation_id',
|
'field' => 'organisation_id',
|
||||||
'label' => __('Owner organisation'),
|
'label' => __('Owner organisation'),
|
||||||
'options' => $dropdownData['organisation'],
|
'options' => $dropdownData['organisation'],
|
||||||
'type' => 'dropdown'
|
'type' => 'dropdown',
|
||||||
|
'empty' => __('-- pick one --')
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
'field' => 'trusted',
|
'field' => 'trusted',
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
$controlParams = [
|
$controlParams = [
|
||||||
'options' => $fieldData['options'],
|
'options' => $fieldData['options'],
|
||||||
|
'empty' => $fieldData['empty'] ?? false,
|
||||||
'class' => ($fieldData['class'] ?? '') . ' formDropdown custom-select'
|
'class' => ($fieldData['class'] ?? '') . ' formDropdown custom-select'
|
||||||
];
|
];
|
||||||
echo $this->FormFieldMassage->prepareFormElement($this->Form, $controlParams, $fieldData);
|
echo $this->FormFieldMassage->prepareFormElement($this->Form, $controlParams, $fieldData);
|
||||||
|
|
|
@ -107,7 +107,7 @@
|
||||||
.click(function() {
|
.click(function() {
|
||||||
const url = `/${controller}/filtering`
|
const url = `/${controller}/filtering`
|
||||||
const reloadUrl = `/${controller}/index${additionalUrlParams}`
|
const reloadUrl = `/${controller}/index${additionalUrlParams}`
|
||||||
openFilteringModal(this, url, reloadUrl, $(`#table-container-${randomValue}`));
|
openFilteringModal(this, url, reloadUrl, $(`#index-table-${randomValue}`));
|
||||||
})
|
})
|
||||||
|
|
||||||
function doFilter($button) {
|
function doFilter($button) {
|
||||||
|
@ -151,7 +151,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function openFilteringModal(clicked, url, reloadUrl, tableId) {
|
function openFilteringModal(clicked, url, reloadUrl, tableId) {
|
||||||
UI.overlayUntilResolve(clicked, UI.submissionModalForIndex(url, reloadUrl, tableId))
|
const modalPromise = UI.submissionModalForIndex(url, reloadUrl, tableId)
|
||||||
|
UI.overlayUntilResolve(clicked, modalPromise)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -996,21 +996,22 @@ class FormValidationHelper {
|
||||||
injectValidationErrorInForm(fieldName, errors) {
|
injectValidationErrorInForm(fieldName, errors) {
|
||||||
const inputField = Array.from(this.form).find(node => { return node.name == fieldName })
|
const inputField = Array.from(this.form).find(node => { return node.name == fieldName })
|
||||||
if (inputField !== undefined) {
|
if (inputField !== undefined) {
|
||||||
const $messageNode = this.buildValidationMessageNode(errors)
|
const $messageNode = this.buildValidationMessageNode(fieldName, errors)
|
||||||
const $inputField = $(inputField)
|
const $inputField = $(inputField)
|
||||||
$inputField.addClass('is-invalid')
|
$inputField.addClass('is-invalid')
|
||||||
$messageNode.insertAfter($inputField)
|
$messageNode.insertAfter($inputField)
|
||||||
} else {
|
} else {
|
||||||
const $messageNode = this.buildValidationMessageNode(errors, true)
|
const $messageNode = this.buildValidationMessageNode(fieldName, errors, true)
|
||||||
const $flashContainer = $(this.form).parent().find('#flashContainer')
|
const $flashContainer = $(this.form).parent().find('#flashContainer')
|
||||||
$messageNode.insertAfter($flashContainer)
|
$messageNode.insertAfter($flashContainer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
buildValidationMessageNode(errors, isAlert=false) {
|
buildValidationMessageNode(fieldName, errors, isAlert=false) {
|
||||||
const $messageNode = $('<div></div>')
|
const $messageNode = $('<div></div>')
|
||||||
if (isAlert) {
|
if (isAlert) {
|
||||||
$messageNode.addClass('alert alert-danger').attr('role', 'alert')
|
$messageNode.addClass('alert alert-danger').attr('role', 'alert')
|
||||||
|
$messageNode.append($('<strong></strong>').text(`${fieldName}: `))
|
||||||
} else {
|
} else {
|
||||||
$messageNode.addClass('invalid-feedback')
|
$messageNode.addClass('invalid-feedback')
|
||||||
}
|
}
|
||||||
|
@ -1020,7 +1021,7 @@ class FormValidationHelper {
|
||||||
if (hasMultipleErrors) {
|
if (hasMultipleErrors) {
|
||||||
$messageNode.append($('<li></li>').text(error))
|
$messageNode.append($('<li></li>').text(error))
|
||||||
} else {
|
} else {
|
||||||
$messageNode.text(error)
|
$messageNode.append($('<span></span>').text(error))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in New Issue