webstaff: start of prediction wizard
authorGalen Charlton <gmc@equinoxinitiative.org>
Fri, 28 Apr 2017 19:23:19 +0000 (15:23 -0400)
committerGalen Charlton <gmc@equinoxinitiative.org>
Fri, 28 Apr 2017 19:23:19 +0000 (15:23 -0400)
Signed-off-by: Galen Charlton <gmc@equinoxinitiative.org>
Open-ILS/src/templates/staff/serials/index.tt2
Open-ILS/src/templates/staff/serials/t_prediction_wizard.tt2 [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/serials/directives/prediction_wizard.js [new file with mode: 0644]

index 692e57d..e37504d 100644 (file)
@@ -11,6 +11,7 @@
 <script src="[% ctx.media_prefix %]/js/ui/default/staff/serials/directives/subscription_manager.js"></script>
 <script src="[% ctx.media_prefix %]/js/ui/default/staff/serials/directives/sub_selector.js"></script>
 <script src="[% ctx.media_prefix %]/js/ui/default/staff/serials/directives/prediction_manager.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/serials/directives/prediction_wizard.js"></script>
 <script src="[% ctx.media_prefix %]/js/ui/default/staff/cat/services/record.js"></script>
 
 [% END %]
diff --git a/Open-ILS/src/templates/staff/serials/t_prediction_wizard.tt2 b/Open-ILS/src/templates/staff/serials/t_prediction_wizard.tt2
new file mode 100644 (file)
index 0000000..34533db
--- /dev/null
@@ -0,0 +1,200 @@
+<div>
+  <uib-tabset active="tab.active">
+    <uib-tab index="0" disable="tab.active != 0" heading="[% l('Enumeration Labels') %]">
+      <div class="row">
+         <div class="radio">
+           <label>
+             <input type="radio" ng-model="pattern.use_enum" ng-value="True">
+             [% l('Use Enumeration (e.g., v.1, no. 1)') %]
+           </label>
+         </div>
+         <div class="radio">
+           <label>
+              <input type="radio" ng-model="pattern.use_enum" ng-value="False">
+              [% l('Use Calendar Dates Only (e.g., April 10)') %]
+            </label>
+         </div>
+         <div class="row" ng-if="pattern.use_enum">
+            <div class="row" ng-repeat="enum_level in pattern.enum_levels">
+                <div class="col-md-1"></div>
+                <div class="col-md-1">[% l('Level [_1]', '{{$index + 1}}')  %]</div>
+                <div class="col-md-2"><input type="text" ng-model="enum_level.caption"></div>
+                <div ng-if="$index > 0">
+                  <div class="col-md-3">
+                    <select ng-model="enum_level.units_per_next_higher.type">
+                      <option value="number">[% l('Number') %]</option>
+                      <option value="var">[% l('Varies') %]</option>
+                      <option value="und">[% l('Undetermined') %]</option>
+                    </select>
+                    <input type="number" step="1" 
+                           ng-model="enum_level.units_per_next_higher.value"
+                           ng-hide="enum_level.units_per_next_higher.type != 'number'"
+                    >
+                  </div>
+                  <div class="col-md-2">
+                    <div class="radio">
+                      <label>
+                        <input type="radio" ng-model="enum_level.restart" ng-value="True">
+                        [% l('Restarts at unit completion') %]
+                      </label>
+                    </div>
+                    <div class="radio">
+                      <label>
+                        <input type="radio" ng-model="enum_level.restart" ng-value="False">
+                        [% l('Increments continuously') %]
+                      </label>
+                    </div>
+                  </div>
+                  <div class="col-md-1" ng-if="$last">
+                    <button class="btn btn-warning btn-sm"
+                            ng-click="pattern.drop_enum_level()">
+                    [% ('Remove Level') %]
+                    </button>
+                  </div>
+                </div>
+            </div>
+            <div class="row">
+              <div class="col-md-1">
+                <button class="btn btn-warning btn-sm" ng-disabled="pattern.enum_levels.length >= 6"
+                        ng-click="pattern.add_enum_level()">
+                  [% ('Add Level') %]
+                </button>
+              </div>
+            </div>
+         </div>
+      </div>
+      <div class="row">
+        <div class="checkbox">
+          <label>
+            <input type="checkbox" ng-model="pattern.use_alt_enum">
+            [% l('Add alternative enumeration') %]
+          </label>
+         </div>
+         <div class="row" ng-if="pattern.use_alt_enum">
+            <div class="row" ng-repeat="alt_enum_level in pattern.alt_enum_levels">
+                <div class="col-md-1"></div>
+                <div class="col-md-1">[% l('Level [_1]', '{{$index + 1}}')  %]</div>
+                <div class="col-md-2"><input type="text" ng-model="alt_enum_level.caption"></div>
+                <div ng-if="$index > 0">
+                  <div class="col-md-3">
+                    <select ng-model="alt_enum_level.units_per_next_higher.type">
+                      <option value="number">[% l('Number') %]</option>
+                      <option value="var">[% l('Varies') %]</option>
+                      <option value="und">[% l('Undetermined') %]</option>
+                    </select>
+                    <input type="number" step="1" 
+                           ng-model="alt_enum_level.units_per_next_higher.value"
+                           ng-hide="alt_enum_level.units_per_next_higher.type != 'number'"
+                    >
+                  </div>
+                  <div class="col-md-2">
+                    <div class="radio">
+                      <label>
+                        <input type="radio" ng-model="alt_enum_level.restart" ng-value="True">
+                        [% l('Restarts at unit completion') %]
+                      </label>
+                    </div>
+                    <div class="radio">
+                      <label>
+                        <input type="radio" ng-model="alt_enum_level.restart" ng-value="False">
+                        [% l('Increments continuously') %]
+                      </label>
+                    </div>
+                  </div>
+                  <div class="col-md-1" ng-if="$last">
+                    <button class="btn btn-warning btn-sm"
+                            ng-click="pattern.drop_alt_enum_level()">
+                    [% ('Remove Level') %]
+                    </button>
+                  </div>
+                </div>
+            </div>
+            <div class="row">
+              <div class="col-md-1">
+                <button class="btn btn-warning btn-sm" ng-disabled="pattern.alt_enum_levels.length >= 2"
+                        ng-click="pattern.add_alt_enum_level()">
+                  [% ('Add Level') %]
+                </button>
+              </div>
+            </div>
+         </div>
+      </div>
+      <div class="row">
+        <button class="btn btn-success pull-right" ng-click="tab.active = tab.active + 1">
+            [% l('Next') %]
+        </button>
+      </div>
+    </uib-tab>
+    <uib-tab index="1" disable="tab.active != 1" heading="[% l('Chronology Display') %]">
+      <div class="row">
+        <div class="checkbox">
+          <label>
+            <input type="checkbox" ng-model="pattern.use_chron">
+            [% l('Use Chronology Captions?') %]
+          </label>
+        </div>
+        <div class="row" ng-if="pattern.use_chron">
+CHRON
+        </div>
+      </div>
+      <div class="row">
+        <button class="btn btn-warning pull-left" ng-click="tab.active = tab.active - 1">
+            [% l('Back') %]
+        </button>
+        <button class="btn btn-success pull-right" ng-click="tab.active = tab.active + 1">
+            [% l('Next') %]
+        </button>
+      </div>
+    </uib-tab>
+    <uib-tab index="2" disable="tab.active != 2" heading="[% l('MFHD Indicators') %]">
+      <div class="row">
+        <div class="col-md-6">
+          <label for="selectCompressExpand">[% l('Compression Display Options') %]</label>
+          <select ng-model="pattern.compress_expand">
+            <option value="0">[% l('Cannot compress or expand') %]</option>
+            <option value="1">[% l('Can compress but not expand') %]</option>
+            <option value="2">[% l('Can compress or expand') %]</option>
+            <option value="3">[% l('Unknown') %]</option>
+          </select>
+        </div>
+        <div class="col-md-6">
+          <label for="selectCompressExpand">[% l('Caption Evaluation') %]</label>
+          <select ng-model="pattern.caption_evaluation">
+            <option value="0">[% l('Captions verified; all levels present') %]</option>
+            <option value="1">[% l('Captions verified; all levels may not be present') %]</option>
+            <option value="2">[% l('Captions unverified; all levels present') %]</option>
+            <option value="3">[% l('Captions unverified; all levels may not be present') %]</option>
+          </select>
+        </div>
+      </div>
+      <div class="row">
+        <button class="btn btn-warning pull-left" ng-click="tab.active = tab.active - 1">
+            [% l('Back') %]
+        </button>
+        <button class="btn btn-success pull-right" ng-click="tab.active = tab.active + 1">
+            [% l('Next') %]
+        </button>
+      </div>
+    </uib-tab>
+    <uib-tab index="3" disable="tab.active != 3" heading="[% l('Frequency and Regularity') %]">
+      <div class="row">
+        <button class="btn btn-warning pull-left" ng-click="tab.active = tab.active - 1">
+            [% l('Back') %]
+        </button>
+        <button class="btn btn-success pull-right" ng-click="tab.active = tab.active + 1">
+            [% l('Next') %]
+        </button>
+      </div>
+    </uib-tab>
+    <uib-tab index="4" disable="tab.active != 4" heading="[% l('Review') %]">
+      <div class="row">
+        <button class="btn btn-warning pull-left" ng-click="tab.active = tab.active - 1">
+            [% l('Back') %]
+        </button>
+        <button class="btn btn-primary pull-right">
+            [% l('Save') %]
+        </button>
+      </div>
+    </uib-tab>
+  </uib-tabset>
+</div>
diff --git a/Open-ILS/web/js/ui/default/staff/serials/directives/prediction_wizard.js b/Open-ILS/web/js/ui/default/staff/serials/directives/prediction_wizard.js
new file mode 100644 (file)
index 0000000..63f3385
--- /dev/null
@@ -0,0 +1,211 @@
+angular.module('egSerialsAppDep')
+
+.directive('egPredictionWizard', function() {
+    return {
+        transclude: true,
+        restrict:   'E',
+        scope: {
+            patternCode : '='
+        },
+        templateUrl: './serials/t_prediction_wizard',
+        controller:
+       ['$scope','$q','egSerialsCoreSvc','egCore','egGridDataProvider',
+function($scope , $q , egSerialsCoreSvc , egCore , egGridDataProvider) {
+
+    $scope.tab = { active : 0 };
+    // for use by ng-value
+    $scope.True = true;
+    $scope.False = false;
+
+    // class for MARC21 serial predication pattern
+    // TODO move elsewhere
+    function PredictionPattern(patternCode) {
+        var self = this;
+        this.use_enum = false;
+        this.use_alt_enum = false;
+        this.use_chron = false;
+        this.compress_expand = '3';
+        this.caption_evaluation = '0';        
+        this.enum_levels = [];
+        this.alt_enum_levels = [];
+        this.chron_levels = [];
+        this.alt_chron_levels = [];
+
+        var nr_sf_map = {
+            '0' : 'link',
+            'n' : 'note',
+            'p' : 'pieces_per_issuance',
+            'w' : 'frequency',
+            't' : 'copy_caption'
+        }
+        var enum_level_map = {
+            'a' : 0,
+            'b' : 1,
+            'c' : 2,
+            'd' : 3,
+            'e' : 4,
+            'f' : 5
+        }
+        var alt_enum_level_map = {
+            'g' : 0,
+            'h' : 1
+        }
+        var chron_level_map = {
+            'i' : 0,
+            'j' : 1,
+            'k' : 2,
+            'l' : 3
+        }
+        var alt_chron_level_map = {
+            'm' : 0
+        }
+
+        var curr_enum_level = -1;
+        var curr_alt_enum_level = -1;
+        var curr_chron_level = -1;
+        var curr_alt_chron_level = -1;
+        if (patternCode && patternCode.length > 2 && (patternCode.length % 2 == 0)) {
+            // set indicator values
+            this.compress_expand = patternCode[0];
+            this.caption_evaluation = patternCode[1];
+            for (var i = 2; i < patternCode.length; i += 2) {
+                var sf = patternCode[i];
+                var value = patternCode[i + 1]; 
+                if (sf in nr_sf_map) {
+                    this[nr_sf_map[sf]] = value;
+                    continue;
+                }
+                if (sf in enum_level_map) {
+                    this.use_enum = true;
+                    curr_enum_level = enum_level_map[sf];
+                    this.enum_levels[curr_enum_level] = {
+                        caption : value,
+                        restart : false
+                    }
+                    continue;
+                }
+                if (sf in alt_enum_level_map) {
+                    this.use_enum = true;
+                    this.use_alt_enum = true;
+                    curr_enum_level = -1;
+                    curr_alt_enum_level = alt_enum_level_map[sf];
+                    this.alt_enum_levels[curr_alt_enum_level] = {
+                        caption : value,
+                        restart : false
+                    }
+                    continue;
+                }
+                if (sf in chron_level_map) {
+                    this.use_chron = true;
+                    curr_chron_level = chron_level_map[sf];
+                    this.chron_levels[curr_chron_level] = {
+                        caption : value
+                    }
+                    continue;
+                }
+                if (sf in alt_chron_level_map) {
+                    this.use_chron = true;
+                    curr_chron_level = -1;
+                    curr_alt_chron_level = alt_enum_level_map[sf];
+                    this.alt_chron_levels[curr_alt_chron_level] = {
+                        caption : value
+                    }
+                    continue;
+                }
+
+                if (sf == 'u') {
+                    var units = {
+                        type : 'number'
+                    };
+                    if (value == 'und' || value == 'var') {
+                        units.type = value;
+                    } else if (!isNaN(parseInt(value))) {
+                        units.value = parseInt(value);
+                    } else {
+                        continue; // escape garbage
+                    }
+                    if (curr_enum_level > 0) {
+                        this.enum_levels[curr_enum_level].units_per_next_higher = units;
+                    } else if (curr_alt_enum_level > 0) {
+                        this.alt_enum_levels[curr_alt_enum_level].units_per_next_higher = units;
+                    }
+                }
+                if (sf == 'v' && value == 'r') {
+                    if (curr_enum_level > 0) {
+                        this.enum_levels[curr_enum_level].restart = true;
+                    } else if (curr_alt_enum_level > 0) {
+                        this.alt_enum_levels[curr_alt_enum_level].restart = true;
+                    }
+                }
+                if (sf == 'z') {
+                    if (curr_enum_level > -1) {
+                        this.enum_levels[curr_enum_level].numbering_scheme = value;
+                    } else if (curr_alt_enum_level > -1) {
+                        this.alt_enum_levels[curr_alt_enum_level].numbering_scheme = value;
+                    }
+                }
+                if (sf == 'x') {
+                    this.calendar_change = [];
+                    value.split(',').forEach(function(chg) {
+                        var calendar_change = {
+                            season : null,
+                            month  : null,
+                            day    : null
+                        }
+                        if (chg.length == 2) {
+                            if (chg >= '21') {
+                                calendar_change.season = chg;
+                            } else {
+                                calendar_change.month = chg;
+                            }
+                        } else if (chg.length == 4) {
+                            calendar_change.month = chg.substring(0, 2);
+                            calendar_change.day   = chg.substring(2, 4);
+                        }
+                        self.calendar_change.push(calendar_change);
+                    });
+                }
+                if (sf == 'y') {
+                    // TODO regularity
+                }
+            }
+        }
+
+        this.add_enum_level = function() {
+            if (self.enum_levels.length < 6) {
+                self.enum_levels.push({
+                    caption : null,
+                    units_per_next_higher : { type : 'und' },
+                    restart : false
+                });
+            }
+        }
+        this.drop_enum_level = function() {
+            if (self.enum_levels.length > 1) {
+                self.enum_levels.pop();
+            }
+        }
+
+        this.add_alt_enum_level = function() {
+            if (self.alt_enum_levels.length < 2) {
+                self.alt_enum_levels.push({
+                    caption : null,
+                    units_per_next_higher : { type : 'und' },
+                    restart : false
+                });
+            }
+        }
+        this.drop_alt_enum_level = function() {
+            if (self.alt_enum_levels.length > 1) {
+                self.alt_enum_levels.pop();
+            }
+        }
+    }
+    // TODO chron only
+
+    // dummy pattern
+    $scope.pattern = new PredictionPattern(["3","0","8","1","a","v.","b","no.","u","6","v","r","g","sequence","i","(year)","j","(month)","w","m","x","06,12"]);
+    console.debug($scope.pattern);
+}]
+    }
+})