From: Bill Erickson Date: Fri, 25 May 2012 13:22:36 +0000 (-0400) Subject: Search filter groups admin UI / API X-Git-Tag: sprint4-merge-nov22~3909 X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=42505e6c89ef51cdba62d112222739114e8de8dd;p=working%2FEvergreen.git Search filter groups admin UI / API UI for managing search filter groups and group entries. This inclues a new API call for performing CRUD actions on filter group entries: open-ils.actor.filter_group_entry.crud This new API call was necessary because entries link to actor.search_query's, whose write access cannot be controled by pcrud. Signed-off-by: Bill Erickson Signed-off-by: Kathy Lussier Signed-off-by: Dan Scott --- diff --git a/Open-ILS/examples/fm_IDL.xml b/Open-ILS/examples/fm_IDL.xml index 71706383d8..eb75532675 100644 --- a/Open-ILS/examples/fm_IDL.xml +++ b/Open-ILS/examples/fm_IDL.xml @@ -4934,13 +4934,13 @@ SELECT usr, - + - + diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Actor.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Actor.pm index 50cff13551..660cebd2e7 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Actor.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Actor.pm @@ -4644,4 +4644,116 @@ sub get_all_at_reactors_in_use { return [ map { $_->{reactor} } @$reactors ]; } +__PACKAGE__->register_method( + method => "filter_group_entry_crud", + api_name => "open-ils.actor.filter_group_entry.crud", + signature => { + desc => q/ + Provides CRUD access to filter group entry objects. These are not full accessible + via PCRUD, since they requre "asq" objects for storing the query, and "asq" objects + are not accessible via PCRUD (because they have no fields against which to link perms) + /, + params => [ + {desc => "Authentication token", type => "string"}, + {desc => "Entry ID / Entry Object", type => "number"}, + {desc => "Additional note text (optional)", type => "string"}, + {desc => "penalty org unit ID (optional, default to top of org tree)", + type => "number"} + ], + return => { + desc => "Entry fleshed with query on Create, Retrieve, and Uupdate. 1 on Delete", + type => "object" + } + } +); + +sub filter_group_entry_crud { + my ($self, $conn, $auth, $arg) = @_; + + return OpenILS::Event->new('BAD_PARAMS') unless $arg; + my $e = new_editor(authtoken => $auth, xact => 1); + return $e->die_event unless $e->checkauth; + + if (ref $arg) { + + if ($arg->isnew) { + + my $grp = $e->retrieve_actor_search_filter_group($arg->grp) + or return $e->die_event; + + return $e->die_event unless $e->allowed( + 'ADMIN_SEARCH_FILTER_GROUP', $grp->owner); + + my $query = $arg->query; + $query = $e->create_actor_search_query($query) or return $e->die_event; + $arg->query($query->id); + my $entry = $e->create_actor_search_filter_group_entry($arg) or return $e->die_event; + $entry->query($query); + + $e->commit; + return $entry; + + } elsif ($arg->ischanged) { + + my $entry = $e->retrieve_actor_search_filter_group_entry([ + $arg->id, { + flesh => 1, + flesh_fields => {asfge => ['grp']} + } + ]) or return $e->die_event; + + return $e->die_event unless $e->allowed( + 'ADMIN_SEARCH_FILTER_GROUP', $entry->grp->owner); + + my $query = $e->update_actor_search_query($arg->query) or return $e->die_event; + $arg->query($arg->query->id); + $e->update_actor_search_filter_group_entry($arg) or return $e->die_event; + $arg->query($query); + + $e->commit; + return $arg; + + } elsif ($arg->isdeleted) { + + my $entry = $e->retrieve_actor_search_filter_group_entry([ + $arg->id, { + flesh => 1, + flesh_fields => {asfge => ['grp', 'query']} + } + ]) or return $e->die_event; + + return $e->die_event unless $e->allowed( + 'ADMIN_SEARCH_FILTER_GROUP', $entry->grp->owner); + + $e->delete_actor_search_filter_group_entry($entry) or return $e->die_event; + $e->delete_actor_search_query($entry->query) or return $e->die_event; + + $e->commit; + return 1; + + } else { + + $e->rollback; + return undef; + } + + } else { + + my $entry = $e->retrieve_actor_search_filter_group_entry([ + $arg, { + flesh => 1, + flesh_fields => {asfge => ['grp', 'query']} + } + ]) or return $e->die_event; + + return $e->die_event unless $e->allowed( + ['ADMIN_SEARCH_FILTER_GROUP', 'VIEW_SEARCH_FILTER_GROUP'], + $entry->grp->owner); + + $e->rollback; + $entry->grp($entry->grp->id); # for consistency + return $entry; + } +} + 1; diff --git a/Open-ILS/src/templates/conify/global/actor/search_filter_group.tt2 b/Open-ILS/src/templates/conify/global/actor/search_filter_group.tt2 new file mode 100644 index 0000000000..4118015256 --- /dev/null +++ b/Open-ILS/src/templates/conify/global/actor/search_filter_group.tt2 @@ -0,0 +1,104 @@ +[% + WRAPPER base.tt2; + ctx.page_title = l('Search Filter Group'); + filter_group_id = ctx.page_args.0; +%] + + + +
+ + [% IF filter_group_id %] + +
+
[% l('Search Filter Group') %]
+
+ + +
+
+ + ↖ [% l('Return to Filter Groups') %] +

+ + + + + + + + + + + +
[% l('Label') %][% l('Query Text') %][% l('Sort Position') %][% l('ID') %]
+ + + + [% ELSE %] + +
+
[% l('Search Filter Group') %]
+
+ + +
+
+ + + + + + + + + + +
[% l('Code') %][% l('Owner') %][% l('Label') %][% l('Create Date') %]
+ +

+
[% l('To view groups for a different location, use the "Filter" option') %]
+ + [% END %] +
+ + + +[% END %] + + diff --git a/Open-ILS/web/js/ui/default/conify/global/actor/search_filter_group.js b/Open-ILS/web/js/ui/default/conify/global/actor/search_filter_group.js new file mode 100644 index 0000000000..3aadee78ae --- /dev/null +++ b/Open-ILS/web/js/ui/default/conify/global/actor/search_filter_group.js @@ -0,0 +1,182 @@ +dojo.require('dijit.form.TextBox'); +dojo.require('openils.Util'); +dojo.require('openils.User'); +dojo.require('fieldmapper.OrgUtils'); +dojo.require("openils.widget.FlattenerGrid"); +dojo.require('openils.widget.AutoFieldWidget'); +dojo.require('openils.PermaCrud'); + +var fgeEditLabel, fgeEditQuery, fgeEditPos; +var curEntry, ocHandler; + +// Builds an editor table for filter group entries +function showFgeEditor(fgeId, create) { + + dojo.addClass(fgeGrid.domNode, 'hidden'); + dojo.removeClass(dojo.byId('fge-edit-div'), 'hidden'); + + function cancelHandler() { + dojo.removeClass(fgeGrid.domNode, 'hidden'); + dojo.addClass(dojo.byId('fge-edit-div'), 'hidden'); + } + + if (!fgeEditLabel) { + + // first time loading the editor. build the widgets. + + fgeEditLabel = new openils.widget.AutoFieldWidget({ + fmField : 'label', + fmClass : 'asq', + parentNode : dojo.byId('fge-edit-label') + }); + + fgeEditLabel.build(); + + fgeEditQuery = new openils.widget.AutoFieldWidget({ + fmField : 'query_text', + fmClass : 'asq', + parentNode : dojo.byId('fge-edit-query') + }); + + fgeEditQuery.build(); + + fgeEditPos = new openils.widget.AutoFieldWidget({ + fmField : 'pos', + fmClass : 'asfge', + parentNode : dojo.byId('fge-edit-pos') + }); + + fgeEditPos.build(); + dojo.connect(fgeCancel, 'onClick', cancelHandler); + } + + var pcrud = new openils.PermaCrud({authtoken : openils.User.authtoken}); + + if (create) { + + curEntry = new fieldmapper.asfge(); + curEntry.isnew(true); + curEntry.grp(filterGroupId); + curEntry.query(new fieldmapper.asq()); + + fgeEditLabel.widget.attr('value', ''); + fgeEditQuery.widget.attr('value', ''); + fgeEditPos.widget.attr('value', ''); + + } else { + + // we're editing an existing entry, fetch it first + + curEntry = fieldmapper.standardRequest( + ['open-ils.actor', 'open-ils.actor.filter_group_entry.crud'], + {params : [openils.User.authtoken, fgeId], async : false} + ); + + fgeEditLabel.widget.attr('value', curEntry.query().label()); + fgeEditQuery.widget.attr('value', curEntry.query().query_text()); + fgeEditPos.widget.attr('value', curEntry.pos()); + curEntry.ischanged(true); + } + + if (ocHandler) dojo.disconnect(ocHandler); + ocHandler = dojo.connect(fgeSave, 'onClick', + function() { + + // creates / updates entries + + curEntry.query().label(fgeEditLabel.widget.attr('value')); + curEntry.query().query_text(fgeEditQuery.widget.attr('value')); + curEntry.pos(fgeEditPos.widget.attr('value')); + + var stat = fieldmapper.standardRequest( + ['open-ils.actor', 'open-ils.actor.filter_group_entry.crud'], + {params : [openils.User.authtoken, curEntry], async : false} + ); + + cancelHandler(); + fgeGrid.refresh(); + } + ); +} + +// deletes filter group entries (after fetching them first) +function fgeDelete() { + + dojo.forEach( + fgeGrid.getSelectedItems(), + function(item) { + + console.log(item); + var id = fgeGrid.store.getValue(item, 'id'); + + var entry = fieldmapper.standardRequest( + ['open-ils.actor', 'open-ils.actor.filter_group_entry.crud'], + {params : [openils.User.authtoken, id], async : false} + ); + + entry.isdeleted(true); + + var stat = fieldmapper.standardRequest( + ['open-ils.actor', 'open-ils.actor.filter_group_entry.crud'], + {params : [openils.User.authtoken, entry], async : false} + ); + } + ); + + fgeGrid.refresh(); +} + +// builds a link to show the editor table +function getFgeLabel(rowIdx, item) { + if (item) { + return { + id : this.grid.store.getValue(item, 'id'), + label : this.grid.store.getValue(item, 'query_label') + }; + } +} + +function formatFgeLabel(args) { + if (!args) return ''; + return '' + args.label + ''; +} + +// builds a link to this group's entries page +function getFgCode(rowIdx, item) { + if (item) { + return { + id : this.grid.store.getValue(item, 'id'), + code : this.grid.store.getValue(item, 'code') + }; + } +} + +function formatFgCode(args) { + if (!args) return ''; + return '' + args.code + ''; +} + +function load() { + + if (filterGroupId) { + + // entries grid loads itself from template data. + // nothing for us to do. + + } else { + + // filter groups by where we have edit permission + new openils.User().getPermOrgList( + ['ADMIN_SEARCH_FILTER_GROUP'], + function(list) { + fgGrid.query = {owner : list}; + fgGrid.refresh(); + fgGrid.suppressEditFields = ['id', 'create_date']; + }, + false, true + ); + } +} + +openils.Util.addOnLoad(load); +