2 [% ctx.page_title = l("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": "[% l('Circulation') %]"},
113 {"name": "ahr", "label": "[% l('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": "[% l('Found') %]"},
128 {"name": "collected", "label": "[% l('Collected') %]"},
129 {"name": "invalid", "label": "[% l('Invalid') %]"},
130 {"name": "pending", "label": "[% l('Pending') %]"},
131 {"name": "reacting", "label": "[% l('Reacting') %]"},
132 {"name": "complete", "label": "[% l('Complete') %]"},
133 {"name": "error", "label": "[% l('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 grid.baseQuery.perm_lib = aou.descendantNodeList(
200 org_selector.attr("value"), /* as id */ true
203 /* But for the persistent filter UI, this would be grid.filter()
204 and grid.refresh() */
205 if (filter_semaphore()) /* avoid race between ou selector and other
207 filter_semaphore_callback();
210 /* Builds a OrgUnitFilteringSelect limited to org units where you have
211 a given permission. */
212 function prepare_org_selector(perm) {
213 new openils.User().buildPermOrgSelector(
214 perm, org_selector, null,
217 org_selector, "onChange", set_grid_query_from_org_selector
219 set_grid_query_from_org_selector();
224 openils.Util.addOnLoad(
226 prepare_org_selector("VIEW_TRIGGER_EVENT");
230 <div dojoType="dijit.layout.ContentPane" layoutAlign="client">
231 <div dojoType="dijit.layout.ContentPane"
232 layoutAlign="top" class="oils-header-panel">
235 <span id="copy_specific" class="hidden">([% l('copy specific') %])</span>
236 <span id="patron_specific" class="hidden">([% l('patron specific') %])</span>
239 <button dojoType="dijit.form.Button"
240 onClick="act_on_events(grid.getSelectedIDs(), 'reset');">[% l('Reset Selected Events') %]</button>
241 <button dojoType="dijit.form.Button"
242 onClick="act_on_events(grid.getSelectedIDs(), 'cancel');">[% l('Cancel Selected Events') %]</button>
243 <button dojoType="dijit.form.Button"
244 onClick="grid.printSelected();">[% l('Print Selected Events') %]</button>
245 <button dojoType="dijit.form.Button"
246 onClick="print_all();">[% l('Print All Events') %]</button>
249 <div class="oils-acq-basic-roomy">
250 <label for="org_selector">[% l('Show events at and below') %]:</label>
252 id="org_selector" jsId="org_selector"
253 dojoType="openils.widget.OrgUnitFilteringSelect"
254 searchAttr="name" labelAttr="name">
258 <div style="float: left; width: 66%;">
261 dojoType="openils.widget.FlattenerGrid"
262 columnPersistKey='"ui.grid_columns.actor.user.event_log"'
266 showLoadFilter="true"
267 filterAlwaysInDiv="'filter_holder'"
268 filterInitializers="filter_initializers"
269 filterWidgetBuilders="filter_widget_builders"
270 filterSemaphore="filter_semaphore"
271 filterSemaphoreCallback="filter_semaphore_callback"
273 autoFieldFields="['target_hold','target_circ']"
274 defaultSort="['run_time']"
275 mapExtras="map_extras"
277 query="initial_query">
280 <th field="name" fpath="name" ffilter="true">[% l('Event Name') %]</th>
281 <th field="reactor" fpath="reactor" ffilter="true"></th>
282 <th field="run_time" fpath="run_time" ffilter="true"></th><!-- XXX TODO formatters for *_time -->
283 <th field="add_time" fpath="add_time" ffilter="true" _visible="false"></th>
284 <th field="start_time" fpath="start_time" ffilter="true" _visible="false"></th>
285 <th field="update_time" fpath="update_time" ffilter="true" _visible="false"></th>
286 <th field="complete_time" fpath="complete_time" ffilter="true" _visible="false"></th>
287 <th field="id" fpath="id" ffilter="true" _visible="false"></th>
288 <th field="state" fpath="state" ffilter="true"></th>
289 <th field="target_circ_copy_barcode" fpath="target_circ.target_copy.barcode" ffilter="true">[% l('Target Circulation - Copy Barcode') %]</th>
290 <th field="target_circ_copy_title" fpath="target_circ.target_copy.call_number.record.simple_record.title">[% l('Target Circulation - Title') %]</th>
291 <th field="target_circ_copy_author" fpath="target_circ.target_copy.call_number.record.simple_record.author">[% l('Target Circulation - Author') %]</th>
292 <th field="target_circ_patron_barcode" fpath="target_circ.usr.card.barcode" ffilter="true">[% l('Target Circulation - Patron Barcode') %]</th>
293 <th field="target_hold_copy_title" fpath="target_hold.current_copy.call_number.record.simple_record.title">[% l('Target Hold - Title') %]</th>
294 <th field="target_hold_copy_author" fpath="target_hold.current_copy.call_number.record.simple_record.author">[% l('Target Hold - Author') %]</th>
295 <th field="target_hold_patron_barcode" fpath="target_hold.usr.card.barcode" ffilter="true">[% l('Target Hold - Patron Barcode') %]</th>
300 <div style="float: right; width: 33%;">
301 <div id="filter_holder"></div>
303 <div style="clear: both;"></div>
306 <div dojoType="openils.widget.ProgressDialog" jsId="progress_dialog"></div>