Acq: Resurrect an old "view fund" interface, add some tag mapping managment
authorsenator <senator@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Fri, 26 Mar 2010 20:30:56 +0000 (20:30 +0000)
committersenator <senator@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Fri, 26 Mar 2010 20:30:56 +0000 (20:30 +0000)
From the "list funds" interface, you can click on the name of a fund and get
to the "view funds" interface for that fund.  That interface now how a "tags"
tab where you can attach and detach tags to/from the fund you're viewing.

git-svn-id: svn://svn.open-ils.org/ILS/trunk@16017 dcc99617-32d9-48b4-a31d-7c20da2025e4

Open-ILS/src/perlmods/OpenILS/Application/Acq/Financials.pm
Open-ILS/web/css/skin/default/acq.css
Open-ILS/web/js/dojo/openils/acq/nls/acq.js
Open-ILS/web/js/ui/default/acq/common/tag_manager.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/acq/financial/list_funds.js
Open-ILS/web/js/ui/default/acq/financial/view_fund.js
Open-ILS/web/templates/default/acq/financial/list_funds.tt2
Open-ILS/web/templates/default/acq/financial/view_fund.tt2

index 676e792..caa14d4 100644 (file)
@@ -254,6 +254,10 @@ sub retrieve_fund {
     $options ||= {};
 
     my $flesh = {flesh => 2, flesh_fields => {acqf => []}};
+    if ($options->{"flesh_tags"}) {
+        push @{$flesh->{"flesh_fields"}->{"acqf"}}, "tags";
+        $flesh->{"flesh_fields"}->{"acqftm"} = ["tag"];
+    }
     push(@{$flesh->{flesh_fields}->{acqf}}, 'debits') if $$options{flesh_debits};
     push(@{$flesh->{flesh_fields}->{acqf}}, 'allocations') if $$options{flesh_allocations};
     push(@{$flesh->{flesh_fields}->{acqfa}}, 'funding_source') if $$options{flesh_allocation_sources};
index 87b83a5..2016931 100644 (file)
 }
 #oils-acq-metapo-summary td { text-align: right; }
 
+#oils-acq-tag-manager-display { padding: 8px 2px; }
+#oils-acq-tag-manager-add { padding: 8px 2px; border-top: 1px dotted #ccc; }
+.oils-acq-fund-tag {
+    border: 1px #666 dashed;
+    margin: 2px 8px;
+    padding: 4px;
+}
+.oils-acq-fund-tag A { margin-left: 10px; }
+
 /* li search page */
 h1.oils-acq-li-search { font-size: 150%;font-weight: bold;margin-bottom: 12px; }
 h2.oils-acq-li-search { font-size: 138%;font-weight: bold;margin-bottom: 11px; }
index 15576db..3d6bac2 100644 (file)
@@ -39,5 +39,9 @@
     'VENDOR_SAYS_PREPAY_NOT_NEEDED': "The selected vendor does not necessarily require prepayment, according\nto records. Require prepayment on this PO anyway?",
     'VENDOR_SAYS_PREPAY_NEEDED': "The selected vendor requires prepayment, according to records.\nProceed anyway without required prepayment on this PO?",
     'PREPAYMENT_REQUIRED_REMINDER': "This PO requires prepayment.  Are you certain you're ready to activate it?",
-    'LI_FORMAT_ERROR': "Unexpected error retrieving formatted lineitem information."
+    'LI_FORMAT_ERROR': "Unexpected error retrieving formatted lineitem information.",
+    'FUND_NOT_YET_LOADED': "Fund not yet loaded. Try coming back to this display later.",
+    'CONFIRM_DELETE_MAPPING': "Are you sure you want to remove this tag from this fund?",
+    'COULD_NOT_CREATE_MAPPING': "Error tagging fund.",
+    'COULD_NOT_DELETE_MAPPING': "Error removing tag from fund."
 }
diff --git a/Open-ILS/web/js/ui/default/acq/common/tag_manager.js b/Open-ILS/web/js/ui/default/acq/common/tag_manager.js
new file mode 100644 (file)
index 0000000..c2086aa
--- /dev/null
@@ -0,0 +1,113 @@
+dojo.require("openils.PermaCrud");
+dojo.require("dojo.data.ItemFileReadStore");
+
+if (typeof(localeStrings) == "undefined") {
+    dojo.requireLocalization("openils.acq", "acq");
+    var localeStrings = dojo.i18n.getLocalization("openils.acq", "acq");
+}
+
+function TagManager(displayNode) {
+    var self = this;
+    this.tagCache = {};
+    this.displayNode = displayNode;
+
+    this.pcrud = new openils.PermaCrud();
+
+// selected (by checkbox) id's from an autogrid of objects:
+//        return grid.getSelectedItems().map(function(o) { return o.id[0]; });
+
+    this.displayFund = function(fund) {
+        if (!fund) {
+            this.displayNode.innerHTML = localeStrings.FUND_NOT_YET_LOADED;
+            return;
+        }
+
+        dojo.empty(this.displayNode);
+        fund.tags().forEach(
+            function(o) {
+                dojo.place(self.renderTagMapping(o), self.displayNode, "last");
+            }
+        );
+    };
+
+    this.renderTagMapping = function(mapping) {
+        var span = dojo.create(
+            "span", {
+                "id": "oils-acq-fund-tag-mapping-" + mapping.id(),
+                "className": "oils-acq-fund-tag",
+                "innerHTML": mapping.tag().name()
+            }
+        );
+        dojo.create(
+            "a", {
+                "href": "javascript:void(0);",
+                "innerHTML": "X",
+                "onclick": function() { self.deleteMapping(mapping); },
+            },
+            span, "last"
+        );
+        return span;
+    };
+
+    this.deleteMapping = function(mapping) {
+        if (confirm(localeStrings.CONFIRM_DELETE_MAPPING)) {
+            this.pcrud.eliminate(
+                mapping, {
+                    "oncomplete": function(r) {
+                        dojo.destroy(
+                            "oils-acq-fund-tag-mapping-" + mapping.id()
+                        );
+                    },
+                    "onerror": function() {
+                        /* XXX does onerror not actually work? */
+                        alert(localeStrings.COULD_NOT_DELETE_MAPPING);
+                    }
+                }
+            );
+        }
+    };
+
+    this.addMapping = function(fund, tag) {
+        var mapping = new acqftm();
+        mapping.fund(fund.id());
+        mapping.tag(tag.id());
+
+        this.pcrud.create(
+            mapping, {
+                "onerror": function(r) {
+                    /* XXX does onerror not actually work? */
+                    alert(localeStrings.COULD_NOT_CREATE_MAPPING);
+                },
+                "oncomplete": function(r, list) {
+                    mapping = list[0]; /* get the new mapping's ID this way */
+                    mapping.tag(tag); /* re-"flesh" */
+                    dojo.place(
+                        self.renderTagMapping(mapping),
+                        self.displayNode, "last"
+                    );
+                }
+            }
+        );
+    };
+
+    this.prepareTagSelector = function(selector) {
+        this.pcrud.search(
+            "acqft", {
+                "owner": fieldmapper.aou.orgNodeTrail(
+                    fieldmapper.aou.findOrgUnit(openils.User.user.ws_ou()),
+                    true /* asId */
+                )
+            }, {
+                "async": true,
+                "oncomplete": function(r) {
+                    if ((r = openils.Util.readResponse(r))) {
+                        selector.store = new dojo.data.ItemFileReadStore(
+                            {"data": acqft.toStoreData(r)}
+                        );
+                        selector.startup();
+                    }
+                }
+            }
+        );
+    };
+}
index 7a31f2d..c078bcb 100644 (file)
@@ -43,6 +43,8 @@ function initPage() {
 
     loadYearSelector();
     loadFundGrid();
+
+    tagManager = new TagManager(lfGrid);
 }
 
 function loadFundGrid(year) {
@@ -154,4 +156,3 @@ function performRollover(args) {
 }
 
 openils.Util.addOnLoad(initPage);
-
index 7f8bb86..eb0f0bd 100644 (file)
@@ -13,6 +13,7 @@ dojo.require('openils.User');
 dojo.require('openils.Util');
 
 var fund = null;
+var tagManager;
 
 function getSummaryInfo(rowIndex, item) {
     if(!item) return'';
@@ -68,7 +69,7 @@ function fetchFund() {
         {   async: true,
             params: [
                 openils.User.authtoken, fundID, 
-                {flesh_summary:1, flesh_allocations:1, flesh_debits:1} 
+                {flesh_summary:1, flesh_allocations:1, flesh_debits:1, flesh_tags:1
                 /* TODO grab allocations and debits only on as-needed basis */
             ],
             oncomplete: function(r) {
@@ -79,4 +80,10 @@ function fetchFund() {
     );
 }
 
-openils.Util.addOnLoad(fetchFund);
+function load() {
+    tagManager = new TagManager(dojo.byId("oils-acq-tag-manager-display"));
+    tagManager.prepareTagSelector(tagSelector);
+    fetchFund();
+}
+
+openils.Util.addOnLoad(load);
index 94499f3..c8cdbd5 100644 (file)
@@ -3,6 +3,27 @@
 
 <!-- load the page-specific JS -->
 <script src='[% ctx.media_prefix %]/js/ui/default/acq/financial/list_funds.js'> </script>
+<script type="text/javascript">
+    function getFundName(rowIndex, item) {
+        if (!item) return null;
+        return {
+            "name": this.grid.store.getValue(item, "name"),
+            "id": this.grid.store.getValue(item, "id")
+        };
+    }
+
+    function formatName(value) {
+        if (!value) return "XXX"; // XXX
+
+        var link = "<a href='/eg/acq/financial/view_fund/" +
+            value.id + "'>" +
+            value.name + "</a>";
+
+        /* TODO: add another element here to which we can attach a tooltip
+           showing tags */
+        return link;
+    }
+</script>
 
 <table style='width:100%;'>
     <tr>
         <td style='text-align:left;font-size:130%;font-weight: bold;'>Funds</td>
         <td style='text-align:right;width:90%;'>
 
-            <span>
-                <span>Context Org Unit</span>
-                <select 
-                    dojoType="openils.widget.OrgUnitFilteringSelect" 
-                    jsId='contextOrgSelector'
-                    searchAttr='shortname' 
-                    labelAttr='shortname'> 
-                </select>
-            </span>
-
-            Year <select dojoType='dijit.form.FilteringSelect'
-                jsId='fundFilterYearSelect' labelAttr='year' searchAttr='year'> </select>
-
             <button dojoType='dijit.form.Button' onClick='lfGrid.showCreateDialog()'>New Fund</button>
             <button dojoType='dijit.form.Button' onClick='lfGrid.deleteSelected()'>Delete Selected</button>
 
                         <tr>
                             <td colspan='2'>
                                 <div style='width:400px;border-bottom:2px solid #888'>
-                                Propagation creates new funds for the sugsequent fiscal year based on the 
+                                Propagation creates new funds for the sugsequent fiscal year based on the
                                 funds for the selected fiscal year.  Only funds with the propagate setting
                                 enabled will be affected.  No money or encumbrances are altered
-                                during this process. 
-                                <div>
+                                during this process.
+                                </div>
                             </td>
                         </tr>
                         <tr>
@@ -50,9 +58,9 @@
                             <td colspan='2'>
                                 <div style='width:400px;border-bottom:2px solid #888'>
                                 The year end close out operation moves encumbrances from the selected fiscal
-                                year to the analogous funds in the subsequent fiscal year and it deactivates 
-                                funds for the selected fiscal year.  Additionally, for all funds that have 
-                                the "Rollver" setting enabled, this process will move all unspent money to 
+                                year to the analogous funds in the subsequent fiscal year and it deactivates
+                                funds for the selected fiscal year.  Additionally, for all funds that have
+                                the "Rollver" setting enabled, this process will move all unspent money to
                                 the analogous fund in the subsequent fiscal year.
                                 </div>
                             </td>
@@ -66,8 +74,8 @@
                         <tr>
                             <td colspan='2'>
                                 <div style='width:400px;border-bottom:2px solid #888'>
-                                When Dry Run is selected, the system will generate a summary of 
-                                the changes that would occur during the selected operation(s).  
+                                When Dry Run is selected, the system will generate a summary of
+                                the changes that would occur during the selected operation(s).
                                 No data will be changed.
                                 </div>
                             </td>
                         </tr>
                     </table>
                 </div>
-            </div> 
+            </div>
         </td>
     </tr>
 </table>
 
+<div class="oils-acq-basic-roomy">
+    <span>Context Org Unit</span>
+    <select
+        dojoType="openils.widget.OrgUnitFilteringSelect"
+        jsId="contextOrgSelector"
+        searchAttr="shortname"
+        labelAttr="shortname">
+    </select>
+
+    <span>Year</span>
+    <select dojoType="dijit.form.FilteringSelect"
+        jsId="fundFilterYearSelect"
+        labelAttr="year"
+        searchAttr="year">
+    </select>
+</div>
+
 <div dojoType="dijit.layout.ContentPane" layoutAlign="client">
     <table  jsId="lfGrid"
             autoHeight='true'
             editOnEnter='true'>
         <thead>
             <tr>
-                <th field='combined_balance' name="Combined Balance"  get='getBalanceInfo'></th>
+                <th field="name" get="getFundName" formatter="formatName"></th>
+                <th field="combined_balance" name="Combined Balance" get="getBalanceInfo"></th>
             </tr>
         </thead>
     </table>
 </div>
-<div dojoType='openils.widget.ProgressDialog' jsId='progressDialog'/>
-
-
+<div dojoType="openils.widget.ProgressDialog" jsId="progressDialog"></div>
 [% END %]
index fc97851..6945128 100644 (file)
@@ -10,6 +10,7 @@
 </script>
 
 <!-- load the page-specific JS -->
+<script src="[% ctx.media_prefix %]/js/ui/default/acq/common/tag_manager.js"> </script>
 <script src='[% ctx.media_prefix %]/js/ui/default/acq/financial/view_fund.js'> </script>
 
 <div id='oils-acq-list-header' class='container'>
                 </div> 
             </div> 
         </div>
+        <div dojoType="dijit.layout.ContentPane" class="oils-acq-detail-content-pane" title="Tags">
+            <script type="dojo/connect" event="onShow">
+                tagManager.displayFund(fund);
+            </script>
+            <div id="oils-acq-tag-manager-display"></div>
+            <div id="oils-acq-tag-manager-add">
+                <div dojoType="dijit.form.DropDownButton">
+                    <span>Add Tag</span>
+                    <div dojoType="dijit.TooltipDialog">
+                        <select dojoType="dijit.form.FilteringSelect"
+                            jsId="tagSelector">
+                        </select>
+                        <button onclick="tagManager.addMapping(
+                            fund, new acqft().fromStoreItem(tagSelector.item)
+                        );" type="submit" dojoType="dijit.form.Button">
+                            Add
+                        </button>
+                    </div>
+                </div>
+            </div>
+        </div>
     </div>
 </div>
 [% END %]