Skip to content

Commit

Permalink
moved delete and act as use preview in a vue app.
Browse files Browse the repository at this point in the history
  • Loading branch information
Ioannis committed Apr 4, 2024
1 parent 29082fe commit d4aa2fc
Show file tree
Hide file tree
Showing 6 changed files with 216 additions and 72 deletions.
40 changes: 27 additions & 13 deletions Controller/ActAsPeopleController.php
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ public function add(): void
if($ret) {
$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']);
$this->Flash->set("Act As {$fullName} Enabled" , ['key' => 'success']);

$args = [];
$args['conditions']['ActAsPerson.id'] = $this->ActAsPerson->id;
Expand Down Expand Up @@ -159,12 +159,12 @@ public function add(): void

public function delete():void
{
$this->layout = null;
$this->autoRender = false;
$this->request->allowMethod('ajax');
$this->layout = 'ajax';

if(!$this->request->is('delete')
|| $this->request->is('ajax')
|| $this->request->is('restful')) {
&& !$this->request->is('ajax')
) {
throw new RuntimeException('HTTP Method Not Allowed', HttpStatusCodesEnum::HTTP_METHOD_NOT_ALLOWED);
}

Expand All @@ -190,19 +190,33 @@ public function delete():void

$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']);
$error = filter_var($e->getMessage(),FILTER_SANITIZE_SPECIAL_CHARS);
$this->Api->restResultHeader(HttpStatusCodesEnum::HTTP_INTERNAL_SERVER_ERROR, 'Other Error');
$this->set(compact('error'));
$this->set('_serialize', 'error');
return;
}

// Set flash message
if($ret) {
$this->Flash->set(_txt('er.deleted-a', ['Person']) , ['key' => 'success']);
} else {
$this->Flash->set(_txt('er.delete'), ['key' => 'error']);
if(!$ret) {
$error = ErrorsEnum::NotDeleted;
$this->Api->restResultHeader(HttpStatusCodesEnum::HTTP_BAD_REQUEST, 'Bad Request');
$this->set(compact('error'));
$this->set('_serialize', 'error');
return;
}

// Redirect back to the plugin
$this->redirect($redirect);
// We will register a Flash message here. The frontend will reload and it will be rendered
$this->Flash->set('Act As Disabled', ['key' => 'success']);

// We do not redirect but we pass data back to the frontend because we
// want to keep the view structure as simple as possible. If we redirect we will
// have to add more JSON view infrastructure. We will let the frontend
// handle the redirect
$this->Api->restResultHeader(HttpStatusCodesEnum::HTTP_OK, 'Success');
$success = ['status' => 'Success', 'message' => 'Succeeded'];
$this->set(compact('success'));
$this->set('_serialize', 'success');
}


Expand Down
2 changes: 1 addition & 1 deletion Lib/enum.php
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<?php

class ErrorsEnum {
const Conflict = ['status' => 'ERROR', 'message' => 'Already Exists'];
const Error = ['status' => 'ERROR', 'message' => 'Error'];
const Exception = ['status' => 'ERROR', 'message' => 'Exception'];
const NoAccess = ['status' => 'ERROR', 'message' => 'No Access'];
const NotAdded = ['status' => 'ERROR', 'message' => 'Not Added'];
const Conflict = ['status' => 'ERROR', 'message' => 'Already Exists'];
const NotDeleted = ['status' => 'ERROR', 'message' => 'Not Deleted'];
}

Expand Down
5 changes: 3 additions & 2 deletions View/Elements/ActAsPeopleAutocomplete.ctp
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,9 @@ $suffix = Configure::read('debug') > 0 ? '?time=' . time() : '';
return
}
this.rawData = await resp.json();
this.loading = false

// Since we are reloading, we do not want to stop the spinner
// this.loading = false

// Force reload here
window.location.reload();
},
Expand Down
233 changes: 179 additions & 54 deletions View/Elements/ActionItem.ctp
Original file line number Diff line number Diff line change
@@ -1,61 +1,186 @@
<?php
// Action Item Element
$vv_act_as_people = $vv_act_as_people ?? [];
$suffix = Configure::read('debug') > 0 ? '?time=' . time() : '';

?>

<script type="text/javascript">
function handleActionRedirect(event) {
event.preventDefault();
const input = event.target
input.setAttribute('disabled', '')
const form = input.closest('Form')
// Get the current controller
const url = new URL(window.location)
let controller = url.pathname.replace('<?= $this->webroot ?>', '')
.replace('grouper_lite_widget/', '')
.replace('grouper_groups/', '')
.split('/')[0]
// Add the extra named parameter and resubmit the form
form.action += `/redirect_act:${controller}`
form.submit();
<script type="module">
import Loader from '<?= $this->webroot ?>grouper_lite_widget/js/loader.js<?= $suffix ?>';

const provided = {
collapsed: <?= $vv_config['CoGrouperLiteWidget']['default_collapse'] == 'collapsed' ? 'true' : 'false' ?>,
optAction: "<?= $optAction ?? 'none' ?>",
owner: <?= $vv_is_user_owner ? 'true' : 'false' ?>,
url: "<?= $actionUrl ?? 'null' ?>",
view: "<?= $this->action ?>",
hasActAs: <?= (int)!empty($vv_act_as_people) ?>,
actAsPerson: <?= json_encode($vv_act_as_people ?? []) ?>,
permissions: <?= json_encode($permissions, JSON_THROW_ON_ERROR) ?>,
txt: {
adhocHeading: "<?= $vv_config['CoGrouperLiteWidget']['adhoc_heading'] ?? 'Ad-hoc groups' ?>",
wgHeading: "<?= $vv_config['CoGrouperLiteWidget']['wg_heading'] ?? 'Working groups' ?>",
search: "<?= _txt('pl.grouperlite.title.search') ?>",
searchForGroups: "<?= _txt('pl.grouperlite.action.search') ?>",
display: "<?= _txt('fd.page.limit.display') ?>",
records: "<?= _txt('fd.page.limit.records') ?>",
first: "<?= _txt('op.first') ?>",
last: "<?= _txt('op.last') ?>",
previous: "<?= _txt('op.previous') ?>",
next: "<?= _txt('op.next') ?>",
groups: "<?= _txt('pl.grouperlite.dashboard.heading.groups') ?>",
grouper: "<?= _txt('pl.grouperlite.action.grouper') ?>",
leave: "<?= _txt('pl.grouperlite.action.leave') ?>",
zero: {
description: "<?= _txt('pl.grouperlite.value.descr.zerostate') ?>",
records: "<?= _txt('pl.grouperlite.groups.zero-state') ?>"
},
members: "<?= _txt('pl.grouperlite.action.members') ?>",
email: "<?= _txt('pl.grouperlite.value.email') ?>",
enableActAs: "<?= _txt('pl.grouperlite.action.enable') ?>",
close: "<?= _txt('pl.grouperlite.action.close') ?>",
remove: "<?= _txt('pl.grouperlite.action.remove-user') ?>",
addUser: "<?= _txt('pl.grouperlite.action.add-user') ?>",
addSubscriberError: "<?= _txt('pl.grouperlite.message.flash.add-subscriber-failed') ?>",
addSubscriberSuccess: "<?= _txt('pl.grouperlite.message.flash.add-subscriber-success') ?>",
removeSubscriberError: "<?= _txt('pl.grouperlite.message.flash.remove-subscriber-failed') ?>",
removeSubscriberSuccess: "<?= _txt('pl.grouperlite.message.flash.remove-subscriber-success') ?>",
getSubscriberError: "<?= _txt('pl.grouperlite.message.flash.group-detail-members-failed') ?>",
peoplePickerPlaceHolder: "<?= _txt('op.grm.add.placeholder') ?>",
memberships: "<?= _txt('pl.grouperlite.action.memberships') ?>",
noaccess: "<?= _txt('pl.grouperlite.members.noaccess') ?>",
empty: "<?= _txt('pl.grouperlite.members.empty') ?>",
join: "<?= _txt('pl.grouperlite.action.join') ?>",
joinSuccess: "<?= _txt('pl.grouperlite.message.flash.join-group-success') ?>",
joinFailure: "<?= _txt('pl.grouperlite.message.flash.join-group-failed') ?>",
joinError: "<?= _txt('pl.grouperlite.message.flash.join-group-error') ?>",
leaveSuccess: "<?= _txt('pl.grouperlite.message.flash.leave-group-success') ?>",
leaveFailure: "<?= _txt('pl.grouperlite.message.flash.leave-group-failure') ?>",
leaveError: "<?= _txt('pl.grouperlite.message.flash.leave-group-error') ?>",
tabs: {
memberships: "<?= _txt('pl.grouperlite.nav.memberships') ?>",
optin: "<?= _txt('pl.grouperlite.nav.groups-can-join') ?>",
owner: "<?= _txt('pl.grouperlite.nav.groups-presided') ?>",
manager: "<?= _txt('pl.grouperlite.nav.users-presided') ?>",
},
columns: <?= json_encode(['name' => _txt('pl.grouperlite.table.name'),
'role' => _txt('pl.grouperlite.table.role'),
'description' => _txt('pl.grouperlite.table.description'),
'status' => _txt('pl.grouperlite.table.status'),
'action' => _txt('pl.grouperlite.table.action')],
JSON_THROW_ON_ERROR) ?>,
},
api: {
co: <?= $vv_coid ?>,
glid: <?= $vv_config['CoGrouperLiteWidget']['id'] ?>,
coPersonId: <?= $vv_copersonid ?>,
mode: "<?= $vv_picker_mode ?>",
webroot: "<?= $this->webroot ?>",
base: "<?= $this->webroot ?>grouper_lite_widget/grouper_groups",
find: "<?= $this->webroot ?>grouper_lite_widget/grouper_groups/findSubscriber/co:<?= $vv_coid ?>/glid:<?= $vv_config['CoGrouperLiteWidget']['id'] ?>",
join: "<?= $this->webroot ?>grouper_lite_widget/grouper_groups/joinGroup/co:<?= $vv_coid ?>/glid:<?= $vv_config['CoGrouperLiteWidget']['id'] ?>",
leave: "<?= $this->webroot ?>grouper_lite_widget/grouper_groups/leaveGroup/co:<?= $vv_coid ?>/glid:<?= $vv_config['CoGrouperLiteWidget']['id'] ?>",
remove: "<?= $this->webroot ?>grouper_lite_widget/grouper_groups/removeSubscriber/co:<?= $vv_coid ?>/glid:<?= $vv_config['CoGrouperLiteWidget']['id'] ?>",
add: "<?= $this->webroot ?>grouper_lite_widget/grouper_groups/addSubscriber/co:<?= $vv_coid ?>/glid:<?= $vv_config['CoGrouperLiteWidget']['id'] ?>",
addActAs: "<?= $this->webroot ?>grouper_lite_widget/act_as_people/add/co:<?= $vv_coid ?>/glid:<?= $vv_config['CoGrouperLiteWidget']['id'] ?>",
deleteActAs: "<?= $this->webroot ?>grouper_lite_widget/act_as_people/delete/co:<?= $vv_coid ?>/glid:<?= $vv_config['CoGrouperLiteWidget']['id'] ?>",
group: "<?= $this->webroot ?>grouper_lite_widget/grouper_groups/groupSubscribers/co:<?= $vv_coid ?>/glid:<?= $vv_config['CoGrouperLiteWidget']['id'] ?>",
memberships: "<?= $this->webroot ?>grouper_lite_widget/grouper_groups/groupmemberapi/co:<?= $vv_coid ?>/glid:<?= $vv_config['CoGrouperLiteWidget']['id'] ?>",
managing: "<?= $this->webroot ?>grouper_lite_widget/grouper_groups/usermanagerapi/co:<?= $vv_coid ?>/glid:<?= $vv_config['CoGrouperLiteWidget']['id'] ?>",
optin: "<?= $this->webroot ?>grouper_lite_widget/grouper_groups/groupoptinapi/co:<?= $vv_coid ?>/glid:<?= $vv_config['CoGrouperLiteWidget']['id'] ?>",
owner: "<?= $this->webroot ?>grouper_lite_widget/grouper_groups/groupownerapi/co:<?= $vv_coid ?>/glid:<?= $vv_config['CoGrouperLiteWidget']['id'] ?>",
},
}

const app = Vue.createApp({
data() {
return {
loading: false,
person: <?= json_encode($person) ?>,
response: []
}
},
components: {
Loader
},
inject: ['txt', 'api'],
methods: {
async disableActAsUser() {
debugger
const { identifier: ident, label, value: id } = this.person;
this.loading = true

const currentUrl = new URL(window.location)
let controller = currentUrl.pathname.replace('<?= $this->webroot ?>', '')
.replace('grouper_lite_widget/', '')
.replace('grouper_groups/', '')
.split('/')[0]

// Request URL
const urlString = window.location.protocol + "//"
+ window.location.host
+ this.api.deleteActAs
+ `/act_as_copersonid:${id}`
+ `/copersonid:${this.api.coPersonId}`
+ `/redirect_act:${controller}`
const url = new URL(urlString);

// AJAX Request
const request = new Request(url, {
headers: new Headers({
'X-Requested-With': 'XMLHttpRequest', // Ajax Request Header
"Accept": "application/json",
}),
method: "DELETE"
});

// Fire request
const resp = await (fetch(request).catch(error => generateFlash('Network Error', 'error')));

if (!resp.ok) {
generateFlash(`Disable ActAs ${this.person.label} failed`, 'error');
let errorResponse = await resp.json();
this.loading = false
return
}
this.response = await resp.json();
// Since we are reloading, we do not want to stop the spinner
// this.loading = false

// Force reload here
window.location.reload();
},
},
template: `
<Loader :active="loading"/>
<div v-if="!loading" class="person-item d-inline-flex w-100 justify-content-between align-items-center">
<div class="cm-ac-item-wrapper w-75">
<div class="cm-ac-name">
<a :href="this.api.webroot + 'co_people/canvas/' + person.value"
class="spin ignore-invalid">{{ this.person.label }}
</a>
</div>
<div class="cm-ac-subitem cm-ac-email">
<span class="cm-ac-label"><b>{{ this.person.emailLabel }}</b></span>{{ this.person.emailShort }}
</div>
<div class="cm-ac-subitem cm-ac-id">
<span class="cm-ac-label"><b>{{ this.person.identifierLabel }}</b></span>{{ this.person.identifierShort }}
</div>
</div>
<button type="submit"
@click="disableActAsUser()"
class="btn btn-grouper w-25 btn-fit btn-block btn-danger btn-sm m-1 text-nowrap member-del-btn">Disable</button
</div>
`
});

app.config.unwrapInjectedRef = true;
// For core configurations and texts globally
for (const [key, value] of Object.entries(provided)) {
app.provide( key, value);
}
// Mount the component and provide a global reference for this app instance.
app.mount("#action-item-container-<?= $person['value']?>");
</script>

<div class="person-item d-inline-flex w-100 justify-content-between align-items-center">
<div class="cm-ac-item-wrapper w-75">
<div class="cm-ac-name">
<a href="<?= $this->webroot ?>co_people/canvas/3054" class="spin ignore-invalid"><?= $person['label']?></a>
</div>
<div class="cm-ac-subitem cm-ac-email">
<span class="cm-ac-label"><b><?= $person['emailLabel']?></b></span><?= $person['emailShort']?>
</div>
<div class="cm-ac-subitem cm-ac-id">
<span class="cm-ac-label"><b><?= $person['identifierLabel']?></b></span><?= $person['identifierShort']?>
</div>
</div>
<?php
print $this->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:handleActionRedirect(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);
?>
</div>
<span id="action-item-container-<?= $person['value']?>"></span>

4 changes: 2 additions & 2 deletions View/Elements/ActionSideBar.ctp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
})
</script>

<div id="right-sidebar">
<aside id="right-sidebar">
<div class="sidebar-content">
<div class="font-weight-bold d-inline-flex align-items-center w-100">
<em class="material-icons lg" aria-hidden="true">transfer_within_a_station</em>
Expand Down Expand Up @@ -36,6 +36,6 @@
<?php endif; ?>
<hr>
</div>
</div>
</aside>


4 changes: 4 additions & 0 deletions webroot/css/co-grouper-base.css
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@
color: var(--link-hover);
}

.btn-grouper {
min-width: fit-content;
}

#subscribers.loading .loader {
display: block;
}
Expand Down

0 comments on commit d4aa2fc

Please sign in to comment.