2 # Copyright (C) 2008 Georgia Public Library Service / Equinox Software, Inc
3 # Mike Rylander <miker@esilibrary.com>
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License
7 # as published by the Free Software Foundation; either version 2
8 # of the License, or (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
16 "-//W3C//DTD XHTML 1.0 Transitional//EN"
17 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" [
18 <!--#include virtual="/opac/locale/${locale}/conify.dtd"-->
20 <html xmlns="http://www.w2.org/1999/xhtml">
22 <title>&conify.grp_tree.group_tree.title;</title>
24 <style type="text/css">
25 @import url('/js/dojo/dojox/grid/_grid/tundraGrid.css');
26 @import url('/js/dojo/dojo/resources/dojo.css');
27 @import url('/js/dojo/dijit/themes/tundra/tundra.css');
28 @import url('/js/dojo/dojox/widget/Toaster/Toaster.css');
36 margin: 0px 0px 0px 0px;
37 padding: 0px 0px 0px 0px;
62 <!-- The OpenSRF API writ JS -->
63 <script language='javascript' src='/opac/common/js/utils.js' type='text/javascript'></script>
64 <script language='javascript' src='/opac/common/js/Cookies.js' type='text/javascript'></script>
65 <script language='javascript' src='/opac/common/js/CGI.js' type='text/javascript'></script>
66 <script language='javascript' src='/opac/common/js/JSON_v1.js' type='text/javascript'></script>
68 <!-- Dojo goodness -->
69 <script type="text/javascript" src="../admin.js"></script>
70 <script type="text/javascript" src="/js/dojo/dojo/dojo.js"></script>
71 <script type="text/javascript" src="/js/dojo/dijit/dijit.js"></script>
73 <script type="text/javascript" src="grp_tree.js"></script>
77 <body class="tundra" id='pagebody'>
79 <div dojoType="dijit.layout.SplitContainer" orientation="horizontal" style="height: 100%">
81 <div dojoType="dijit.layout.ContentPane" sizeShare="100">
82 <script type="dojo/method">
84 window.dirtyStore = [];
86 server.pCRUD.request({
87 method : 'open-ils.permacrud.search.pgt.atomic',
89 params : [ ses, { id : { "!=" : null } }, { order_by : { pgt : 'name' } } ],
90 onerror : function (r) { status_update( pgt_strings.ERROR_FETCHING_GROUPS ) },
91 oncomplete : function (r) {
92 window._group_list = r.recv().content();
93 window._group_data = pgt.toStoreData( window._group_list );
94 window.group_store = new dojo.data.ItemFileWriteStore({ data : window._group_data });
95 window.group_store.onSet = function (item, attr, o, n) {
96 if (attr == 'ischanged') return;
98 this.setValue( item, 'ischanged', 1);
100 dojo.addOnUnload( function (event) {
102 window.group_store.fetch({
103 query : { ischanged : 1 },
104 queryOptions : { deep : true },
105 onItem : function (item, req) { try { if (this.isItem( item )) window.dirtyStore.push( item ); } catch (e) { /* meh */ } },
106 scope : window.group_store
109 if (dirtyStore.length > 0) {
110 var confirmation = confirm( pgt_strings.CONFIRM_EXIT );
113 for (var i in window.dirtyStore) {
114 window.current_group = window.dirtyStore[i];
124 server.actor.request({
125 method : 'open-ils.actor.org_types.retrieve',
127 onerror : function (r) { status_update( pgt_strings.ERROR_FETCHING_TYPES ) },
128 oncomplete : function (r) {
129 window._ou_type_list = r.recv().content();
130 window._ou_type_data = aout.toStoreData( window._ou_type_list );
131 window.ou_type_store = new dojo.data.ItemFileReadStore({ data : window._ou_type_data });
135 server.actor.request({
136 method : 'open-ils.actor.permissions.retrieve',
138 onerror : function (r) { status_update( pgt_strings.ERROR_FETCHING_PERMS ) },
139 oncomplete : function (r) {
141 window._perm_list = r.recv().content();
143 window._perm_data = ppl.toStoreData( window._perm_list, 'code' );
144 window._perm_name_data = ppl.toStoreData( window._perm_list, 'code', { identifier : 'code' } );
146 window.perm_store = new dojo.data.ItemFileWriteStore({ data : window._perm_data });
147 window.perm_name_store = new dojo.data.ItemFileWriteStore({ data : window._perm_name_data });
153 server.pCRUD.request({
154 method : 'open-ils.permacrud.search.pgpm.atomic',
156 params : [ ses, { id : { "!=" : null } } ],
157 onerror : function (r) { status_update( pgt_strings.ERROR_FETCHING_PERM_MAPS ) },
158 oncomplete : function (r) {
159 window._perm_map_list = r.recv().content();
160 window._perm_map_data = pgpm.toStoreData( window._perm_map_list, 'id' );
161 window.perm_map_store = new dojo.data.ItemFileWriteStore({ data : window._perm_map_data });
163 window.perm_map_store.onSet = function (item, attr, o, n) {
164 if (attr == 'ischanged') return;
167 this.setValue( item, 'ischanged', 1);
169 if (attr == 'grantable' && (typeof (n) != 'string'))
170 this.setValue(item, 'grantable', n ? 't' : 'f');
173 dojo.addOnUnload( function (event) { save_them_all(); });
181 label="&conify.grp_tree.permission_groups.label;"
182 query="{'_top':'true'}"
183 dojoType="dijit.Tree"
189 <script type="dojo/method" event="onClick" args="item,node">
191 right_pane_toggler.show();
193 current_group = item;
194 window.current_fm_group = new pgt().fromStoreItem(item);
196 perm_map_model.query = { grp : current_group ? current_group.id[0] : -1 };
197 perm_map_model.refresh();
200 highlighter.editor_pane.green.play();
201 status_update( dojo.string.substitute( pgt_strings.STATUS_EDITING, [this.store.getValue( item, 'name' )]) );
203 new_kid_button.disabled = false;
204 save_group_button.disabled = false;
205 delete_group_button.disabled = false;
207 var main_settings_fields = [ 'name', 'perm_interval', 'description'];
208 for ( var i in main_settings_fields ) {
209 var field = main_settings_fields[i];
210 var value = this.store.getValue( current_group, field );
213 window["editor_pane_" + field].setValue( '' ); // unset the value
214 if (field != 'description') window["editor_pane_" + field].setDisplayedValue( '' ); // unset the value
215 } else window["editor_pane_" + field].setValue( value );
218 if ( this.store.getValue( current_group, '_trueRoot' ) == 'true' ) {
219 editor_pane_parent.disabled = true;
220 editor_pane_parent.setValue(null);
221 editor_pane_parent.setDisplayedValue('');
222 editor_pane_parent.validate(false);
224 editor_pane_parent.disabled = false;
225 editor_pane_parent.validate(true);
226 editor_pane_parent.setValue( this.store.getValue( current_group, 'parent' ) );
229 editor_pane_application_perm.setValue( this.store.getValue( current_group, 'application_perm' ) );
231 editor_pane_usergroup.setChecked( this.store.getValue( current_group, 'usergroup' ) == 't' ? true : false );
235 <script type="dojo/method" event="getLabel" args="item,pI">
236 var label = this.store.getValue(item,'name');
237 if (this.store.getValue(item,'ischanged') == 1) label = '* ' + label;
244 <div id="right_pane" dojoType="dijit.layout.ContentPane" sizeShare="300">
245 <script type="dojo/method">
246 window.right_pane_toggler = new dojo.fx.Toggler({ node: 'right_pane'});
247 window.right_pane_toggler.hide();
250 <div dojoType="dijit.layout.TabContainer">
251 <div id="editor_pane" dojoType="dijit.layout.ContentPane" title="&conify.grp_tree.group_config.label;">
252 <script type="dojo/method">
253 highlighter.group_tree = {};
254 highlighter.editor_pane = {};
255 highlighter.group_tree.green = dojox.fx.highlight( { color : '#B4FFB4', node : 'group_tree', duration : 500 } );
256 highlighter.group_tree.red = dojox.fx.highlight( { color : '#FF2018', node : 'group_tree', duration : 500 } );
257 highlighter.editor_pane.green = dojox.fx.highlight( { color : '#B4FFB4', node : 'editor_pane', duration : 500 } );
258 highlighter.editor_pane.red = dojox.fx.highlight( { color : '#FF2018', node : 'editor_pane', duration : 500 } );
261 <table class="tundra" style="margin:10px;">
263 <th>&conify.grp_tree.group_name.label;</th>
265 <span id="editor_pane_name" dojoType="dijit.form.ValidationTextBox" jsId="editor_pane_name" regExp=".+" required="true">
266 <script type="dojo/connect" event="onChange">
268 group_store.setValue( current_group, "name", this.getValue() );
272 <span dojoType="openils.widget.TranslatorPopup" targetObject="current_fm_group" field="name"></span>
276 <th>&conify.grp_tree.description.label;</th>
280 id="editor_pane_description"
281 dojoType="dijit.form.Textarea"
282 jsId="editor_pane_description"
283 onChange="if (current_group) group_store.setValue( current_group, 'description', this.getValue() );"
286 <span dojoType="openils.widget.TranslatorPopup" targetObject="current_fm_group" field="description"></span>
290 <th>&conify.grp_tree.permission_interval.label;</th>
292 <span id="editor_pane_perm_interval" dojoType="dijit.form.ValidationTextBox" jsId="editor_pane_perm_interval" regExp="^\d+ (?:y.*|mo.*|d.*)$" required="true">
293 <script type="dojo/connect" event="onChange">
295 group_store.setValue( current_group, "perm_interval", this.getValue() );
302 <th>&conify.grp_tree.editing_permission.label;</th>
305 id="editor_pane_application_perm"
306 dojoType="dijit.form.FilteringSelect"
307 store="perm_name_store"
309 jsId="editor_pane_application_perm"
311 <script type="dojo/connect" event="onChange">
313 if (current_group && this.getValue()) {
314 group_store.setValue( current_group, "application_perm", this.getValue() );
322 <th>&conify.grp_tree.parent_group.label;</th>
325 id="editor_pane_parent"
326 dojoType="dijit.form.FilteringSelect"
327 jsId="editor_pane_parent"
333 <script type="dojo/connect" event="onChange">
335 if (current_group && this.getValue()) {
336 this.store.setValue( current_group, "parent", this.getValue() );
344 <th>&conify.grp_tree.user_group.label;</th>
347 id="editor_pane_usergroup"
348 jsId="editor_pane_usergroup"
350 dojoType="dijit.form.CheckBox"
351 onChange='if (current_group) group_store.setValue( current_group, "usergroup", this.checked ? "t" : "f" );'
357 <div dojoType="dijit.layout.ContentPane" orientation="horizontal" style="margin-bottom: 20px;">
359 <button jsId="save_group_button" dojoType="dijit.form.Button" label="&conify.grp_tree.save_button.label;" onClick="save_group()">
360 <script type="dojo/connect" event="startup">
361 this.disabled = true;
365 <button jsId="delete_group_button" dojoType="dijit.form.Button" label="&conify.grp_tree.delete_button.label;">
366 <script type="dojo/connect" event="startup">
367 this.disabled = true;
369 <script type="dojo/connect" event="onClick">
372 if (group_store.getValue( current_group, '_trueRoot' ) == 'true') {
373 highlighter.editor_pane.red.play();
374 status_update( dojo.string.substitute( pgt_strings.STATUS_ERR_DELETING, [group_store.getValue( current_group, 'name' )]) );
378 if ( current_group.children ) {
379 var kids = current_group.children;
380 if (!dojo.isArray(kids)) kids = [kids];
382 var existing_kids = dojo.filter(
384 function(kid){ return kid.isdeleted[0] != 1 }
386 if ( existing_kids.length > 0) {
387 highlighter.editor_pane.red.play();
388 status_update( dojo.string.substitute( pgt_strings.STATUS_ERR_DELETING_DEPENDENCY, [group_store.getValue( current_group, 'name' ), existing_kids.length]) );
393 if ( confirm( dojo.string.substitute( pgt_strings.CONFIRM_DELETE, [current_group.name]) ) ) {
394 group_store.setValue( current_group, 'isdeleted', 1 );
396 var modified_pgt = new pgt().fromStoreItem( current_group );
397 modified_pgt.isdeleted( 1 );
399 server.pCRUD.request({
400 method : 'open-ils.permacrud.delete.pgt',
402 params : [ ses, modified_pgt ],
403 onerror : function (r) {
404 highlighter.editor_pane.red.play();
405 status_update( dojo.string.substitute( pgt_strings.CONFIRM_DELETE, [group_store.getValue( current_group, 'name' )]) );
407 oncomplete : function (r) {
409 if ( res && res.content() ) {
411 var old_name = group_store.getValue( current_group, 'name' );
414 query : { id : group_store.getValue( current_group, 'id' ) },
415 queryOptions : { deep : true },
416 onItem : function (item, req) { try { if (this.isItem( item )) this.deleteItem( item ); } catch (e) { /* meh */ } },
420 current_group = null;
422 new_kid_button.disabled = true;
423 save_group_button.disabled = true;
424 delete_group_button.disabled = true;
426 var main_settings_fields = [ 'name', 'perm_interval', 'description' ];
427 for ( var i in main_settings_fields ) {
428 var field = main_settings_fields[i];
429 window["editor_pane_" + field].setValue( '' ); // unset the value
430 window["editor_pane_" + field].setDisplayedValue( '' ); // unset the value
433 window["editor_pane_usergroup"].setChecked( false ); // unset the value
435 highlighter.editor_pane.green.play();
436 status_update( dojo.string.substitute( pgt_strings.STATUS_DELETED, [old_name]) );
438 highlighter.editor_pane.red.play();
439 status_update( dojo.string.substitute( pgt_strings.ERROR_DELETING, [old_name]) );
451 <button jsId="new_kid_button" dojoType="dijit.form.Button" label="&conify.grp_tree.new_child_button.label;">
452 <script type="dojo/connect" event="startup">
453 this.disabled = true;
455 <script type="dojo/connect" event="onClick">
458 var new_fm_obj = new pgt().fromHash({
460 name : pgt_strings.LABEL_NEW_GROUP,
462 parent : group_store.getValue( current_group, 'id' )
466 server.pCRUD.request({
467 method : 'open-ils.permacrud.create.pgt',
469 params : [ ses, new_fm_obj ],
470 onerror : function (r) {
471 highlighter.editor_pane.red.play();
472 status_update( pgt_strings.ERROR_CALLING_METHOD );
475 oncomplete : function (r) {
477 if ( res && res.content() ) {
479 res.content().toHash(),
480 { parent : current_group, attribute : 'children' }
483 highlighter.editor_pane.red.play();
484 status_update( pgt_strings.ERROR_CREATING_CHILD_GROUP );
491 highlighter.editor_pane.green.play();
492 highlighter.group_tree.green.play();
493 status_update( dojo.string.substitute( pgt_strings.SUCCESS_NEW_CHILD_GROUP, [group_store.getValue( current_group, 'name' )]) );
501 <div id="perm_pane" dojoType="dijit.layout.ContentPane" title="&conify.grp_tree.group_permissions.title;">
502 <script type="dojo/connect" event="onShow">
503 perm_map_model.query = { grp : current_group ? current_group.id[0] : -1 };
504 perm_map_model.refresh();
507 <div dojoType="dijit.layout.LayoutContainer" orientation="horizontal" style="width:100%; height:100%;">
508 <div id="grid_container" dojoType="dijit.layout.ContentPane" sizeShare="1" layoutAlign="left">
509 <div dojoType="dojox.grid.data.DojoData" id="perm_map_model" jsId="perm_map_model" store="perm_map_store"></div>
511 <div id="perm_grid" dojoType="dojox.Grid" model="perm_map_model" jsId="perm_grid">
512 <script type="dojo/connect" event="startup">
514 function get_item_part(model_field, item_search_field, item_part, model, store, datum, row) {
515 var formatter = true;
517 if (!row && row != '0') {
522 if(!model.getRow(row)) return null;
525 if(!formatter) { //this.editor && (this.editor.alwaysOn || (this.grid.edit.info.rowIndex==row && this.grid.edit.info.cell==this))) {
526 return model.getRow(row)[model_field];
530 q[item_search_field] = model.getRow(row)[model_field];
534 onItem : function (item) { value = store.getValue( item, item_part ) }
540 window.current_perm_grid_layout = [
543 { name : pgt_strings.LABEL_CODE,
545 formatter : dojo.partial(get_item_part, "perm", "id", "code", perm_map_model, perm_store),
548 { name : pgt_strings.LABEL_DEPTH,
550 formatter : dojo.partial(get_item_part, "depth", "depth", "name", perm_map_model, ou_type_store),
551 editor : dojox.grid.editors.select,
552 options : dojo.map( _ou_type_list, function (x) { return x.name() } ),
553 values : dojo.map( _ou_type_list, function (x) { return x.depth() } )
555 { name : pgt_strings.LABEL_GRANTABLE,
557 editor : dojox.grid.editors.bool,
558 get : function (row) {
559 var gr = get_item_part("id", "id", "grantable", perm_map_model, perm_map_model.store, row, row);
560 if (gr == 't' || gr === true) return true;
569 perm_grid.setStructure(window.current_perm_grid_layout);
575 <div id="new_perm_container" dojoType="dijit.layout.ContentPane" sizeShare="1" layoutAlign="client">
577 <div dojoType="dijit.form.DropDownButton" id="new_popup" jsId="new_popup">
578 <span>&conify.grp_tree.new_mapping.label;</span>
579 <div dojoType="dijit.TooltipDialog">
580 <table class="tundra">
582 <td>&conify.grp_tree.permission.label;</td>
585 dojoType="dijit.form.FilteringSelect"
587 jsId="new_perm_select"
591 required="true"></div>
595 <td>&conify.grp_tree.depth.label;</td>
598 dojoType="dijit.form.FilteringSelect"
599 Id="new_depth_select"
600 jsId="new_depth_select"
601 store="ou_type_store"
604 required="true"></div>
608 <td>&conify.grp_tree.grantable.label;</td>
612 dojoType="dijit.form.CheckBox"
613 Id="new_grant_checkbox"
614 jsId="new_grant_checkbox"
620 <button dojoType="dijit.form.Button" jsId="new_mapping_add" label="&conify.grp_tree.add_mapping_button.label;">
621 <script type="dojo/connect" event="onClick">
623 var new_perm = new_perm_select.getValue();
625 if (!new_perm) return;
627 var new_type_id = new_depth_select.getValue();
628 if (!new_type_id) return;
631 window.ou_type_store.fetch({
632 query : { id : new_type_id },
633 onItem : function (item, req) { try { new_type = item } catch (e) { /* meh */ } },
636 var new_depth = ou_type_store.getValue( new_type, 'depth')
637 var new_grant = new_grant_checkbox.getValue();
639 var new_fm_obj = new pgpm().fromHash({
643 grp : group_store.getValue( current_group, 'id' ),
644 grantable : new_grant ? 't' : 'f'
648 server.pCRUD.request({
649 method : 'open-ils.permacrud.create.pgpm',
651 params : [ ses, new_fm_obj ],
652 onerror : function (r) {
653 highlighter.group_tree.red.play();
654 status_update( pgt_strings.ERROR_CALLING_METHOD_PERM_MAP );
657 oncomplete : function (r) {
660 if ( res && res.content() ) {
661 var new_item_hash = res.content().toHash();
662 perm_map_store.newItem( new_item_hash );
663 status_update( pgt_strings.SUCCESS_NEW_PERM_MAP );
664 highlighter.group_tree.green.play();
666 perm_map_model.query = { grp : current_group ? current_group.id[0] : -1 };
667 perm_grid.model.sort(-1);
668 perm_map_model.refresh();
672 highlighter.group_tree.red.play();
673 status_update( pgt_strings.ERROR_CREATING_PERM_MAP );
679 new_popup._closeDropDown();
687 <button jsId="save_pgpm_button" dojoType="dijit.form.Button" label="&conify.grp_tree.save_changes.label;" onClick="save_them_all()"></button><br/>
689 <button jsId="delete_pgpm_button" dojoType="dijit.form.Button" label="&conify.grp_tree.remove_selected.label;">
690 <script type="dojo/connect" event="onClick">
692 var selected_rows = perm_grid.selection.getSelected();
694 var selected_items = [];
695 for (var i in selected_rows) {
697 perm_grid.model.getRow( selected_rows[i] ).__dojo_data_item
701 perm_grid.selection.clear();
703 for (var i in selected_items) {
704 window.current_perm_map = selected_items[i];
706 perm_map_store.setValue( window.current_perm_map, 'isdeleted', 1 );
708 var modified_pgpm = new pgpm().fromStoreItem( window.current_perm_map );
709 modified_pgpm.isdeleted( 1 );
711 server.pCRUD.request({
712 method : 'open-ils.permacrud.delete.pgpm',
714 params : [ ses, modified_pgpm ],
715 onerror : function (r) {
716 highlighter.editor_pane.red.play();
717 status_update( dojo.string.substitute( pgt_strings.ERROR_DELETING_PERM_MAPPING, [perm_map_store.getValue( window.current_perm_map, 'id' )] ) );
719 oncomplete : function (r) {
721 if ( res && res.content() ) {
723 perm_map_store.fetch({
724 query : { id : perm_map_store.getValue( window.current_perm_map, 'id' ) },
725 onItem : function (item, req) { try { if (this.isItem( item )) this.deleteItem( item ); } catch (e) { /* meh */ } },
726 scope : perm_map_store
729 window.current_perm_map = null;
731 highlighter.editor_pane.green.play();
732 status_update( pgt_strings.SUCCESS_DELETED_PERM_MAP );
734 highlighter.editor_pane.red.play();
735 status_update( dojo.string.substitute( pgt_strings.ERROR_DELETING_PERM_MAPPING, [perm_map_store.getValue( window.current_perm_map, 'id' )]) );