LP#1402797 Initial MARC editor -- load, edit content, save, see the Breaker version
authorMike Rylander <mrylander@gmail.com>
Thu, 5 Feb 2015 03:46:20 +0000 (22:46 -0500)
committerBill Erickson <berickxx@gmail.com>
Wed, 25 Feb 2015 16:16:07 +0000 (11:16 -0500)
Signed-off-by: Mike Rylander <mrylander@gmail.com>
Signed-off-by: Bill Erickson <berickxx@gmail.com>
Open-ILS/src/templates/staff/cat/catalog/index.tt2
Open-ILS/src/templates/staff/cat/catalog/t_catalog.tt2
Open-ILS/web/js/ui/default/staff/cat/catalog/app.js
Open-ILS/web/js/ui/default/staff/cat/services/marcedit.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/marcrecord.js

index 919b900..56a4ea9 100644 (file)
@@ -9,6 +9,7 @@
 <script src="[% ctx.media_prefix %]/js/ui/default/staff/services/grid.js"></script>
 <script src="[% ctx.media_prefix %]/js/ui/default/staff/services/eframe.js"></script>
 <script src="[% ctx.media_prefix %]/js/ui/default/staff/cat/services/record.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/cat/services/marcedit.js"></script>
 <script src="[% ctx.media_prefix %]/js/ui/default/staff/circ/services/circ.js"></script>
 [% INCLUDE 'staff/circ/share/circ_strings.tt2' %]
 <script src="[% ctx.media_prefix %]/js/ui/default/staff/circ/services/holds.js"></script>
index 29a6eb6..972fa62 100644 (file)
@@ -2,6 +2,7 @@
 <div class="row pad-vert col-md-12 alert alert-info alert-less-pad strong-text-2">
   <span ng-if="record_tab == 'catalog'">[% l('Catalog') %]</span>
   <span ng-if="record_tab == 'marc_html'">[% l('MARC HTML') %]</span>
+  <span ng-if="record_tab == 'marc_edit'">[% l('Edit MARC') %]</span>
   <span ng-if="record_tab == 'holds'">[% l('Holds for Record') %]</span>
 </div>
 
@@ -22,6 +23,8 @@
       <ul class="dropdown-menu dropdown-menu-right" role="menu">
         <li><a href ng-click="set_record_tab('catalog')">
             [% l('OPAC View') %]</a></li>
+        <li><a href ng-click="set_record_tab('marc_edit')">
+            [% l('MARC Edit') %]</a></li>
         <li><a href ng-click="set_record_tab('marc_html')">
             [% l('MARC View') %]</a></li>
         <li class="divider"></li>
@@ -44,6 +47,9 @@
     <eg-embed-frame url="catalog_url" handlers="handlers" onchange="handle_page"></eg-embed-frame>
   </div>
   <!-- ng-if the remaining tabs so they can be instantiated on demand -->
+  <div ng-if="record_tab == 'marc_edit'">
+    <eg-marc-edit-record record-id="record_id"></eg-marc-edit-record>
+  </div>
   <div ng-if="record_tab == 'marc_html'">
     <eg-record-html record-id="record_id"></eg-record-html>
   </div>
index 181a9ff..4cd81d7 100644 (file)
@@ -7,7 +7,7 @@
  *
  */
 
-angular.module('egCatalogApp', ['ui.bootstrap','ngRoute','egCoreMod','egGridMod'])
+angular.module('egCatalogApp', ['ui.bootstrap','ngRoute','egCoreMod','egGridMod', 'egMarcMod'])
 
 .config(function($routeProvider, $locationProvider, $compileProvider) {
     $locationProvider.html5Mode(true);
diff --git a/Open-ILS/web/js/ui/default/staff/cat/services/marcedit.js b/Open-ILS/web/js/ui/default/staff/cat/services/marcedit.js
new file mode 100644 (file)
index 0000000..8ba6b4a
--- /dev/null
@@ -0,0 +1,214 @@
+/**
+ *  A MARC editor...
+ */
+
+angular.module('egMarcMod', ['egCoreMod', 'ui.bootstrap'])
+
+.directive("egContextMenuItem", function () {
+    return {
+        restrict: 'E',
+        replace: false,
+        template: '<li ng-click="setContent(item.value,item.action)">{{label}}</li>',
+        scope: { item: '=' },
+        controller: ['$scope','$element',
+            function ($scope , $element) {
+                if (!$scope.item.label) $scope.item.label = $scope.item.value;
+                if ($scope.item.divider) {
+                    $element.style.borderTop = 'solid 1px';
+                }
+
+                $scope.setContent = function (v, a) {
+                    if (a) { v = a($scope,v); }
+                    $scope.$apply("item.value=v");
+                    $( $($scope.element).parent() ).parent().empty().remove();
+                    $scope.$parent.$destroy();
+                }
+            }
+        ]
+    }
+})
+
+.directive("egMarcEditEditable", ['$document', function ($document) {
+    function showContext(event) {
+        event.preventDefault();
+        var con = event.data.scope.contextitems;
+
+        if (angular.isArray(con)) { // we have a list of values or transforms
+            var tmpl = 
+            '<div class="dropdown" dropdown is-open="true">'+
+                '<ul class="dropdown-menu" role="menu">'+
+                    '<eg-context-menu-item ng-repeat="item in contextitems" item="item"/>'+
+                '</ul>'+
+            '</div>';
+
+            var el = $compile(tmpl)(event.data);
+            el.css({
+                postion: 'absolute',
+                top: event.pageY,
+                left: event.pageX
+            });
+
+            $document.append(el);
+        }
+    }
+
+    return {
+        restrict: 'E',
+        replace: false,
+        template: '<input style="font-family: \'Lucida Console\', Monaco, monospace;" ng-model="content" size="{{content.length * 1.1}}" maxlength="{{max}}" class="" type="text"/>',
+        transclude: true,
+        scope: {
+            content: '=',
+            //contextitems: '=',
+            max: '@',
+            type: '@'
+        },
+//        controller : ['$scope',
+//            function ( $scope ) {
+//                $scope.minsize = $scope.max || $scope.content.length;
+//                if (!$scope.contextitems) $scope.contextitems = {};
+//            }
+//        ],
+        link: function (scope, element, attrs) {
+
+            element.bind('change', {}, function (e) { element.size = scope.max || scope.content.length * 1.1});
+
+            if (scope.contextitems && angular.isArray(scope.contextitems)) {
+                element.bind('context', { scope : scope, element : element }, showContext);
+            }
+        }
+    }
+}])
+
+.directive("egMarcEditSubfield", function () {
+    return {
+        restrict: 'E',
+        template: '<span>'+
+                    '<span><eg-marc-edit-editable type="sfc" class="marcsfcode" content="subfield[0]" max="1"/></span>'+
+                    '<span><eg-marc-edit-editable type="sfv" class="marcsfvalue" content="subfield[1]"/></span>'+
+                  '</span>',
+        scope: { field: "=", subfield: "=" },
+        replace: false
+    }
+})
+
+.directive("egMarcEditInd", function () {
+    return {
+        restrict: 'E',
+        template: '<span><eg-marc-edit-editable type="ind" content="ind" max="1"/></span>',
+        scope: { ind : '=' },
+        replace: false,
+    }
+})
+
+.directive("egMarcEditTag", function () {
+    return {
+        restrict: 'E',
+        template: '<span><eg-marc-edit-editable type="tag" content="tag" max="3"/></span>',
+        scope: { tag : '=' },
+        replace: false
+    }
+})
+
+.directive("egMarcEditDatafield", function () {
+    return {
+        restrict: 'E',
+        template: '<div>'+
+                    '<span><eg-marc-edit-tag class="marctag" tag="field.tag"/></span>'+
+                    '<span><eg-marc-edit-ind class="marcind" ind="field.ind1"/></span>'+
+                    '<span><eg-marc-edit-ind class="marcind" ind="field.ind2"/></span>'+
+                    '<span><eg-marc-edit-subfield ng-repeat="subfield in field.subfields" subfield="subfield" field="field"/></span>'+
+                  '</div>',
+        scope: { field: "=" }
+    }
+})
+
+.directive("egMarcEditControlfield", function () {
+    return {
+        restrict: 'E',
+        template: '<div>'+
+                    '<span><eg-marc-edit-tag class="marctag" tag="field.tag"/></span>'+
+                    '<span><eg-marc-edit-editable type="cfld" class="marcdata" content="field.data"/></span>'+
+                  '</div>',
+        scope: { field: "=" }
+    }
+})
+
+.directive("egMarcEditLeader", function () {
+    return {
+        restrict: 'E',
+        template: '<div>'+
+                    '<span><eg-marc-edit-editable class="marctag" content="tag"/></span>'+
+                    '<span><eg-marc-edit-editable class="marcdata" max="{{record.leader.length}}" content="record.leader"/></span>'+
+                  '</div>',
+        controller : ['$scope',
+            function ( $scope ) {
+                $scope.tag = 'LDR';
+            }
+        ],
+        scope: { record: "=" }
+    }
+})
+
+/// TODO: fixed field editor and such
+.directive("egMarcEditRecord", function () {
+    return {
+        template: '<form ng-submit="saveRecord()">'+
+                  '<div class="marcrecord">'+
+                    '<div><eg-marc-edit-leader record="record"/></div>'+
+                    '<div><eg-marc-edit-controlfield ng-repeat="field in controlfields" field="field"/></div>'+
+                    '<div><eg-marc-edit-datafield ng-repeat="field in datafields" field="field"/></div>'+
+                  '</div>'+
+                  '<button class="btn btn-default" type="submit">Save</button>'+
+                  '</form>'+
+                  '<button class="btn btn-default" ng-click="seeBreaker()">Breaker</button>',
+        restrict: 'E',
+        replace: false,
+        scope: { recordId : '=' },
+        controller : ['$scope','egCore',
+            function ( $scope , egCore ) {
+
+                function loadRecord() {
+                    return egCore.pcrud.retrieve(
+                        'bre', $scope.recordId
+                    ).then(function(rec) {
+                        $scope.bre = rec;
+                        $scope.record = new MARC.Record();
+                        $scope.record.fromXmlString( $scope.bre.marc() );
+                        $scope.controlfields = $scope.record.fields.filter(function(f){ return f.isControlfield() });
+                        $scope.datafields = $scope.record.fields.filter(function(f){ return !f.isControlfield() });
+                    });
+                }
+
+                $scope.saveRecord = function () {
+                    $scope.bre.marc($scope.record.toXmlString());
+                    return egCore.pcrud.update(
+                        $scope.bre
+                    ).then(loadRecord);
+                };
+
+                $scope.seeBreaker = function () {
+                    alert($scope.record.toBreaker());
+                };
+
+                $scope.$watch('recordId',
+                    function(newVal, oldVal) {
+                        if (newVal && newVal !== oldVal) {
+                            loadRecord();
+                        }
+                    }
+                );
+
+
+                $scope.controlfields = [];
+                $scope.datafields = [];
+
+                if ($scope.recordId)
+                    loadRecord();
+
+            }
+        ]          
+    }
+})
+
+;
index 9dd0a23..876540a 100644 (file)
@@ -118,7 +118,7 @@ var MARC = {
         this.fromXmlURL = function (url) {
             this.ready   = false;
             var me = this;
-            $.get(
+            return $.get( // This is a Promise
                 url,
                 function (mxml) {
                     me.fromXmlDocument($('record', mxml)[0]);
@@ -128,7 +128,7 @@ var MARC = {
         },
 
         this.fromXmlString = function (mxml) {
-                this.fromXmlDocument( $.parseXML( mxml ).find('record')[0] );
+                this.fromXmlDocument( $( $.parseXML( mxml ) ).find('record')[0] );
         },
 
         this.fromXmlDocument = function (mxml) {