diff --git a/Controller/ActAsPeopleController.php b/Controller/ActAsPeopleController.php index eb872ff..71e5b07 100644 --- a/Controller/ActAsPeopleController.php +++ b/Controller/ActAsPeopleController.php @@ -76,8 +76,8 @@ public function beforeFilter() public function add(): void { - $this->layout = null; - $this->autoRender = false; + $this->request->allowMethod('ajax'); + $this->layout = 'ajax'; if(!$this->request->is('restful') && !$this->request->is('ajax')) { @@ -86,40 +86,110 @@ public function add(): void $data = $this->request->data; + $fullName = $data['fullname']; + unset($data['fullname']); + try { $ret = $this->ActAsPerson->saveAll($data); } catch(Exception $e) { $err = filter_var($e->getMessage(),FILTER_SANITIZE_SPECIAL_CHARS); + $this->Flash->set($err, ['key' => 'error']); } if($ret) { - // Reread the data so we account for any normalizations + $this->Api->restResultHeader(HttpStatusCodesEnum::HTTP_CREATED, 'Added'); + // I am registering a flash message. It will render after the frontend triggers a reload + $this->Flash->set("Act As {$fullName}" , ['key' => 'success']); + $args = []; $args['conditions']['ActAsPerson.id'] = $this->ActAsPerson->id; $args['contain'] = false; $data = $this->ActAsPerson->find('first', $args); - $this->Api->restResultHeader(201, "Added"); - $this->set('ActAsPerson', $this->ActAsPerson->id); - $this->response->body(json_encode($data['ActAsPerson'], JSON_THROW_ON_ERROR)); + + $resp = [ + 'ActAsPerson' => $data['ActAsPerson'] + ]; + $this->set(compact('resp')); + $this->set('_serialize', 'resp'); } else { $fs = $this->ActAsPerson->invalidFields(); if(!empty($fs)) { - $this->Api->restResultHeader(400, 'Invalid Fields'); - $this->set('invalid_fields', $fs); + $this->Api->restResultHeader(HttpStatusCodesEnum::HTTP_BAD_REQUEST, 'Invalid Fields'); + $this->Flash->set('Invalid Fields', ['key' => 'error']); + $this->set(compact('fs')); + $this->set('_serialize', 'fs'); } elseif ($e && isset(_txt('en.http.status.codes')[$e->getCode()]) ) { $this->Api->restResultHeader($e->getCode(), _txt('en.http.status.codes')[$e->getCode()]); if(!empty($e->getMessage())) { - $this->set('vv_error', $e->getMessage()); + $vv_error = $e->getMessage(); + $this->set(compact('vv_error')); + $this->set('_serialize', 'vv_error'); + $this->Flash->set($e->getMessage(), ['key' => 'error']); } } else { - $this->Api->restResultHeader(500, "Other Error"); + $this->Api->restResultHeader(HttpStatusCodesEnum::HTTP_INTERNAL_SERVER_ERROR, 'Other Error'); + $error = ErrorsEnum::Error; + $this->set(compact('error')); + $this->set('_serialize', 'error'); } } + } + + /** + * Handle an Act As Person Delete request. + * + * @since COmanage Registry v4.4.0 + */ + + public function delete():void + { + $this->layout = null; + $this->autoRender = false; + + if(!$this->request->is('delete') + || $this->request->is('ajax') + || $this->request->is('restful')) { + throw new RuntimeException('HTTP Method Not Allowed', HttpStatusCodesEnum::HTTP_METHOD_NOT_ALLOWED); + } + + if(empty($this->request->named['copersonid']) + || empty($this->request->named['act_as_copersonid'])) { + $this->log(__METHOD__ . '::message: Named Parameter missing', LOG_ERROR); + throw new BadRequestException('Named Parameter missing'); + } + + $redirect = [ + 'plugin' => 'grouper_lite_widget', + 'controller' => 'grouper_groups', + 'action' => $this->request->named['redirect_act'] ?? 'groupmember', + 'co' => $this->request->named['co'], + 'glid' => $this->request->named['glid'] + ]; + + try { + $conditions = [ + 'ActAsPerson.co_person_id' => $this->request->named['copersonid'], + 'ActAsPerson.act_as_co_person_id' => $this->request->named['act_as_copersonid'] + ]; + + $ret = $this->ActAsPerson->deleteAll($conditions, true, true); + } catch(Exception $e) { + $err = filter_var($e->getMessage(),FILTER_SANITIZE_SPECIAL_CHARS); + $this->Flash->set($err, ['key' => 'error']); + } + + // Set flash message + if($ret) { + $this->Flash->set(_txt('er.deleted-a', ['Person']) , ['key' => 'success']); + } else { + $this->Flash->set(_txt('er.delete'), ['key' => 'error']); + } - $this->response->send(); + // Redirect back to the plugin + $this->redirect($redirect); } @@ -137,6 +207,8 @@ public function add(): void public function isAuthorized(): array|bool { $roles = $this->Role->calculateCMRoles(); + $this->set('roles', $roles); + $pids = $this->parsePersonID($this->request->data); $cfg = $this->CoGrouperLiteWidget->getConfig(); diff --git a/Controller/GrouperGroupsController.php b/Controller/GrouperGroupsController.php index 354c425..6d75472 100644 --- a/Controller/GrouperGroupsController.php +++ b/Controller/GrouperGroupsController.php @@ -28,6 +28,7 @@ App::uses('Validator', 'Vendor/cakephp/Validation'); App::uses('CoGrouperLite', 'GrouperLiteWidget.Model/'); App::uses('GrouperGroup', 'GrouperLiteWidget.Model/'); +App::uses('ActAsPerson', 'GrouperLiteWidget.Model/'); App::uses('Identifier', 'Model'); /** @@ -45,6 +46,7 @@ class GrouperGroupsController extends GrouperLiteWidgetAppController public $uses = [ 'GrouperLiteWidget.GrouperGroup', 'GrouperLiteWidget.CoGrouperLiteWidget', + 'GrouperLiteWidget.ActAsPerson', 'Identifier', 'CoPerson' ]; @@ -152,6 +154,22 @@ public function beforeRender() { $roles = $this->Role->calculateCMRoles(); $this->set('vv_copersonid', $roles['copersonid'] ?? null); + $this->set('vv_picker_mode', PeoplePickerModeEnum::All); + + // Get the ActAs User Data + $co_person_id = $this->viewVars['roles']['copersonid']; + // Get the act as data from the database + $args = []; + $args['conditions']['ActAsPerson.co_person_id'] = $co_person_id; + $args['contain'] = false; + $act_as_record = $this->ActAsPerson->find('first', $args); + $this->set('vv_act_as_people', []); + if(!empty($act_as_record)) { + $act_as_person = $this->GrouperGroup->dataConstructForPicker($this->cur_co['Co']['id'], + PeoplePickerModeEnum::All, + [$act_as_record['ActAsPerson']['act_as_co_person_id']]); + $this->set('vv_act_as_people', $act_as_person); + } } /** @@ -423,12 +441,15 @@ public function index(): void public function isAuthorized(): array|bool { $roles = $this->Role->calculateCMRoles(); + $this->set('roles', $roles); + $pids = $this->parsePersonID($this->request->data); + $cfg = $this->CoGrouperLiteWidget->getConfig(); // Find the identifier $args = array(); $args['conditions']['Identifier.type'] = $cfg['CoGrouperLiteWidget']['identifier_type']; $args['conditions']['Identifier.status'] = SuspendableStatusEnum::Active; - $args['conditions']['Identifier.co_person_id'] = $roles['copersonid']; + $args['conditions']['Identifier.co_person_id'] = !empty($roles['copersonid']) ? $roles['copersonid'] : $pids['copersonid']; $args['contain'] = false; $identifiers = $this->Identifier->find('first', $args); diff --git a/Model/GrouperGroup.php b/Model/GrouperGroup.php index a8f55b8..ad83576 100644 --- a/Model/GrouperGroup.php +++ b/Model/GrouperGroup.php @@ -169,19 +169,15 @@ public function filteredMemberOfGroups(string $userId, array $cfg): array * * @return array Array of CO Person records * @since COmanage Registry v4.4.0 - * - * XXX Remove this as soon as the change is present in COmanage core - * */ public function findForPicker(int $coId, string $mode, ?string $term): array { $coPersonIds = []; $this->CoPerson = ClassRegistry::init('CoPerson'); - $this->Co = ClassRegistry::init('Co'); // jquery Autocomplete sends the search as url?term=foo if(!empty($term)) { - // Leverage model specific keyword search + // Leverage-model-specific keyword search // Note EmailAddress and Identifier don't support substring search foreach(array('Name', 'EmailAddress', 'Identifier') as $m) { @@ -197,7 +193,29 @@ public function findForPicker(int $coId, string $mode, ?string $term): array // We only do this when there are relatively small numbers of results to // avoid making a bunch of database queries early in the search. - $matches = array(); + return $this->dataConstructForPicker($coId, $term,$coPersonIds); + } + + /** + * Construct picker(like) response data based on mode and term + * + * @param integer $coId CO ID + * @param string $mode Search mode to apply filters for + * @param array $coPersonIds List of PersonIds + * + * @return array Array of CO Person records + * @since COmanage Registry v4.4.0 + */ + public function dataConstructForPicker(int $coId, string $mode, array $coPersonIds): array + { + if(empty($coPersonIds)) { + return []; + } + + $this->CoPerson = ClassRegistry::init('CoPerson'); + $this->Co = ClassRegistry::init('Co'); + + $matches = []; if(count($coPersonIds) > 100) { // We don't return large sets to avoid slow performance diff --git a/View/Elements/actAsPeopleAutocomplete.ctp b/View/Elements/ActAsPeopleAutocomplete.ctp similarity index 97% rename from View/Elements/actAsPeopleAutocomplete.ctp rename to View/Elements/ActAsPeopleAutocomplete.ctp index 67a0f85..26a951a 100644 --- a/View/Elements/actAsPeopleAutocomplete.ctp +++ b/View/Elements/ActAsPeopleAutocomplete.ctp @@ -78,7 +78,7 @@ $suffix = Configure::read('debug') > 0 ? '?time=' . time() : ''; co: , glid: , coPersonId: , - mode: "", + mode: "", base: "webroot ?>grouper_lite_widget/grouper_groups", find: "webroot ?>grouper_lite_widget/grouper_groups/findSubscriber/co:/glid:", join: "webroot ?>grouper_lite_widget/grouper_groups/joinGroup/co:/glid:", @@ -116,6 +116,7 @@ $suffix = Configure::read('debug') > 0 ? '?time=' . time() : ''; formData.append("act_as_co_person_id", id); formData.append("co_person_id", this.api.coPersonId); formData.append("co_grouper_lite_widget_id", this.api.glid); + formData.append("fullname", label); // Request URL const urlString = window.location.protocol + "//" + window.location.host + this.api.addActAs; @@ -141,9 +142,11 @@ $suffix = Configure::read('debug') > 0 ? '?time=' . time() : ''; this.loading = false; return } - generateFlash('Act As User Enabled', 'success'); + // generateFlash('Act As User Enabled', 'success'); this.rawData = await resp.json(); - this.loading = false; + console.log(this.rawData) + this.loading = false + window.location.reload(); // Force reload here }, } diff --git a/View/Elements/ActionItem.ctp b/View/Elements/ActionItem.ctp new file mode 100644 index 0000000..518ef4d --- /dev/null +++ b/View/Elements/ActionItem.ctp @@ -0,0 +1,61 @@ + + + + +
+
+
+ +
+ +
+ +
+
+ Form->create('ActAsPeople', [ + 'id' => 'ActAsPeopleDeleteForm' . $person['value'], + 'inputDefaults' => [ + 'label' => false, + 'div' => false + ], + 'url' => [ + 'plugin' => 'grouper_lite_widget', + 'controller' => 'act_as_people', + 'action' => 'delete', + 'co' => $vv_coid, + 'glid' => $vv_config['CoGrouperLiteWidget']['id'], + 'act_as_copersonid' => $person['value'], + 'copersonid' => $vv_copersonid + ], + 'type' => 'delete' + ]); + $options = [ + 'label' => 'Disable', + 'onclick' => 'javascript:handleDisable(event)', + 'class' => 'btn btn-grouper btn-fit btn-block btn-danger btn-sm m-1 text-nowrap member-del-btn', + ]; + echo $this->Form->end($options); + ?> +
diff --git a/View/Elements/ActionSideBar.ctp b/View/Elements/ActionSideBar.ctp new file mode 100644 index 0000000..a4abe2d --- /dev/null +++ b/View/Elements/ActionSideBar.ctp @@ -0,0 +1,2 @@ + 0 ? '?time=' . time() : '';
- element('actAsPeopleAutocomplete', + element('ActAsPeopleAutocomplete', compact('vv_config', 'vv_coid', 'vv_is_user_owner', 'htmlId') )?> -
- -
-
-
- John Doe -
- -
- Identifier (I2CollabPN): nickmastoris.mastoris@at.in... -
-
- - -
+ +
+ + element('ActionItem', compact('person')) ?> + +
diff --git a/webroot/css/co-grouper-base.css b/webroot/css/co-grouper-base.css index 836c05c..f501f8b 100644 --- a/webroot/css/co-grouper-base.css +++ b/webroot/css/co-grouper-base.css @@ -123,6 +123,10 @@ animation: fadeInHalf 0.9s -0.3s infinite reverse; } +.grouper_groups .person-item { + overflow-wrap: anywhere; +} + .popover { max-width: 400px; }