@@ -, +, @@ --- C4/Biblio.pm | 28 +- C4/ImportBatch.pm | 20 +- cataloguing/editor.pl | 2 +- .../lib/koha/cateditor/koha-backend.js | 52 +++ .../lib/koha/cateditor/preferences.js | 2 + koha-tmpl/intranet-tmpl/prog/css/cateditor.css | 46 ++- .../prog/en/includes/cateditor-ui.inc | 347 +++++++++++++++++++-- .../prog/en/modules/cataloguing/editor.tt | 44 ++- svc/cataloguing/import_batches | 212 +++++++++++++ 9 files changed, 698 insertions(+), 55 deletions(-) create mode 100755 svc/cataloguing/import_batches --- a/C4/Biblio.pm +++ a/C4/Biblio.pm @@ -3266,6 +3266,27 @@ sub _koha_delete_biblio_metadata { =head1 UNEXPORTED FUNCTIONS +=head2 Update005Time + + &Update005Time( $record ); + +Updates the 005 timestamp of the given record to the current time. + +=cut + +sub UpdateMarcTimestamp { + my ( $record ) = @_; + + my $encoding = C4::Context->preference("marcflavour"); + + if ( $encoding =~ /MARC21|UNIMARC/ ) { + my @a = (localtime) [5,4,3,2,1,0]; $a[0]+=1900; $a[1]++; + # YY MM DD HH MM SS (update year and month) + my $f005 = $record->field('005'); + $f005->update( sprintf( "%4d%02d%02d%02d%02d%04.1f",@a ) ) if $f005; + } +} + =head2 ModBiblioMarc &ModBiblioMarc($newrec,$biblionumber,$frameworkcode); @@ -3318,12 +3339,7 @@ sub ModBiblioMarc { } #enhancement 5374: update transaction date (005) for marc21/unimarc - if($encoding =~ /MARC21|UNIMARC/) { - my @a= (localtime) [5,4,3,2,1,0]; $a[0]+=1900; $a[1]++; - # YY MM DD HH MM SS (update year and month) - my $f005= $record->field('005'); - $f005->update(sprintf("%4d%02d%02d%02d%02d%04.1f",@a)) if $f005; - } + UpdateMarcTimestamp( $record ); my $metadata = { biblionumber => $biblionumber, --- a/C4/ImportBatch.pm +++ a/C4/ImportBatch.pm @@ -28,6 +28,8 @@ use C4::Charset; use C4::AuthoritiesMarc; use C4::MarcModificationTemplates; use Koha::Items; +use DateTime; +use DateTime::Format::Strptime; use Koha::Plugins::Handler; use Koha::Logger; @@ -1607,10 +1609,12 @@ sub _create_import_record { sub _update_import_record_marc { my ($import_record_id, $marc_record, $marc_type) = @_; + my $upload_timestamp = _get_import_record_timestamp($marc_record); + my $dbh = C4::Context->dbh; - my $sth = $dbh->prepare("UPDATE import_records SET marc = ?, marcxml = ? + my $sth = $dbh->prepare("UPDATE import_records SET marc = ?, marcxml = ?, upload_timestamp = ? WHERE import_record_id = ?"); - $sth->execute($marc_record->as_usmarc(), $marc_record->as_xml($marc_type), $import_record_id); + $sth->execute($marc_record->as_usmarc(), $marc_record->as_xml($marc_type), $upload_timestamp, $import_record_id); $sth->finish(); } @@ -1631,14 +1635,18 @@ sub _add_auth_fields { sub _add_biblio_fields { my ($import_record_id, $marc_record) = @_; + my $controlnumber; + if ($marc_record->field('001')) { + $controlnumber = $marc_record->field('001')->data(); + } my ($title, $author, $isbn, $issn) = _parse_biblio_fields($marc_record); my $dbh = C4::Context->dbh; - # FIXME no controlnumber, originalsource + # FIXME no originalsource $isbn = C4::Koha::GetNormalizedISBN($isbn); - my $sth = $dbh->prepare("INSERT INTO import_biblios (import_record_id, title, author, isbn, issn) VALUES (?, ?, ?, ?, ?)"); - $sth->execute($import_record_id, $title, $author, $isbn, $issn); + my $sth = $dbh->prepare("INSERT INTO import_biblios (import_record_id, title, author, isbn, issn, control_number) VALUES (?, ?, ?, ?, ?, ?)"); + $sth->execute($import_record_id, $title, $author, $isbn, $issn, $controlnumber); $sth->finish(); - + } sub _update_biblio_fields { --- a/cataloguing/editor.pl +++ a/cataloguing/editor.pl @@ -55,7 +55,7 @@ my $schema = Koha::Database->new->schema; $template->{VARS}->{editable_batches} = [ $schema->resultset('ImportBatch')->search( { batch_type => [ 'batch', 'webservice' ], - import_status => 'staged', + import_status => [ 'staged', 'staging' ], }, { result_class => 'DBIx::Class::ResultClass::HashRefInflator' }, ) ]; --- a/koha-tmpl/intranet-tmpl/lib/koha/cateditor/koha-backend.js +++ a/koha-tmpl/intranet-tmpl/lib/koha/cateditor/koha-backend.js @@ -168,6 +168,58 @@ define( [ '/cgi-bin/koha/svc/cataloguing/framework?frameworkcode=&callback=defin } ); }, + GetBatchRecord: function( batch_id, id, callback ) { + $.get( + '/cgi-bin/koha/svc/cataloguing/import_batches/' + batch_id + '/' + id + ).done( function( data ) { + var record = new MARC.Record(); + record.loadMARCXML( data.record ); + callback(record); + } ).fail( function( data ) { + callback( { error: data } ); + } ); + }, + + CreateBatch: function( batch_name, callback ) { + $.ajax( { + type: 'POST', + url: '/cgi-bin/koha/svc/cataloguing/import_batches/', + data: { batch_name: batch_name }, + } ).done( function( data ) { + callback( data ); + } ).fail( function( data ) { + callback( { error: data } ); + } ); + }, + + CreateBatchRecord: function( record, batch_id, callback, options ) { + $.ajax( { + type: 'POST', + url: '/cgi-bin/koha/svc/cataloguing/import_batches/' + batch_id + '/', + data: { record: record.toXML(), allow_control_number_conflict: options.allow_control_number_conflict ? 1 : undefined }, + } ).done( function( data ) { + callback( data ); + } ).fail( function( data ) { + callback( { error: $.parseJSON( data.responseText ) || data.responseText } ); + } ); + }, + + SaveBatchRecord: function( batch_id, id, record, callback, options ) { + $.ajax( { + type: 'POST', + url: '/cgi-bin/koha/svc/cataloguing/import_batches/' + batch_id + '/' + id, + data: { record: record.toXML(), allow_control_number_conflict: options.allow_control_number_conflict ? 1 : undefined }, + } ).done( function( data ) { + callback( data ); + } ).fail( function( data ) { + callback( { data: { error: data } } ); + } ); + }, + + StartBatchExport: function( batch_id, options ) { + window.open( '/cgi-bin/koha/svc/cataloguing/import_batches/' + batch_id + '?download=1&' + $.param( options ) ); + }, + GetTagsBy: function( frameworkcode, field, value ) { var result = {}; --- a/koha-tmpl/intranet-tmpl/lib/koha/cateditor/preferences.js +++ a/koha-tmpl/intranet-tmpl/lib/koha/cateditor/preferences.js @@ -29,10 +29,12 @@ define( function() { Preferences.user = $.extend( { // Preference defaults + enabledBatches: {}, fieldWidgets: true, font: 'monospace', fontSize: '1em', macros: {}, + selected_save_targets: {}, selected_search_targets: {}, }, saved_prefs ); }, --- a/koha-tmpl/intranet-tmpl/prog/css/cateditor.css +++ a/koha-tmpl/intranet-tmpl/prog/css/cateditor.css @@ -65,6 +65,33 @@ body { font-size: 12px; } +#save-targets input { + display: inline-block; + margin: 1px; + vertical-align: middle; +} + +#save-targets input:checked + label { + color: #000; +} + +#save-targets label { + color: #666; + display: inline-block; + margin-left: 0.3em; + padding: 0.3em 0; + vertical-align: middle; + width: 10em; +} + +#save-targets li { + overflow: hidden; +} + +#shortcuts-container { + font-size: 12px; +} + /*> MARC editor */ #editor .CodeMirror { line-height: 1.2; @@ -220,7 +247,8 @@ body { /*> Search */ -#advanced-search-ui .modal-lg, #search-results-ui .modal-lg, #macro-ui .modal-lg { +#advanced-search-ui .modal-lg, #search-results-ui .modal-lg, #macro-ui .modal-lg .ui-modal { + padding: 5px; width: 90%; } @@ -454,6 +482,20 @@ body { position: absolute; } +/* >Batches */ +#batches-list > li { + border: 2px solid #F0F0F0; + border-radius: 6px; + display: block; + line-height: 3em; + font-size: 115%; +} + +#batches-list > li input { + display: inline-block; + margin: 0 1em; +} + /* Small devices (tablets, 768px and up) */ @media (min-width: @screen-sm-min) { #statusbar { @@ -461,4 +503,4 @@ body { border-radius: 6px 6px 0 0; margin-bottom: -32px; } -} +} --- a/koha-tmpl/intranet-tmpl/prog/en/includes/cateditor-ui.inc +++ a/koha-tmpl/intranet-tmpl/prog/en/includes/cateditor-ui.inc @@ -39,6 +39,13 @@ require( [ 'koha-backend', 'search', 'macros', 'marc-editor', 'marc-record', 'pr recordtype: 'biblio', checked: false, }, + [%- FOREACH batch = editable_batches -%] + 'batch:[% batch.import_batch_id %]': { + name: _("Batch: ") + '[% batch.file_name %]', + recordtype: 'biblio', + checked: false, + }, + [%- END -%] [%- FOREACH server = z3950_servers -%] [% server.id | html %]: { name: '[% server.servername | html %]', @@ -64,8 +71,8 @@ require( [ 'koha-backend', 'search', 'macros', 'marc-editor', 'marc-record', 'pr var state = { backend: '', - saveBackend: 'catalog', - recordID: undefined + recordID: undefined, + saveTargets: {}, }; var editor; @@ -235,16 +242,29 @@ require( [ 'koha-backend', 'search', 'macros', 'marc-editor', 'marc-record', 'pr }, }, 'catalog': { - titleForRecord: _("Editing catalog record #{ID}"), + titleForRecord: _("Editing catalog record #%s"), links: [ - { title: _("view"), href: "/cgi-bin/koha/catalogue/detail.pl?biblionumber={ID}" }, - { title: _("edit items"), href: "/cgi-bin/koha/cataloguing/additem.pl?biblionumber={ID}" }, + { title: _("view"), href: "/cgi-bin/koha/catalogue/detail.pl?biblionumber=%s" }, + { title: _("edit items"), href: "/cgi-bin/koha/cataloguing/additem.pl?biblionumber=%s" }, ], - saveLabel: _("Save to catalog"), + saveLabel: _("New catalog record"), + saveExistingLabel: _("Catalog record #%s"), get: function( id, callback ) { if ( !id ) return false; - KohaBackend.GetRecord( id, callback ); + KohaBackend.GetRecord( id, function( data ) { + if ( !data.error ) { + setSaveTargetChecked( 'catalog/', false ); + addSaveTarget( { + label: backends.catalog.saveExistingLabel.format( id ), + id: 'catalog/' + id, + description: '', + checked: true + } ); + } + + callback(data); + } ); }, save: function( id, record, done ) { function finishCb( data ) { @@ -267,7 +287,7 @@ require( [ 'koha-backend', 'search', 'macros', 'marc-editor', 'marc-record', 'pr } }, 'marcxml': { - saveLabel: _("Save as MARCXML (.xml) file"), + saveLabel: _("New MARCXML (.xml) file"), save: function( id, record, done ) { saveAs( new Blob( [record.toXML()], { 'type': 'application/octet-stream;charset=utf-8' } ), 'record.xml' ); @@ -289,6 +309,63 @@ require( [ 'koha-backend', 'search', 'macros', 'marc-editor', 'marc-record', 'pr }, }; + var editable_batches = { + [%- FOREACH batch = editable_batches -%] + [% batch.import_batch_id %]: { + 'name': '[% batch.file_name %]', + }, + [%- END -%] + }; + + function addSaveTarget( target ) { + state.saveTargets[target.id] = target; + if (target.enabled == null) target.enabled = true; + + // Have to check that Preferences has been initialized + var saved_value = Preferences.user && Preferences.user.selected_save_targets[target.id]; + if ( saved_value != null ) target.checked = saved_value; + + var target_list = $.map( state.saveTargets, function( target ) { + return target; + } ); + + target_list.sort( function( a, b ) { + return a.label.localeCompare(b.label); + } ); + + $('#save-targets ol').empty(); + + $.each( target_list, function( i, target ) { + var $new_target = $( + '