<script src="[% ctx.media_prefix %]/js/ui/default/staff/services/grid.js"></script>
<script src="[% ctx.media_prefix %]/js/ui/default/staff/serials/services/core.js"></script>
<script src="[% ctx.media_prefix %]/js/ui/default/staff/serials/app.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/serials/directives/subscription_manager.js"></script>
<script src="[% ctx.media_prefix %]/js/ui/default/staff/cat/services/record.js"></script>
[% END %]
<!-- note that non-numeric index values must be enclosed in single-quotes,
otherwise selecting the active table won't work cleanly -->
<uib-tab index="'create-subscription'" heading="[% l('Create Subscription') %]">
-<!-- TODO: move the subscription / distribution manager to separate template -->
-<form name="ssubform">
- <div ng-repeat="ssub in subscriptions">
- <div class="row form-inline">
- <div class="form-group">
- <label>[% l('Owning Library') %]</label>
- <eg-org-selector selected="ssub.owning_lib"></eg-org-selector>
- </div>
- <div class="form-group">
- <label>[% l('Start Date') %]</label>
- </div>
- <div class="form-group">
- <eg-date-input ng-model="ssub.start_date"></eg-date-input>
- </div>
- <div class="form-group">
- <label>[% l('End Date') %]</label>
- </div>
- <div class="form-group">
- <eg-date-input ng-model="ssub.end_date"></eg-date-input>
- </div>
- <div class="form-group">
- <label>[% l('Expected Offset') %]</label>
- <input type="text" ng-model="ssub.expected_offset"></input>
- </div>
- <button class="btn btn-sm btn-warning" ng-click="add_distribution(ssub)">[% l('Add distribution') %]</button>
- </div>
- <div class="row form-inline" ng-repeat="sdist in ssub.distributions">
- <div class="col-md-1"></div>
- <div class="col-md-5 form-group">
- <label>[% l('Library') %]</label>
- <eg-org-selector selected="sdist.holding_lib"></eg-org-selector>
- <label>[% l('Label') %]</label>
- <input type="text" required ng-model="sdist.label"></input>
- <label>[% l('OPAC Display') %]</label>
- <select required ng-model="sdist.display_grouping">
- <option value="chron">[% l('Chronological') %]</option>
- <option value="enum" >[% l('Enumeration') %]</option>
- </select>
- </div>
- <div class="col-md-2">
- <button class="btn btn-sm btn-info" ng-click="add_stream(sdist)">[% l('Add copy stream') %]</button>
- </div>
- <div class="col-md-3">
- <div class="row" ng-repeat="sstr in sdist.streams">
- <div class="form-inline">
- <label>[% l('Send to') %]</label>
- <input type="text" ng-model="sstr.routing_label"></input>
- </div>
- </div>
- </div>
- </div>
- <div class="row pad-vert"></div>
- </div>
- <div class="row">
- <button class="btn btn-warning pull-left" ng-click="add_subscription()">[% l('New Subscription') %]</button>
- <div class="btn-group pull-right">
- <button class="btn btn-default" ng-disabled="!ssubform.$dirty" ng-click="abort_changes(ssubform)">[% l('Cancel') %]</button>
- <button class="btn btn-primary" ng-disabled="!ssubform.$dirty" ng-click="save_subscriptions(ssubform)">[% l('Save') %]</button>
- </div>
- </div>
- <div class="row pad-vert"></div>
-</form>
-<!-- TODO: move the grid to a separate template file -->
-<div>
- <eg-grid
- id-field="index"
- features="-display,-sort,-multisort"
- items-provider="distStreamGridDataProvider"
- grid-controls="distStreamGridControls"
- persist-key="serials.dist_stream_grid">
-
- <eg-grid-action handler="apply_receiving_template"
- label="[% l('Apply Receiving Template') %]"></eg-grid-action>
- <eg-grid-action handler="apply_binding_template"
- label="[% l('Apply Binding Template') %]"></eg-grid-action>
- <eg-grid-action handler="additional_routing" disabled="need_one_selected"
- label="[% l('Additional Routing') %]"></eg-grid-action>
- <eg-grid-action handler="link_mfhd"
- label="[% l('Link MFHD') %]"></eg-grid-action>
- <eg-grid-action handler="edit_offsets"
- label="[% l('Edit Offsets') %]"></eg-grid-action>
- <eg-grid-action handler="clone_subscription"
- label="[% l('Clone Subscription') %]"></eg-grid-action>
-
- <eg-grid-field label="[% l('Owning Library') %]" path="owning_lib.name" visible></eg-grid-field>
- <eg-grid-field label="[% l('Distribution Library') %]" path="sdist.holding_lib.name" visible></eg-grid-field>
- <eg-grid-field label="[% l('Distribution Label') %]" path="sdist.label" visible></eg-grid-field>
- <eg-grid-field label="[% l('Copy Stream') %]" path="sstr.id" visible></eg-grid-field>
- <eg-grid-field label="[% l('Offset') %]" path="expected_date_offset" visible></eg-grid-field>
- <eg-grid-field label="[% l('Start Date') %]" path="start_date" datatype="timestamp" visible></eg-grid-field>
- <eg-grid-field label="[% l('End Date') %]" path="end_date" datatype="timestamp" visible></eg-grid-field>
- <eg-grid-field label="[% l('Route To') %]" path="sstr.routing_label" visible></eg-grid-field>
- <eg-grid-field label="[% l('Additional Routing') %]" path="sstr.additional_routing" visible></eg-grid-field>
- <eg-grid-field label="[% l('Receiving Template') %]" path="sdist.receive_unit_template.name" visible></eg-grid-field>
- <eg-grid-field label="[% l('MFHD ID') %]" path="sdist.record_entry" visible></eg-grid-field>
- <eg-grid-field label="[% l('Summary Display') %]" path="sdist.summary_method" visible></eg-grid-field>
- <eg-grid-field label="[% l('Receiving Call Number') %]" path="sdist.receive_call_number.label"></eg-grid-field>
- <eg-grid-field label="[% l('Binding Call Number') %]" path="sdist.bind_call_number.label"></eg-grid-field>
- <eg-grid-field label="[% l('Binding Template') %]" path="sdist.bind_unit_template.name"></eg-grid-field>
- <eg-grid-field label="[% l('Unit Label Prefix') %]" path="sdist.unit_label_prefix"></eg-grid-field>
- <eg-grid-field label="[% l('Unit Label Suffix') %]" path="sdist.unit_label_suffix"></eg-grid-field>
- <eg-grid-field label="[% l('Display Grouping') %]" path="sdist.display_grouping"></eg-grid-field>
- <eg-grid-field label="[% l('Subscription ID') %]" path="id"></eg-grid-field>
- <eg-grid-field label="[% l('Distribution ID') %]" path="sdist.id"></eg-grid-field>
- </eg-grid>
-</div>
+ <eg-subscription-manager bib-id="bib_id"></eg-subscription-manager>
</uib-tab>
<uib-tab index="'prediction'" heading="[% l('Manage Predictions') %]">
<p>Frequency TODO</p>
--- /dev/null
+<form name="ssubform">
+ <div ng-repeat="ssub in subscriptions">
+ <div class="row form-inline">
+ <div class="form-group">
+ <label>[% l('Owning Library') %]</label>
+ <eg-org-selector selected="ssub.owning_lib"></eg-org-selector>
+ </div>
+ <div class="form-group">
+ <label>[% l('Start Date') %]</label>
+ </div>
+ <div class="form-group">
+ <eg-date-input ng-model="ssub.start_date"></eg-date-input>
+ </div>
+ <div class="form-group">
+ <label>[% l('End Date') %]</label>
+ </div>
+ <div class="form-group">
+ <eg-date-input ng-model="ssub.end_date"></eg-date-input>
+ </div>
+ <div class="form-group">
+ <label>[% l('Expected Offset') %]</label>
+ <input type="text" ng-model="ssub.expected_offset"></input>
+ </div>
+ <button class="btn btn-sm btn-warning" ng-click="add_distribution(ssub)">[% l('Add distribution') %]</button>
+ </div>
+ <div class="row form-inline" ng-repeat="sdist in ssub.distributions">
+ <div class="col-md-1"></div>
+ <div class="col-md-5 form-group">
+ <label>[% l('Library') %]</label>
+ <eg-org-selector selected="sdist.holding_lib"></eg-org-selector>
+ <label>[% l('Label') %]</label>
+ <input type="text" required ng-model="sdist.label"></input>
+ <label>[% l('OPAC Display') %]</label>
+ <select required ng-model="sdist.display_grouping">
+ <option value="chron">[% l('Chronological') %]</option>
+ <option value="enum" >[% l('Enumeration') %]</option>
+ </select>
+ </div>
+ <div class="col-md-2">
+ <button class="btn btn-sm btn-info" ng-click="add_stream(sdist)">[% l('Add copy stream') %]</button>
+ </div>
+ <div class="col-md-3">
+ <div class="row" ng-repeat="sstr in sdist.streams">
+ <div class="form-inline">
+ <label>[% l('Send to') %]</label>
+ <input type="text" ng-model="sstr.routing_label"></input>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="row pad-vert"></div>
+ </div>
+ <div class="row">
+ <button class="btn btn-warning pull-left" ng-click="add_subscription()">[% l('New Subscription') %]</button>
+ <div class="btn-group pull-right">
+ <button class="btn btn-default" ng-disabled="!ssubform.$dirty" ng-click="abort_changes(ssubform)">[% l('Cancel') %]</button>
+ <button class="btn btn-primary" ng-disabled="!ssubform.$dirty" ng-click="save_subscriptions(ssubform)">[% l('Save') %]</button>
+ </div>
+ </div>
+ <div class="row pad-vert"></div>
+</form>
+<div>
+ <eg-grid
+ id-field="index"
+ features="-display,-sort,-multisort"
+ items-provider="distStreamGridDataProvider"
+ grid-controls="distStreamGridControls"
+ persist-key="serials.dist_stream_grid">
+
+ <eg-grid-action handler="apply_receiving_template"
+ label="[% l('Apply Receiving Template') %]"></eg-grid-action>
+ <eg-grid-action handler="apply_binding_template"
+ label="[% l('Apply Binding Template') %]"></eg-grid-action>
+ <eg-grid-action handler="additional_routing" disabled="need_one_selected"
+ label="[% l('Additional Routing') %]"></eg-grid-action>
+ <eg-grid-action handler="link_mfhd"
+ label="[% l('Link MFHD') %]"></eg-grid-action>
+ <eg-grid-action handler="edit_offsets"
+ label="[% l('Edit Offsets') %]"></eg-grid-action>
+ <eg-grid-action handler="clone_subscription"
+ label="[% l('Clone Subscription') %]"></eg-grid-action>
+
+ <eg-grid-field label="[% l('Owning Library') %]" path="owning_lib.name" visible></eg-grid-field>
+ <eg-grid-field label="[% l('Distribution Library') %]" path="sdist.holding_lib.name" visible></eg-grid-field>
+ <eg-grid-field label="[% l('Distribution Label') %]" path="sdist.label" visible></eg-grid-field>
+ <eg-grid-field label="[% l('Copy Stream') %]" path="sstr.id" visible></eg-grid-field>
+ <eg-grid-field label="[% l('Offset') %]" path="expected_date_offset" visible></eg-grid-field>
+ <eg-grid-field label="[% l('Start Date') %]" path="start_date" datatype="timestamp" visible></eg-grid-field>
+ <eg-grid-field label="[% l('End Date') %]" path="end_date" datatype="timestamp" visible></eg-grid-field>
+ <eg-grid-field label="[% l('Route To') %]" path="sstr.routing_label" visible></eg-grid-field>
+ <eg-grid-field label="[% l('Additional Routing') %]" path="sstr.additional_routing" visible></eg-grid-field>
+ <eg-grid-field label="[% l('Receiving Template') %]" path="sdist.receive_unit_template.name" visible></eg-grid-field>
+ <eg-grid-field label="[% l('MFHD ID') %]" path="sdist.record_entry" visible></eg-grid-field>
+ <eg-grid-field label="[% l('Summary Display') %]" path="sdist.summary_method" visible></eg-grid-field>
+ <eg-grid-field label="[% l('Receiving Call Number') %]" path="sdist.receive_call_number.label"></eg-grid-field>
+ <eg-grid-field label="[% l('Binding Call Number') %]" path="sdist.bind_call_number.label"></eg-grid-field>
+ <eg-grid-field label="[% l('Binding Template') %]" path="sdist.bind_unit_template.name"></eg-grid-field>
+ <eg-grid-field label="[% l('Unit Label Prefix') %]" path="sdist.unit_label_prefix"></eg-grid-field>
+ <eg-grid-field label="[% l('Unit Label Suffix') %]" path="sdist.unit_label_suffix"></eg-grid-field>
+ <eg-grid-field label="[% l('Display Grouping') %]" path="sdist.display_grouping"></eg-grid-field>
+ <eg-grid-field label="[% l('Subscription ID') %]" path="id"></eg-grid-field>
+ <eg-grid-field label="[% l('Distribution ID') %]" path="sdist.id"></eg-grid-field>
+ </eg-grid>
+</div>
-angular.module('egSerialsApp', ['ui.bootstrap','ngRoute','egCoreMod','egGridMod','ngToast','egSerialsMod'])
+angular.module('egSerialsApp', ['ui.bootstrap','ngRoute','egCoreMod','egGridMod','ngToast','egSerialsMod','egSerialsAppDep']);
+angular.module('egSerialsAppDep', []);
+angular.module('egSerialsApp')
.config(['ngToastProvider', function(ngToastProvider) {
ngToastProvider.configure({
verticalPosition: 'bottom',
})
.controller('ManageCtrl',
- ['$scope','$routeParams','$location','$window','$q','egSerialsCoreSvc','egCore',
- 'egGridDataProvider','$uibModal',
-function($scope , $routeParams , $location , $window , $q , egSerialsCoreSvc , egCore ,
- egGridDataProvider , $uibModal
-) {
+ ['$scope','$routeParams','$location',
+function($scope , $routeParams , $location) {
$scope.bib_id = $routeParams.bib_id;
$scope.active_tab = $routeParams.active_tab ? $routeParams.active_tab : 'create-subscription';
- egSerialsCoreSvc.fetch($scope.bib_id).then(function() {
- $scope.subscriptions = egCore.idl.toTypedHash(egSerialsCoreSvc.subTree);
- });
- $scope.distStreamGridControls = {
- activateItem : function (item) { } // TODO
- };
- $scope.distStreamGridDataProvider = egGridDataProvider.instance({
- get : function(offset, count) {
- return this.arrayNotifier(egSerialsCoreSvc.subList, offset, count);
- }
- });
-
- function reload() {
- egSerialsCoreSvc.fetch($scope.bib_id).then(function() {
- $scope.subscriptions = egCore.idl.toTypedHash(egSerialsCoreSvc.subTree);
- $scope.distStreamGridDataProvider.refresh();
- });
- }
-
- $scope.need_one_selected = function() {
- var items = $scope.distStreamGridControls.selectedItems();
- if (items.length == 1) return false;
- return true;
- };
-
- $scope.add_subscription = function() {
- var new_ssub = egCore.idl.toTypedHash(new egCore.idl.ssub());
- new_ssub._isnew = true;
- new_ssub.record_entry = $scope.bib_id;
- $scope.subscriptions.push(new_ssub);
- }
- $scope.add_distribution = function(ssub) {
- var new_sdist = egCore.idl.toTypedHash(new egCore.idl.sdist());
- new_sdist._isnew = true;
- new_sdist.subscription = ssub.id;
- if (!angular.isArray(ssub.distributions)){
- ssub.distributions = [];
- }
- ssub.distributions.push(new_sdist);
- }
- $scope.add_stream = function(sdist) {
- var new_sstr = egCore.idl.toTypedHash(new egCore.idl.sstr());
- new_sstr.distribution = sdist.id;
- new_sstr._isnew = true;
- if (!angular.isArray(sdist.streams)){
- sdist.streams = [];
- }
- sdist.streams.push(new_sstr);
- }
-
- $scope.abort_changes = function(form) {
- reload();
- form.$setPristine();
- }
- $scope.save_subscriptions = function(form) {
- // traverse through structure and set _ischanged
- // TODO add more granular dirty input detection
- angular.forEach($scope.subscriptions, function(ssub) {
- if (!ssub._isnew) ssub._ischanged = true;
- angular.forEach(ssub.distributions, function(sdist) {
- if (!sdist._isnew) sdist._ischanged = true;
- angular.forEach(sdist.streams, function(sstr) {
- if (!sstr._isnew) sstr._ischanged = true;
- });
- });
- });
-
- var obj = egCore.idl.fromTypedHash($scope.subscriptions);
-
- // create a bunch of promises that each get resolved upon each
- // CUD update; that way, we can know when the entire save
- // operation is completed
- var promises = [];
- angular.forEach(obj, function(ssub) {
- ssub._cud_done = $q.defer();
- promises.push(ssub._cud_done.promise);
- angular.forEach(ssub.distributions(), function(sdist) {
- sdist._cud_done = $q.defer();
- promises.push(sdist._cud_done.promise);
- angular.forEach(sdist.streams(), function(sstr) {
- sstr._cud_done = $q.defer();
- promises.push(sstr._cud_done.promise);
- });
- });
- });
-
- angular.forEach(obj, function(ssub) {
- ssub.owning_lib(ssub.owning_lib().id()); // deflesh
- egCore.pcrud.apply(ssub).then(function(res) {
- var ssub_id = (ssub.isnew() && angular.isObject(res)) ? res.id() : ssub.id();
- angular.forEach(ssub.distributions(), function(sdist) {
- // set subscription ID just in case it's new
- sdist.holding_lib(sdist.holding_lib().id()); // deflesh
- sdist.subscription(ssub_id);
- egCore.pcrud.apply(sdist).then(function(res) {
- var sdist_id = (sdist.isnew() && angular.isObject(res)) ? res.id() : sdist.id();
- angular.forEach(sdist.streams(), function(sstr) {
- // set distribution ID just in case it's new
- sstr.distribution(sdist_id);
- egCore.pcrud.apply(sstr).then(function(res) {
- sstr._cud_done.resolve();
- });
- });
- });
- sdist._cud_done.resolve();
- });
- ssub._cud_done.resolve();
- });
- });
- $q.all(promises).then(function(resolutions) {
- reload();
- form.$setPristine();
- });
- }
- $scope.additional_routing = function(rows) {
- if (!rows) { return; }
- var row = rows[0];
- if (!row) { row = $scope.distStreamGridControls.selectedItems()[0]; }
- if (row && row['sstr.id']) {
- egCore.pcrud.search('srlu', {
- stream : row['sstr.id']
- }, {
- flesh : 2,
- flesh_fields : {
- 'srlu' : ['reader'],
- 'au' : ['mailing_address','billing_address','home_ou']
- },
- order_by : { srlu : 'pos' }
- },
- { atomic : true }
- ).then(function(list) {
- $uibModal.open({
- templateUrl: './serials/t_routing_list',
- controller: 'RoutingCtrl',
- resolve : {
- rowInfo : function() {
- return row;
- },
- routes : function() {
- return egCore.idl.toHash(list);
- }
- }
- }).result.then(function(routes) {
- // delete all of the routes first;
- // it's easiest given the constraints
- var deletions = [];
- var creations = [];
- angular.forEach(routes, function(r) {
- var srlu = new egCore.idl.srlu();
- srlu.stream(r.stream);
- srlu.pos(r.pos);
- if (r.reader) {
- srlu.reader(r.reader.id);
- }
- srlu.department(r.department);
- srlu.note(r.note);
- if (r.id) {
- srlu.id(r.id);
- var srlu_copy = angular.copy(srlu);
- srlu_copy.isdeleted(true);
- deletions.push(srlu_copy);
- }
- if (!r.delete_me) {
- srlu.isnew(true);
- creations.push(srlu);
- }
- });
- egCore.pcrud.apply(deletions.concat(creations)).then(function(){
- reload();
- });
- });
- });
- }
- }
-}])
-
-.controller('RoutingCtrl',
- ['$scope','$uibModalInstance','egCore','rowInfo','routes',
-function($scope , $uibModalInstance , egCore , rowInfo , routes ) {
- $scope.args = {
- which_radio_button: 'reader'
- ,reader: ''
- ,department: ''
- ,delete_me: false
- };
- $scope.stream_id = rowInfo['sstr.id'];
- $scope.stream_label = rowInfo['sstr.routing_label'];
- $scope.routes = routes;
- $scope.readerInFocus = true;
- $scope.ok = function(count) { $uibModalInstance.close($scope.routes) }
- $scope.cancel = function () { $uibModalInstance.dismiss() }
- $scope.model_has_changed = false;
- $scope.find_user = function () {
-
- $scope.readerNotFound = null;
- $scope.reader_obj = null;
- if (!$scope.args.reader) return;
-
- egCore.net.request(
- 'open-ils.actor',
- 'open-ils.actor.get_barcodes',
- egCore.auth.token(), egCore.auth.user().ws_ou(),
- 'actor', $scope.args.reader)
-
- .then(function(resp) { // get_barcodes
-
- if (evt = egCore.evt.parse(resp)) {
- console.error(evt.toString());
- return;
- }
-
- if (!resp || !resp[0]) {
- $scope.readerNotFound = $scope.args.reader;
- return;
- }
-
- egCore.pcrud.search('au', {
- id : resp[0].id
- }, {
- flesh : 1,
- flesh_fields : {
- 'au' : ['mailing_address','billing_address','home_ou']
- }
- },
- { atomic : true }
- ).then(function(usr) {
- $scope.reader_obj = egCore.idl.toHash(usr[0]);
- });
- });
- }
- $scope.add_route = function () {
- var new_route = {
- stream: $scope.stream_id
- ,pos: $scope.routes.length
- ,note: $scope.args.note
- }
- if ($scope.args.which_radio_button == 'reader') {
- new_route.reader = $scope.reader_obj;
- } else {
- new_route.department = $scope.args.department;
- }
- $scope.routes.push(new_route);
- $scope.model_has_changed = true;
- }
- function adjust_pos_field() {
- var idx = 0;
- for (var i = 0; i < $scope.routes.length; i++) {
- $scope.routes[i].pos = $scope.routes[i].delete_me ? idx : idx++;
- }
- $scope.model_has_changed = true;
- }
- $scope.move_route_up = function(r) {
- var pos = r.pos;
- if (pos > 0) {
- var temp = $scope.routes[ pos - 1 ];
- $scope.routes[ pos - 1 ] = $scope.routes[ pos ];
- $scope.routes[ pos ] = temp;
- adjust_pos_field();
- }
- }
- $scope.move_route_down = function(r) {
- var pos = r.pos;
- if (pos < $scope.routes.length - 1) {
- var temp = $scope.routes[ pos + 1 ];
- $scope.routes[ pos + 1 ] = $scope.routes[ pos ];
- $scope.routes[ pos ] = temp;
- adjust_pos_field();
- }
- }
- $scope.toggle_delete = function(r) {
- r.delete_me = ! r.delete_me;
- adjust_pos_field();
- }
- $scope.$watch("args.reader", function(newVal, oldVal) {
- if (newVal && newVal != oldVal) {
- $scope.find_user();
- }
- });
}])
--- /dev/null
+angular.module('egSerialsAppDep')
+
+.directive('egSubscriptionManager', function() {
+ return {
+ transclude: true,
+ restrict: 'E',
+ scope: {
+ bibId : '='
+ },
+ templateUrl: './serials/t_subscription_manager',
+ controller:
+ ['$scope','$q','egSerialsCoreSvc','egCore','egGridDataProvider',
+ '$uibModal',
+ function($scope , $q , egSerialsCoreSvc , egCore , egGridDataProvider ,
+ $uibModal) {
+ egSerialsCoreSvc.fetch($scope.bibId).then(function() {
+ $scope.subscriptions = egCore.idl.toTypedHash(egSerialsCoreSvc.subTree);
+ });
+ $scope.distStreamGridControls = {
+ activateItem : function (item) { } // TODO
+ };
+ $scope.distStreamGridDataProvider = egGridDataProvider.instance({
+ get : function(offset, count) {
+ return this.arrayNotifier(egSerialsCoreSvc.subList, offset, count);
+ }
+ });
+
+ function reload() {
+ egSerialsCoreSvc.fetch($scope.bibId).then(function() {
+ $scope.subscriptions = egCore.idl.toTypedHash(egSerialsCoreSvc.subTree);
+ $scope.distStreamGridDataProvider.refresh();
+ });
+ }
+
+ $scope.need_one_selected = function() {
+ var items = $scope.distStreamGridControls.selectedItems();
+ if (items.length == 1) return false;
+ return true;
+ };
+
+ $scope.add_subscription = function() {
+ var new_ssub = egCore.idl.toTypedHash(new egCore.idl.ssub());
+ new_ssub._isnew = true;
+ new_ssub.record_entry = $scope.bibId;
+ $scope.subscriptions.push(new_ssub);
+ }
+ $scope.add_distribution = function(ssub) {
+ var new_sdist = egCore.idl.toTypedHash(new egCore.idl.sdist());
+ new_sdist._isnew = true;
+ new_sdist.subscription = ssub.id;
+ if (!angular.isArray(ssub.distributions)){
+ ssub.distributions = [];
+ }
+ ssub.distributions.push(new_sdist);
+ }
+ $scope.add_stream = function(sdist) {
+ var new_sstr = egCore.idl.toTypedHash(new egCore.idl.sstr());
+ new_sstr.distribution = sdist.id;
+ new_sstr._isnew = true;
+ if (!angular.isArray(sdist.streams)){
+ sdist.streams = [];
+ }
+ sdist.streams.push(new_sstr);
+ }
+
+ $scope.abort_changes = function(form) {
+ reload();
+ form.$setPristine();
+ }
+ $scope.save_subscriptions = function(form) {
+ // traverse through structure and set _ischanged
+ // TODO add more granular dirty input detection
+ angular.forEach($scope.subscriptions, function(ssub) {
+ if (!ssub._isnew) ssub._ischanged = true;
+ angular.forEach(ssub.distributions, function(sdist) {
+ if (!sdist._isnew) sdist._ischanged = true;
+ angular.forEach(sdist.streams, function(sstr) {
+ if (!sstr._isnew) sstr._ischanged = true;
+ });
+ });
+ });
+
+ var obj = egCore.idl.fromTypedHash($scope.subscriptions);
+
+ // create a bunch of promises that each get resolved upon each
+ // CUD update; that way, we can know when the entire save
+ // operation is completed
+ var promises = [];
+ angular.forEach(obj, function(ssub) {
+ ssub._cud_done = $q.defer();
+ promises.push(ssub._cud_done.promise);
+ angular.forEach(ssub.distributions(), function(sdist) {
+ sdist._cud_done = $q.defer();
+ promises.push(sdist._cud_done.promise);
+ angular.forEach(sdist.streams(), function(sstr) {
+ sstr._cud_done = $q.defer();
+ promises.push(sstr._cud_done.promise);
+ });
+ });
+ });
+
+ angular.forEach(obj, function(ssub) {
+ ssub.owning_lib(ssub.owning_lib().id()); // deflesh
+ egCore.pcrud.apply(ssub).then(function(res) {
+ var ssub_id = (ssub.isnew() && angular.isObject(res)) ? res.id() : ssub.id();
+ angular.forEach(ssub.distributions(), function(sdist) {
+ // set subscription ID just in case it's new
+ sdist.holding_lib(sdist.holding_lib().id()); // deflesh
+ sdist.subscription(ssub_id);
+ egCore.pcrud.apply(sdist).then(function(res) {
+ var sdist_id = (sdist.isnew() && angular.isObject(res)) ? res.id() : sdist.id();
+ angular.forEach(sdist.streams(), function(sstr) {
+ // set distribution ID just in case it's new
+ sstr.distribution(sdist_id);
+ egCore.pcrud.apply(sstr).then(function(res) {
+ sstr._cud_done.resolve();
+ });
+ });
+ });
+ sdist._cud_done.resolve();
+ });
+ ssub._cud_done.resolve();
+ });
+ });
+ $q.all(promises).then(function(resolutions) {
+ reload();
+ form.$setPristine();
+ });
+ }
+ $scope.additional_routing = function(rows) {
+ if (!rows) { return; }
+ var row = rows[0];
+ if (!row) { row = $scope.distStreamGridControls.selectedItems()[0]; }
+ if (row && row['sstr.id']) {
+ egCore.pcrud.search('srlu', {
+ stream : row['sstr.id']
+ }, {
+ flesh : 2,
+ flesh_fields : {
+ 'srlu' : ['reader'],
+ 'au' : ['mailing_address','billing_address','home_ou']
+ },
+ order_by : { srlu : 'pos' }
+ },
+ { atomic : true }
+ ).then(function(list) {
+ $uibModal.open({
+ templateUrl: './serials/t_routing_list',
+ controller: 'RoutingCtrl',
+ resolve : {
+ rowInfo : function() {
+ return row;
+ },
+ routes : function() {
+ return egCore.idl.toHash(list);
+ }
+ }
+ }).result.then(function(routes) {
+ // delete all of the routes first;
+ // it's easiest given the constraints
+ var deletions = [];
+ var creations = [];
+ angular.forEach(routes, function(r) {
+ var srlu = new egCore.idl.srlu();
+ srlu.stream(r.stream);
+ srlu.pos(r.pos);
+ if (r.reader) {
+ srlu.reader(r.reader.id);
+ }
+ srlu.department(r.department);
+ srlu.note(r.note);
+ if (r.id) {
+ srlu.id(r.id);
+ var srlu_copy = angular.copy(srlu);
+ srlu_copy.isdeleted(true);
+ deletions.push(srlu_copy);
+ }
+ if (!r.delete_me) {
+ srlu.isnew(true);
+ creations.push(srlu);
+ }
+ });
+ egCore.pcrud.apply(deletions.concat(creations)).then(function(){
+ reload();
+ });
+ });
+ });
+ }
+ }
+ }]
+ }
+})
+
+.controller('RoutingCtrl',
+ ['$scope','$uibModalInstance','egCore','rowInfo','routes',
+function($scope , $uibModalInstance , egCore , rowInfo , routes ) {
+ $scope.args = {
+ which_radio_button: 'reader'
+ ,reader: ''
+ ,department: ''
+ ,delete_me: false
+ };
+ $scope.stream_id = rowInfo['sstr.id'];
+ $scope.stream_label = rowInfo['sstr.routing_label'];
+ $scope.routes = routes;
+ $scope.readerInFocus = true;
+ $scope.ok = function(count) { $uibModalInstance.close($scope.routes) }
+ $scope.cancel = function () { $uibModalInstance.dismiss() }
+ $scope.model_has_changed = false;
+ $scope.find_user = function () {
+
+ $scope.readerNotFound = null;
+ $scope.reader_obj = null;
+ if (!$scope.args.reader) return;
+
+ egCore.net.request(
+ 'open-ils.actor',
+ 'open-ils.actor.get_barcodes',
+ egCore.auth.token(), egCore.auth.user().ws_ou(),
+ 'actor', $scope.args.reader)
+
+ .then(function(resp) { // get_barcodes
+
+ if (evt = egCore.evt.parse(resp)) {
+ console.error(evt.toString());
+ return;
+ }
+
+ if (!resp || !resp[0]) {
+ $scope.readerNotFound = $scope.args.reader;
+ return;
+ }
+
+ egCore.pcrud.search('au', {
+ id : resp[0].id
+ }, {
+ flesh : 1,
+ flesh_fields : {
+ 'au' : ['mailing_address','billing_address','home_ou']
+ }
+ },
+ { atomic : true }
+ ).then(function(usr) {
+ $scope.reader_obj = egCore.idl.toHash(usr[0]);
+ });
+ });
+ }
+ $scope.add_route = function () {
+ var new_route = {
+ stream: $scope.stream_id
+ ,pos: $scope.routes.length
+ ,note: $scope.args.note
+ }
+ if ($scope.args.which_radio_button == 'reader') {
+ new_route.reader = $scope.reader_obj;
+ } else {
+ new_route.department = $scope.args.department;
+ }
+ $scope.routes.push(new_route);
+ $scope.model_has_changed = true;
+ }
+ function adjust_pos_field() {
+ var idx = 0;
+ for (var i = 0; i < $scope.routes.length; i++) {
+ $scope.routes[i].pos = $scope.routes[i].delete_me ? idx : idx++;
+ }
+ $scope.model_has_changed = true;
+ }
+ $scope.move_route_up = function(r) {
+ var pos = r.pos;
+ if (pos > 0) {
+ var temp = $scope.routes[ pos - 1 ];
+ $scope.routes[ pos - 1 ] = $scope.routes[ pos ];
+ $scope.routes[ pos ] = temp;
+ adjust_pos_field();
+ }
+ }
+ $scope.move_route_down = function(r) {
+ var pos = r.pos;
+ if (pos < $scope.routes.length - 1) {
+ var temp = $scope.routes[ pos + 1 ];
+ $scope.routes[ pos + 1 ] = $scope.routes[ pos ];
+ $scope.routes[ pos ] = temp;
+ adjust_pos_field();
+ }
+ }
+ $scope.toggle_delete = function(r) {
+ r.delete_me = ! r.delete_me;
+ adjust_pos_field();
+ }
+ $scope.$watch("args.reader", function(newVal, oldVal) {
+ if (newVal && newVal != oldVal) {
+ $scope.find_user();
+ }
+ });
+}])