2 [% ctx.page_title = "Triggered Event Log" %]
3 <script type="text/javascript">
4 dojo.require("dijit.form.Button");
5 dojo.require("dojo.data.ItemFileReadStore");
6 dojo.require("openils.CGI");
7 dojo.require("openils.widget.FlattenerGrid");
8 dojo.require("openils.widget.OrgUnitFilteringSelect");
9 dojo.require("openils.widget.ProgressDialog");
11 /* If you want to expand this list of supported core_types, you must also
12 change openils.widget._FSBuilder.CoreType further down, so that it
13 includes labels for these in its data store for filter widget
15 var initial_query = {"core_type": ["circ", "ahr"]};
17 /* Pre-filter by patron ID or copy ID if those are passed in as CGI
18 parameters. It's an either-or proposition for now. */
19 var cgi = new openils.CGI();
20 var patron_id = cgi.param("patron_id");
21 var copy_id = cgi.param("copy_id");
23 /* These features depends on target_{circ,hold}_{patron,copy}_id fields
24 being present in map_extras later. */
26 initial_query["-or"] = {
27 "target_circ_patron_id": patron_id,
28 "target_hold_patron_id": patron_id
30 openils.Util.addOnLoad(
31 function() { openils.Util.show("patron_specific", "inline"); }
34 initial_query["-or"] = {
35 "target_circ_copy_id": copy_id,
36 "target_hold_copy_id": copy_id
38 openils.Util.addOnLoad(
39 function() { openils.Util.show("copy_specific", "inline"); }
43 /* This semaphore business exists to prevent a race condition. Both
44 the OrgUnitFilteringSelect and the FlattenerFilterPane try to refresh
45 the grid when they're done loading, but that doesn't need to happen
46 until they're /both/ done loading. */
47 var _filter_semaphore_ctr = 2;
48 function filter_semaphore() { return --_filter_semaphore_ctr <= 0; }
49 function filter_semaphore_callback() {
50 grid.fetchLock = false;
51 grid.filterUi.doApply();
56 /* This and its subclasses exist because *FilterPane expect things that
57 act like AutoFieldWidget, which is a widget /builder/. */
59 "openils.widget._FSBuilder", null, {
64 "constructor": function(args) {
65 dojo.mixin(this, args);
69 var dijitArgs = dojo.mixin(
71 "store": this.store || this.storeBuilder(),
74 "searchAttr": "label",
79 new dijit.form.FilteringSelect(dijitArgs, this.parentNode);
85 "openils.widget._FSBuilder.Reactor",
86 [openils.widget._FSBuilder], {
87 "storeBuilder": function() {
88 _reactors_cache = _reactors_cache ||
89 fieldmapper.standardRequest(
90 ["open-ils.actor", "open-ils.actor.action_trigger.reactors.all_in_use"],
91 { "params": [openils.User.authtoken] }
93 return new dojo.data.ItemFileReadStore({
96 "items": _reactors_cache.map(
97 function(o) { return {"name": o, "label": o}; }
106 "openils.widget._FSBuilder.CoreType",
107 [openils.widget._FSBuilder], {
108 "store": new dojo.data.ItemFileReadStore({
110 "identifier": "name",
111 "items": [ /* XXX i18n */
112 {"name": "circ", "label": "Circulation"},
113 {"name": "ahr", "label": "Hold"}
121 "openils.widget._FSBuilder.EventState",
122 [openils.widget._FSBuilder], {
123 "store": new dojo.data.ItemFileReadStore({
125 "identifier": "name",
126 "items": [ /* XXX i18n */
127 {"name": "found", "label": "Found"},
128 {"name": "collected", "label": "Collected"},
129 {"name": "invalid", "label": "Invalid"},
130 {"name": "pending", "label": "Pending"},
131 {"name": "reacting", "label": "Reacting"},
132 {"name": "complete", "label": "Complete"},
133 {"name": "error", "label": "Error"}
140 /* Various things with which to initialize FlattenerGrid. */
142 "core_type": {"path": "hook.core_type", "filter": true},
143 "perm_lib": {"path": "perm_lib", "filter": true},
144 "target_circ_patron_id": {"path": "target_circ.usr", "filter": true},
145 "target_hold_patron_id": {"path": "target_hold.usr", "filter": true},
146 "target_circ_copy_id":{"path":"target_circ.target_copy","filter":true},
147 "target_hold_copy_id":{"path":"target_hold.current_copy","filter":true}
150 var filter_initializers = [
151 {"field": "state", "operator": "=", "value": "complete"},
152 {"field": "core_type", "operator": "=", "value": "circ"}
155 var filter_widget_builders = {
156 "ath:core_type": openils.widget._FSBuilder.CoreType,
157 "atul:state": openils.widget._FSBuilder.EventState,
158 "atul:reactor": openils.widget._FSBuilder.Reactor,
161 function print_all() {
163 if ((n = parseInt(prompt('[% l("Up to how many rows?") %]','100'))) > 0)
167 function act_on_events(id_list, action) {
168 console.log(id_list);
169 var method = "open-ils.actor.user.event." + action + ".batch";
170 if (id_list.length < 1) {
171 alert("[% l('You selected nothing.') %]");
176 progress_dialog.show(true);
177 fieldmapper.standardRequest(
178 ["open-ils.actor", method], {
180 "params": [openils.User.authtoken, id_list],
181 "onresponse": function(r) {
182 if (r = openils.Util.readResponse(r)) {
183 progress_dialog.update(
184 {"maximum": id_list.length, "progress": ++count}
188 "oncomplete": function(r) {
189 progress_dialog.hide();
190 r = openils.Util.readResponse(r);
197 /* The callback fired when the OrgUnitFilteringSelect is changed */
198 function set_grid_query_from_org_selector() {
199 /* Naughty: shouldn't use _baseQuery like this, but need to rethink
200 multiple competing filtering mechanisms. */
201 grid._baseQuery.perm_lib = aou.descendantNodeList(
202 org_selector.attr("value"), /* as id */ true
205 /* But for the persistent filter UI, this would be grid.refresh() */
206 if (filter_semaphore()) /* avoid race between ou selector and other
208 filter_semaphore_callback();
211 /* Builds a OrgUnitFilteringSelect limited to org units where you have
212 a given permission. */
213 function prepare_org_selector(perm) {
214 new openils.User().buildPermOrgSelector(
215 perm, org_selector, null,
218 org_selector, "onChange", set_grid_query_from_org_selector
220 set_grid_query_from_org_selector();
225 openils.Util.addOnLoad(
227 prepare_org_selector("VIEW_TRIGGER_EVENT");
231 <div dojoType="dijit.layout.ContentPane" layoutAlign="client">
232 <div dojoType="dijit.layout.ContentPane"
233 layoutAlign="top" class="oils-header-panel">
236 <span id="copy_specific" class="hidden">([% l('copy specific') %])</span>
237 <span id="patron_specific" class="hidden">([% l('patron specific') %])</span>
240 <button dojoType="dijit.form.Button"
241 onClick="act_on_events(grid.getSelectedIDs(), 'reset');">[% l('Reset Selected Events') %]</button>
242 <button dojoType="dijit.form.Button"
243 onClick="act_on_events(grid.getSelectedIDs(), 'cancel');">[% l('Cancel Selected Events') %]</button>
244 <button dojoType="dijit.form.Button"
245 onClick="grid.printSelected();">[% l('Print Selected Events') %]</button>
246 <button dojoType="dijit.form.Button"
247 onClick="print_all();">[% l('Print All Events') %]</button>
250 <div class="oils-acq-basic-roomy">
251 <label for="org_selector">[% l('Show events at and below') %]:</label>
253 id="org_selector" jsId="org_selector"
254 dojoType="openils.widget.OrgUnitFilteringSelect"
255 searchAttr="name" labelAttr="name">
259 <div style="float: left; width: 66%;">
262 dojoType="openils.widget.FlattenerGrid"
263 columnPersistKey='"ui.grid_columns.actor.user.event_log"'
267 showLoadFilter="true"
268 filterAlwaysInDiv="'filter_holder'"
269 filterInitializers="filter_initializers"
270 filterWidgetBuilders="filter_widget_builders"
271 filterSemaphore="filter_semaphore"
272 filterSemaphoreCallback="filter_semaphore_callback"
274 autoFieldFields="['target_hold','target_circ']"
275 defaultSort="['run_time']"
276 mapExtras="map_extras"
278 query="initial_query">
281 <th field="name" fpath="name" ffilter="true">Event Name</th>
282 <th field="reactor" fpath="reactor" ffilter="true"></th>
283 <th field="run_time" fpath="run_time" ffilter="true"></th><!-- XXX TODO formatters for *_time -->
284 <th field="add_time" fpath="add_time" ffilter="true" _visible="false"></th>
285 <th field="start_time" fpath="start_time" ffilter="true" _visible="false"></th>
286 <th field="update_time" fpath="update_time" ffilter="true" _visible="false"></th>
287 <th field="complete_time" fpath="complete_time" ffilter="true" _visible="false"></th>
288 <th field="id" fpath="id" ffilter="true" _visible="false"></th>
289 <th field="state" fpath="state" ffilter="true"></th>
290 <th field="target_circ_copy_barcode" fpath="target_circ.target_copy.barcode" ffilter="true">Target Circulation - Copy Barcode</th>
291 <th field="target_circ_copy_title" fpath="target_circ.target_copy.call_number.record.simple_record.title">Target Circulation - Title</th>
292 <th field="target_circ_copy_author" fpath="target_circ.target_copy.call_number.record.simple_record.author">Target Circulation - Author</th>
293 <th field="target_circ_patron_barcode" fpath="target_circ.usr.card.barcode" ffilter="true">Target Circulation - Patron Barcode</th>
294 <th field="target_hold_copy_title" fpath="target_hold.current_copy.call_number.record.simple_record.title">Target Hold - Title</th>
295 <th field="target_hold_copy_author" fpath="target_hold.current_copy.call_number.record.simple_record.author">Target Hold - Author</th>
296 <th field="target_hold_patron_barcode" fpath="target_hold.usr.card.barcode" ffilter="true">Target Hold - Patron Barcode</th>
301 <div style="float: right; width: 33%;">
302 <div id="filter_holder"></div>
304 <div style="clear: both;"></div>
307 <div dojoType="openils.widget.ProgressDialog" jsId="progress_dialog"></div>