Bug 32030: Link external packages with agreements
Signed-off-by: Jonathan Field <jonathan.field@ptfs-europe.com> Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com> Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com> Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>
This commit is contained in:
parent
62c8469e80
commit
111622efcc
|
|
@ -84,6 +84,26 @@ sub vendor {
|
|||
return Koha::Acquisition::Bookseller->_new_from_dbic($rs);
|
||||
}
|
||||
|
||||
=head3 to_api_mapping
|
||||
|
||||
=cut
|
||||
|
||||
sub to_api_mapping {
|
||||
my ( $self ) = @_;
|
||||
|
||||
return {
|
||||
external_id => undef,
|
||||
( # Do we really need this?
|
||||
$self->external_id
|
||||
? (
|
||||
package_id => $self->external_id,
|
||||
koha_internal_id => $self->package_id
|
||||
)
|
||||
: ()
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
=head2 Internal methods
|
||||
|
||||
=head3 _type
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ use List::Util qw( first );
|
|||
|
||||
use Koha::Exceptions;
|
||||
|
||||
use Koha::ERM::EHoldings::Packages;
|
||||
|
||||
sub new {
|
||||
my $class = shift;
|
||||
my $self = {};
|
||||
|
|
@ -80,8 +82,13 @@ sub build_vendor {
|
|||
|
||||
sub build_package {
|
||||
my ( $self, $result ) = @_;
|
||||
my $local_package = $self->get_local_package(
|
||||
$result->{vendorId} . '-' . $result->{packageId} );
|
||||
my $package = {
|
||||
package_id => $result->{vendorId} . '-' . $result->{packageId},
|
||||
( $local_package
|
||||
? ( koha_internal_id => $local_package->package_id )
|
||||
: () ),
|
||||
name => $result->{packageName},
|
||||
content_type => $result->{contentType}, # This does not exist in /vendors/1/packages/2/titles/3
|
||||
created_on => undef,
|
||||
|
|
@ -121,11 +128,18 @@ sub build_additional_params {
|
|||
return $additional_params;
|
||||
}
|
||||
|
||||
sub get_local_package {
|
||||
my ( $self, $package_id ) = @_;
|
||||
return Koha::ERM::EHoldings::Packages->find(
|
||||
{ provider => 'ebsco', external_id => $package_id } );
|
||||
}
|
||||
|
||||
sub embed {
|
||||
my ( $self, $object, $info, $embed_header ) = @_;
|
||||
$embed_header ||= q{};
|
||||
|
||||
my @embed_resources;
|
||||
|
||||
foreach my $embed_req ( split /\s*,\s*/, $embed_header ) {
|
||||
if ( $embed_req eq 'vendor.name' ) {
|
||||
$object->{vendor} = { name => $info->{vendorName}, };
|
||||
|
|
@ -145,6 +159,23 @@ sub embed {
|
|||
elsif ( $embed_req eq 'package.name' ) {
|
||||
$object->{package} = { name => $info->{packageName}, };
|
||||
}
|
||||
elsif ( $embed_req eq 'package_agreements.agreement' ) {
|
||||
# How to deal with 'package_agreements.agreement'?
|
||||
$object->{package_agreements} = [];
|
||||
my $package_id = $info->{vendorId} . '-' . $info->{packageId};
|
||||
my $local_package = $self->get_local_package($package_id);
|
||||
if ( $local_package ) {
|
||||
for my $package_agreement (
|
||||
@{ $local_package->package_agreements->as_list } )
|
||||
{
|
||||
push @{ $object->{package_agreements} },
|
||||
{
|
||||
%{ $package_agreement->unblessed },
|
||||
agreement => $package_agreement->agreement->unblessed,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( $embed_req eq 'resources' || $embed_req eq 'resources.package' ) {
|
||||
push @embed_resources, $embed_req;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,7 +35,8 @@ use Try::Tiny qw( catch try );
|
|||
sub list {
|
||||
my $c = shift->openapi->valid_input or return;
|
||||
return try {
|
||||
my $packages_set = Koha::ERM::EHoldings::Packages->new;
|
||||
my $packages_set =
|
||||
Koha::ERM::EHoldings::Packages->search( { 'me.external_id' => undef } );
|
||||
my $packages = $c->objects->search($packages_set);
|
||||
return $c->render( status => 200, openapi => $packages );
|
||||
}
|
||||
|
|
@ -89,6 +90,7 @@ sub add {
|
|||
my $body = $c->validation->param('body');
|
||||
|
||||
my $package_agreements = delete $body->{package_agreements} // [];
|
||||
delete $body->{external_id} unless $body->{external_id};
|
||||
|
||||
my $package = Koha::ERM::EHoldings::Package->new_from_api($body)->store;
|
||||
$package->package_agreements($package_agreements);
|
||||
|
|
@ -164,9 +166,12 @@ sub update {
|
|||
my $body = $c->validation->param('body');
|
||||
|
||||
my $package_agreements = delete $body->{package_agreements} // [];
|
||||
use Data::Printer colored => 1; warn p $package_agreements;
|
||||
delete $body->{external_id} unless $body->{external_id};
|
||||
|
||||
$package->set_from_api($body)->store;
|
||||
|
||||
# FIXME If there is no package_agreements and external_id is set, we could delete the row
|
||||
# ie. It's coming from EBSCO and we don't have local data linked to it
|
||||
$package->package_agreements($package_agreements);
|
||||
|
||||
$c->res->headers->location($c->req->url->to_string . '/' . $package->package_id);
|
||||
|
|
|
|||
|
|
@ -13,11 +13,21 @@ properties:
|
|||
name:
|
||||
description: name of the package
|
||||
type: string
|
||||
provider:
|
||||
description: external id of the package
|
||||
type:
|
||||
- string
|
||||
- "null"
|
||||
external_id:
|
||||
description: external id of the package
|
||||
type:
|
||||
- string
|
||||
- "null"
|
||||
koha_internal_id:
|
||||
description: internal id of the package
|
||||
type:
|
||||
- integer
|
||||
- "null"
|
||||
package_type:
|
||||
description: type of the package
|
||||
type:
|
||||
|
|
|
|||
|
|
@ -191,6 +191,7 @@ return {
|
|||
`vendor_id` INT(11) DEFAULT NULL COMMENT 'foreign key to aqbooksellers',
|
||||
`name` VARCHAR(255) NOT NULL COMMENT 'name of the package',
|
||||
`external_id` VARCHAR(255) DEFAULT NULL COMMENT 'External key',
|
||||
`provider` ENUM('ebsco') DEFAULT NULL COMMENT 'External provider',
|
||||
`package_type` VARCHAR(80) DEFAULT NULL COMMENT 'type of the package',
|
||||
`content_type` VARCHAR(80) DEFAULT NULL COMMENT 'type of the package',
|
||||
`created_on` timestamp NOT NULL DEFAULT current_timestamp() COMMENT 'date of creation of the package',
|
||||
|
|
|
|||
|
|
@ -2902,6 +2902,7 @@ CREATE TABLE `erm_eholdings_packages` (
|
|||
`vendor_id` INT(11) DEFAULT NULL COMMENT 'foreign key to aqbooksellers',
|
||||
`name` VARCHAR(255) NOT NULL COMMENT 'name of the package',
|
||||
`external_id` VARCHAR(255) DEFAULT NULL COMMENT 'External key',
|
||||
`provider` ENUM('ebsco') DEFAULT NULL COMMENT 'External provider',
|
||||
`package_type` VARCHAR(80) DEFAULT NULL COMMENT 'type of the package',
|
||||
`content_type` VARCHAR(80) DEFAULT NULL COMMENT 'type of the package',
|
||||
`created_on` timestamp NOT NULL DEFAULT current_timestamp() COMMENT 'date of creation of the package',
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<div v-if="!this.initialized">{{ $t("Loading") }}</div>
|
||||
<div v-else-if="this.agreements" id="agreements_list">
|
||||
<Toolbar />
|
||||
<Toolbar v-if="before_route_entered" />
|
||||
<table v-if="this.agreements.length" id="agreement_list"></table>
|
||||
<div v-else-if="this.initialized" class="dialog message">
|
||||
{{ $t("There are no agreements defined") }}
|
||||
|
|
@ -36,11 +36,17 @@ export default {
|
|||
return {
|
||||
agreements: [],
|
||||
initialized: false,
|
||||
before_route_entered: false,
|
||||
building_table: false,
|
||||
}
|
||||
},
|
||||
beforeRouteEnter(to, from, next) {
|
||||
next(vm => {
|
||||
vm.getAgreements()
|
||||
vm.before_route_entered = true // FIXME This is ugly, but we need to distinguish when it's used as main component or child component (from EHoldingsEBSCOPAckagesShow for instance)
|
||||
if (!vm.building_table) {
|
||||
vm.building_table = true
|
||||
vm.getAgreements().then(() => vm.build_datatable())
|
||||
}
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
|
|
@ -58,193 +64,232 @@ export default {
|
|||
delete_agreement: function (agreement_id) {
|
||||
this.$router.push("/cgi-bin/koha/erm/agreements/delete/" + agreement_id)
|
||||
},
|
||||
select_agreement: function (agreement_id) {
|
||||
this.$emit('select-agreement', agreement_id)
|
||||
this.$emit('close')
|
||||
},
|
||||
build_datatable: function () {
|
||||
let show_agreement = this.show_agreement
|
||||
let edit_agreement = this.edit_agreement
|
||||
let delete_agreement = this.delete_agreement
|
||||
let select_agreement = this.select_agreement
|
||||
let default_search = this.$route.query.q
|
||||
let actions = this.before_route_entered ? 'edit_delete' : 'select'
|
||||
|
||||
window['vendors'] = this.vendors.map(e => {
|
||||
e['_id'] = e['id']
|
||||
e['_str'] = e['name']
|
||||
return e
|
||||
})
|
||||
let vendors_map = this.vendors.reduce((map, e) => {
|
||||
map[e.id] = e
|
||||
return map
|
||||
}, {})
|
||||
window['av_agreement_statuses'] = this.av_agreement_statuses.map(e => {
|
||||
e['_id'] = e['authorised_value']
|
||||
e['_str'] = e['lib']
|
||||
return e
|
||||
})
|
||||
let av_agreement_statuses_map = this.av_agreement_statuses.reduce((map, e) => {
|
||||
map[e.authorised_value] = e
|
||||
return map
|
||||
}, {})
|
||||
window['av_agreement_closure_reasons'] = this.av_agreement_closure_reasons.map(e => {
|
||||
e['_id'] = e['authorised_value']
|
||||
e['_str'] = e['lib']
|
||||
return e
|
||||
})
|
||||
let av_agreement_closure_reasons_map = this.av_agreement_closure_reasons.reduce((map, e) => {
|
||||
map[e.authorised_value] = e
|
||||
return map
|
||||
}, {})
|
||||
window['av_agreement_renewal_priorities'] = this.av_agreement_renewal_priorities.map(e => {
|
||||
e['_id'] = e['authorised_value']
|
||||
e['_str'] = e['lib']
|
||||
return e
|
||||
})
|
||||
let av_agreement_renewal_priorities_map = this.av_agreement_renewal_priorities.reduce((map, e) => {
|
||||
map[e.authorised_value] = e
|
||||
return map
|
||||
}, {})
|
||||
window['av_agreement_is_perpetual'] = [{ _id: 0, _str: _('No') }, { _id: 1, _str: _("Yes") }]
|
||||
|
||||
const table = $('#agreement_list').kohaTable({
|
||||
"ajax": {
|
||||
"url": "/api/v1/erm/agreements",
|
||||
},
|
||||
"order": [[0, "asc"]],
|
||||
autoWidth: false,
|
||||
"search": { search: default_search },
|
||||
"columnDefs": [{
|
||||
"targets": [0, 2],
|
||||
"render": function (data, type, row, meta) {
|
||||
if (type == 'display') {
|
||||
return escape_str(data)
|
||||
}
|
||||
return data
|
||||
}
|
||||
}],
|
||||
"columns": [
|
||||
{
|
||||
"title": __("Name"),
|
||||
"data": "me.agreement_id:me.name",
|
||||
"searchable": true,
|
||||
"orderable": true,
|
||||
"render": function (data, type, row, meta) {
|
||||
// Rendering done in drawCallback
|
||||
return ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": __("Vendor"),
|
||||
"data": "vendor_id",
|
||||
"searchable": true,
|
||||
"orderable": true,
|
||||
"render": function (data, type, row, meta) {
|
||||
return row.vendor_id != undefined ? escape_str(vendors_map[row.vendor_id].name) : ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": __("Description"),
|
||||
"data": "description",
|
||||
"searchable": true,
|
||||
"orderable": true
|
||||
},
|
||||
{
|
||||
"title": __("Status"),
|
||||
"data": "status",
|
||||
"searchable": true,
|
||||
"orderable": true,
|
||||
"render": function (data, type, row, meta) {
|
||||
return escape_str(av_agreement_statuses_map[row.status].lib)
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": __("Closure reason"),
|
||||
"data": "closure_reason",
|
||||
"searchable": true,
|
||||
"orderable": true,
|
||||
"render": function (data, type, row, meta) {
|
||||
return row.closure_reason != undefined && row.closure_reason != "" ? escape_str(av_agreement_closure_reasons_map[row.closure_reason].lib) : ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": __("Is perpetual"),
|
||||
"data": "is_perpetual",
|
||||
"searchable": true,
|
||||
"orderable": true,
|
||||
"render": function (data, type, row, meta) {
|
||||
return escape_str(row.is_perpetual ? _("Yes") : _("No"))
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": __("Renewal priority"),
|
||||
"data": "renewal_priority",
|
||||
"searchable": true,
|
||||
"orderable": true,
|
||||
"render": function (data, type, row, meta) {
|
||||
return row.renewal_priority != undefined && row.renewal_priority != "" ? escape_str(av_agreement_renewal_priorities_map[row.renewal_priority].lib) : ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": __("Actions"),
|
||||
"data": function (row, type, val, meta) {
|
||||
return '<div class="actions"></div>'
|
||||
},
|
||||
"className": "actions noExport",
|
||||
"searchable": false,
|
||||
"orderable": false
|
||||
}
|
||||
],
|
||||
drawCallback: function (settings) {
|
||||
|
||||
var api = new $.fn.dataTable.Api(settings)
|
||||
|
||||
if (actions == 'edit_delete') {
|
||||
$.each($(this).find("td .actions"), function (index, e) {
|
||||
let agreement_id = api.row(index).data().agreement_id
|
||||
let editButton = createVNode("a", {
|
||||
class: "btn btn-default btn-xs", role: "button", onClick: () => {
|
||||
edit_agreement(agreement_id)
|
||||
}
|
||||
},
|
||||
[createVNode("i", { class: "fa fa-pencil", 'aria-hidden': "true" }), __("Edit")])
|
||||
|
||||
let deleteButton = createVNode("a", {
|
||||
class: "btn btn-default btn-xs", role: "button", onClick: () => {
|
||||
delete_agreement(agreement_id)
|
||||
}
|
||||
},
|
||||
[createVNode("i", { class: "fa fa-trash", 'aria-hidden': "true" }), __("Delete")])
|
||||
|
||||
let n = createVNode('span', {}, [editButton, " ", deleteButton])
|
||||
render(n, e)
|
||||
})
|
||||
} else {
|
||||
$.each($(this).find("td .actions"), function (index, e) {
|
||||
let agreement_id = api.row(index).data().agreement_id
|
||||
let selectButton = createVNode("a", {
|
||||
class: "btn btn-default btn-xs", role: "button", onClick: () => {
|
||||
select_agreement(agreement_id)
|
||||
}
|
||||
},
|
||||
[createVNode("i", { class: "fa fa-check", 'aria-hidden': "true" }), __("Select")])
|
||||
|
||||
let n = createVNode('span', {}, [selectButton])
|
||||
render(n, e)
|
||||
})
|
||||
}
|
||||
|
||||
$.each($(this).find("tbody tr td:first-child"), function (index, e) {
|
||||
let row = api.row(index).data()
|
||||
if (!row) return // Happen if the table is empty
|
||||
let n = createVNode("a", {
|
||||
role: "button",
|
||||
onClick: () => {
|
||||
show_agreement(row.agreement_id)
|
||||
}
|
||||
},
|
||||
`${row.name} (#${row.agreement_id})`
|
||||
)
|
||||
render(n, e)
|
||||
})
|
||||
},
|
||||
preDrawCallback: function (settings) {
|
||||
var table_id = settings.nTable.id
|
||||
$("#" + table_id).find("thead th").eq(1).attr('data-filter', 'vendors')
|
||||
$("#" + table_id).find("thead th").eq(3).attr('data-filter', 'av_agreement_statuses')
|
||||
$("#" + table_id).find("thead th").eq(4).attr('data-filter', 'av_agreement_closure_reasons')
|
||||
$("#" + table_id).find("thead th").eq(5).attr('data-filter', 'av_agreement_is_perpetual')
|
||||
$("#" + table_id).find("thead th").eq(6).attr('data-filter', 'av_agreement_renewal_priorities')
|
||||
}
|
||||
|
||||
}, agreement_table_settings, 1)
|
||||
},
|
||||
destroy_table: function () {
|
||||
$('#agreement_list')
|
||||
.DataTable()
|
||||
.destroy(true)
|
||||
},
|
||||
},
|
||||
updated() {
|
||||
let show_agreement = this.show_agreement
|
||||
let edit_agreement = this.edit_agreement
|
||||
let delete_agreement = this.delete_agreement
|
||||
let default_search = this.$route.query.q
|
||||
|
||||
window['vendors'] = this.vendors.map(e => {
|
||||
e['_id'] = e['id']
|
||||
e['_str'] = e['name']
|
||||
return e
|
||||
})
|
||||
let vendors_map = this.vendors.reduce((map, e) => {
|
||||
map[e.id] = e
|
||||
return map
|
||||
}, {})
|
||||
window['av_agreement_statuses'] = this.av_agreement_statuses.map(e => {
|
||||
e['_id'] = e['authorised_value']
|
||||
e['_str'] = e['lib']
|
||||
return e
|
||||
})
|
||||
let av_agreement_statuses_map = this.av_agreement_statuses.reduce((map, e) => {
|
||||
map[e.authorised_value] = e
|
||||
return map
|
||||
}, {})
|
||||
window['av_agreement_closure_reasons'] = this.av_agreement_closure_reasons.map(e => {
|
||||
e['_id'] = e['authorised_value']
|
||||
e['_str'] = e['lib']
|
||||
return e
|
||||
})
|
||||
let av_agreement_closure_reasons_map = this.av_agreement_closure_reasons.reduce((map, e) => {
|
||||
map[e.authorised_value] = e
|
||||
return map
|
||||
}, {})
|
||||
window['av_agreement_renewal_priorities'] = this.av_agreement_renewal_priorities.map(e => {
|
||||
e['_id'] = e['authorised_value']
|
||||
e['_str'] = e['lib']
|
||||
return e
|
||||
})
|
||||
let av_agreement_renewal_priorities_map = this.av_agreement_renewal_priorities.reduce((map, e) => {
|
||||
map[e.authorised_value] = e
|
||||
return map
|
||||
}, {})
|
||||
window['av_agreement_is_perpetual'] = [{ _id: 0, _str: _('No') }, { _id: 1, _str: _("Yes") }]
|
||||
|
||||
const table = $('#agreement_list').kohaTable({
|
||||
"ajax": {
|
||||
"url": "/api/v1/erm/agreements",
|
||||
},
|
||||
"order": [[0, "asc"]],
|
||||
"search": { search: default_search },
|
||||
"columnDefs": [{
|
||||
"targets": [0, 2],
|
||||
"render": function (data, type, row, meta) {
|
||||
if (type == 'display') {
|
||||
return escape_str(data)
|
||||
}
|
||||
return data
|
||||
}
|
||||
}],
|
||||
"columns": [
|
||||
{
|
||||
"title": __("Name"),
|
||||
"data": "me.agreement_id:me.name",
|
||||
"searchable": true,
|
||||
"orderable": true,
|
||||
"render": function (data, type, row, meta) {
|
||||
// Rendering done in drawCallback
|
||||
return ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": __("Vendor"),
|
||||
"data": "vendor_id",
|
||||
"searchable": true,
|
||||
"orderable": true,
|
||||
"render": function (data, type, row, meta) {
|
||||
return row.vendor_id != undefined ? escape_str(vendors_map[row.vendor_id].name) : ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": __("Description"),
|
||||
"data": "description",
|
||||
"searchable": true,
|
||||
"orderable": true
|
||||
},
|
||||
{
|
||||
"title": __("Status"),
|
||||
"data": "status",
|
||||
"searchable": true,
|
||||
"orderable": true,
|
||||
"render": function (data, type, row, meta) {
|
||||
return escape_str(av_agreement_statuses_map[row.status].lib)
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": __("Closure reason"),
|
||||
"data": "closure_reason",
|
||||
"searchable": true,
|
||||
"orderable": true,
|
||||
"render": function (data, type, row, meta) {
|
||||
return row.closure_reason != undefined && row.closure_reason != "" ? escape_str(av_agreement_closure_reasons_map[row.closure_reason].lib) : ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": __("Is perpetual"),
|
||||
"data": "is_perpetual",
|
||||
"searchable": true,
|
||||
"orderable": true,
|
||||
"render": function (data, type, row, meta) {
|
||||
return escape_str(row.is_perpetual ? _("Yes") : _("No"))
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": __("Renewal priority"),
|
||||
"data": "renewal_priority",
|
||||
"searchable": true,
|
||||
"orderable": true,
|
||||
"render": function (data, type, row, meta) {
|
||||
return row.renewal_priority != undefined && row.renewal_priority != "" ? escape_str(av_agreement_renewal_priorities_map[row.renewal_priority].lib) : ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": __("Actions"),
|
||||
"data": function (row, type, val, meta) {
|
||||
return '<div class="actions"></div>'
|
||||
},
|
||||
"className": "actions noExport",
|
||||
"searchable": false,
|
||||
"orderable": false
|
||||
}
|
||||
],
|
||||
drawCallback: function (settings) {
|
||||
|
||||
var api = new $.fn.dataTable.Api(settings)
|
||||
|
||||
$.each($(this).find("td .actions"), function (index, e) {
|
||||
let agreement_id = api.row(index).data().agreement_id
|
||||
let editButton = createVNode("a", {
|
||||
class: "btn btn-default btn-xs", role: "button", onClick: () => {
|
||||
edit_agreement(agreement_id)
|
||||
}
|
||||
},
|
||||
[createVNode("i", { class: "fa fa-pencil", 'aria-hidden': "true" }), __("Edit")])
|
||||
|
||||
let deleteButton = createVNode("a", {
|
||||
class: "btn btn-default btn-xs", role: "button", onClick: () => {
|
||||
delete_agreement(agreement_id)
|
||||
}
|
||||
},
|
||||
[createVNode("i", { class: "fa fa-trash", 'aria-hidden': "true" }), __("Delete")])
|
||||
|
||||
let n = createVNode('span', {}, [editButton, " ", deleteButton])
|
||||
render(n, e)
|
||||
})
|
||||
|
||||
$.each($(this).find("tbody tr td:first-child"), function (index, e) {
|
||||
let row = api.row(index).data()
|
||||
if (!row) return // Happen if the table is empty
|
||||
let n = createVNode("a", {
|
||||
role: "button",
|
||||
onClick: () => {
|
||||
show_agreement(row.agreement_id)
|
||||
}
|
||||
},
|
||||
`${row.name} (#${row.agreement_id})`
|
||||
)
|
||||
render(n, e)
|
||||
})
|
||||
},
|
||||
preDrawCallback: function (settings) {
|
||||
var table_id = settings.nTable.id
|
||||
$("#" + table_id).find("thead th").eq(1).attr('data-filter', 'vendors')
|
||||
$("#" + table_id).find("thead th").eq(3).attr('data-filter', 'av_agreement_statuses')
|
||||
$("#" + table_id).find("thead th").eq(4).attr('data-filter', 'av_agreement_closure_reasons')
|
||||
$("#" + table_id).find("thead th").eq(5).attr('data-filter', 'av_agreement_is_perpetual')
|
||||
$("#" + table_id).find("thead th").eq(6).attr('data-filter', 'av_agreement_renewal_priorities')
|
||||
}
|
||||
|
||||
}, agreement_table_settings, 1)
|
||||
mounted() {
|
||||
if (!this.building_table) {
|
||||
this.building_table = true
|
||||
this.getAgreements().then(() => this.build_datatable())
|
||||
}
|
||||
},
|
||||
beforeUnmount() {
|
||||
$('#agreement_list')
|
||||
.DataTable()
|
||||
.destroy(true)
|
||||
// This delays the closing of the modal, do we really need it?
|
||||
//this.destroy_table()
|
||||
},
|
||||
components: { Toolbar },
|
||||
name: "AgreementsList",
|
||||
emits: ["select-agreement", "close"],
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
#agreement_list {
|
||||
display: table;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,84 +1,121 @@
|
|||
<template>
|
||||
<fieldset class="rows" id="package_agreements">
|
||||
<legend>{{ $t("Agreements") }}</legend>
|
||||
<fieldset
|
||||
class="rows"
|
||||
v-for="(package_agreement, counter) in package_agreements"
|
||||
<transition name="modal">
|
||||
<div v-if="showModal" class="modal">
|
||||
<AgreementsList @select-agreement="addAgreement" />
|
||||
<input
|
||||
type="button"
|
||||
@click="showModal = false"
|
||||
:value="$t('Close')"
|
||||
/>
|
||||
</div>
|
||||
</transition>
|
||||
<div id="package_agreements">
|
||||
<div
|
||||
v-for="(
|
||||
package_agreement, counter
|
||||
) in erm_package.package_agreements"
|
||||
v-bind:key="counter"
|
||||
>
|
||||
<legend>
|
||||
{{ $t("Agreement .counter", { counter: counter + 1 }) }}
|
||||
<a href="#" @click.prevent="deleteAgreement(counter)"
|
||||
><i class="fa fa-trash"></i>
|
||||
{{ $t("Remove this agreement") }}</a
|
||||
>
|
||||
</legend>
|
||||
<ol>
|
||||
<li>
|
||||
<label :for="`agreement_id_${counter}`"
|
||||
>{{ $t("Agreement") }}:
|
||||
</label>
|
||||
<select
|
||||
v-model="package_agreement.agreement_id"
|
||||
:id="`agreement_id_${counter}`"
|
||||
required
|
||||
>
|
||||
<option value=""></option>
|
||||
<option
|
||||
v-for="agreement in agreements"
|
||||
:key="agreement.agreement_id"
|
||||
:value="agreement.agreement_id"
|
||||
:selected="
|
||||
agreement.agreement_id ==
|
||||
package_agreement.agreement_id
|
||||
? true
|
||||
: false
|
||||
"
|
||||
>
|
||||
{{ agreement.name }}
|
||||
</option>
|
||||
</select>
|
||||
<span class="required">{{ $t("Required") }}</span>
|
||||
</li>
|
||||
</ol>
|
||||
</fieldset>
|
||||
<a
|
||||
v-if="agreements.length"
|
||||
class="btn btn-default"
|
||||
@click="addAgreement"
|
||||
<router-link
|
||||
:to="`/cgi-bin/koha/erm/agreements/${package_agreement.agreement.agreement_id}`"
|
||||
>{{ package_agreement.agreement.name }}</router-link
|
||||
>
|
||||
|
||||
<a
|
||||
href="#"
|
||||
@click.prevent="deleteAgreement(counter)"
|
||||
:title="$t('Remove this agreement')"
|
||||
><i class="fa fa-trash"></i
|
||||
></a>
|
||||
</div>
|
||||
<a class="btn btn-default btn-xs" @click="showModal = true"
|
||||
><font-awesome-icon icon="plus" /> {{ $t("Add new agreement") }}</a
|
||||
>
|
||||
<span v-else>{{ $t("There are no agreements created yet") }}</span>
|
||||
</fieldset>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { fetchAgreements } from "../../fetch"
|
||||
import AgreementsList from "./AgreementsList.vue"
|
||||
import { createPackage, editPackage } from "../../fetch"
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
agreements: [],
|
||||
}
|
||||
return { showModal: false, }
|
||||
},
|
||||
beforeCreate() {
|
||||
fetchAgreements().then((agreements) => {
|
||||
this.agreements = agreements
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
addAgreement() {
|
||||
this.package_agreements.push({
|
||||
agreement_id: null,
|
||||
})
|
||||
serializeAgreement() {
|
||||
let erm_package = JSON.parse(JSON.stringify(this.erm_package)) // copy
|
||||
delete erm_package.vendor_id // This is the EBSCO's vendor_id
|
||||
|
||||
// Remove remote data, we don't need to store them (don't we?)
|
||||
// Keep the name, it's mandatory by the REST API specs
|
||||
delete erm_package.package_type
|
||||
delete erm_package.content_type
|
||||
erm_package.external_id = erm_package.package_id
|
||||
delete erm_package.package_id
|
||||
erm_package.provider = 'ebsco'
|
||||
erm_package.package_id = erm_package.koha_internal_id
|
||||
delete erm_package.koha_internal_id
|
||||
return erm_package
|
||||
},
|
||||
addAgreement(agreement_id) {
|
||||
this.showModal = false
|
||||
let erm_package = this.serializeAgreement()
|
||||
// Only add if it does not exist
|
||||
// TODO Add a warning?
|
||||
if (!erm_package.package_agreements.find((a) => a.agreement_id == agreement_id)) {
|
||||
erm_package.package_agreements.push({ agreement_id })
|
||||
if (this.erm_package.koha_internal_id) {
|
||||
editPackage(erm_package).then(() => {
|
||||
this.$emit('refresh-agreements')
|
||||
})
|
||||
} else {
|
||||
createPackage(erm_package).then(() => {
|
||||
this.$emit('refresh-agreements')
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
deleteAgreement(counter) {
|
||||
this.package_agreements.splice(counter, 1)
|
||||
let erm_package = this.serializeAgreement()
|
||||
erm_package.package_agreements.splice(counter, 1)
|
||||
editPackage(erm_package).then(() => {
|
||||
this.$emit('refresh-agreements')
|
||||
})
|
||||
},
|
||||
},
|
||||
props: {
|
||||
package_agreements: Array,
|
||||
erm_package: Object,
|
||||
},
|
||||
components: {
|
||||
AgreementsList,
|
||||
},
|
||||
emits: ['refresh-agreements'],
|
||||
name: 'EHoldingsEBSCOPackageAgreements',
|
||||
}
|
||||
</script>
|
||||
<style scoped>
|
||||
#package_agreements {
|
||||
padding-left: 26rem;
|
||||
}
|
||||
.modal {
|
||||
position: fixed;
|
||||
z-index: 9998;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 80%;
|
||||
height: 80%;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
display: table;
|
||||
transition: opacity 0.3s ease;
|
||||
margin: auto;
|
||||
padding: 20px 30px;
|
||||
background-color: #fff;
|
||||
border-radius: 2px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.33);
|
||||
transition: all 0.3s ease;
|
||||
font-family: Helvetica, Arial, sans-serif;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -51,6 +51,14 @@
|
|||
<span>{{ format_date(erm_package.created_on) }}</span>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<label>Agreements</label>
|
||||
<EHoldingsPackageAgreements
|
||||
:erm_package="erm_package"
|
||||
@refresh-agreements="refreshAgreements"
|
||||
/>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<label
|
||||
>Titles ({{ erm_package.resources_count }})</label
|
||||
|
|
@ -78,6 +86,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import EHoldingsPackageAgreements from "./EHoldingsEBSCOPackageAgreements.vue"
|
||||
import EHoldingsPackageTitlesList from "./EHoldingsEBSCOPackageTitlesList.vue"
|
||||
import { useAVStore } from "../../stores/authorised_values"
|
||||
import { fetchEBSCOPackage } from "../../fetch"
|
||||
|
|
@ -101,10 +110,12 @@ export default {
|
|||
vendor_id: null,
|
||||
name: '',
|
||||
external_id: '',
|
||||
provider: '',
|
||||
package_type: '',
|
||||
content_type: '',
|
||||
created_on: null,
|
||||
resources: null,
|
||||
package_agreements: [],
|
||||
},
|
||||
initialized: false,
|
||||
}
|
||||
|
|
@ -123,8 +134,14 @@ export default {
|
|||
this.erm_package = erm_package
|
||||
this.initialized = true
|
||||
},
|
||||
refreshAgreements() {
|
||||
// FIXME We could GET /erm/eholdings/packages/$package_id/agreements instead
|
||||
this.initialized = false
|
||||
this.getPackage(this.erm_package.package_id)
|
||||
},
|
||||
},
|
||||
components: {
|
||||
EHoldingsPackageAgreements,
|
||||
EHoldingsPackageTitlesList,
|
||||
},
|
||||
name: "EHoldingsEBSCOPackagesShow",
|
||||
|
|
@ -134,4 +151,4 @@ export default {
|
|||
fieldset.rows label {
|
||||
width: 25rem;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
|
@ -115,7 +115,7 @@ import EHoldingsPackageAgreements from "./EHoldingsLocalPackageAgreements.vue"
|
|||
import { useVendorStore } from "../../stores/vendors"
|
||||
import { useAVStore } from "../../stores/authorised_values"
|
||||
import { setMessage, setError } from "../../messages"
|
||||
import { fetchLocalPackage } from '../../fetch'
|
||||
import { fetchLocalPackage, createPackage, editPackage } from '../../fetch'
|
||||
import { storeToRefs } from "pinia"
|
||||
|
||||
export default {
|
||||
|
|
@ -138,10 +138,13 @@ export default {
|
|||
return {
|
||||
erm_package: {
|
||||
package_id: null,
|
||||
vendor_id: null,
|
||||
name: '',
|
||||
external_id: '',
|
||||
package_type: '',
|
||||
content_type: '',
|
||||
created_on: null,
|
||||
resources: null,
|
||||
package_agreements: [],
|
||||
},
|
||||
initialized: false,
|
||||
|
|
@ -166,42 +169,26 @@ export default {
|
|||
e.preventDefault()
|
||||
|
||||
let erm_package = JSON.parse(JSON.stringify(this.erm_package)) // copy
|
||||
let apiUrl = '/api/v1/erm/eholdings/local/packages'
|
||||
|
||||
let method = 'POST'
|
||||
if (erm_package.package_id) {
|
||||
method = 'PUT'
|
||||
apiUrl += '/' + erm_package.package_id
|
||||
}
|
||||
delete erm_package.package_id
|
||||
delete erm_package.resources
|
||||
delete erm_package.vendor
|
||||
delete erm_package.resources_count
|
||||
|
||||
erm_package.package_agreements = erm_package.package_agreements.map(({ package_id, agreement, ...keepAttrs }) => keepAttrs)
|
||||
|
||||
const options = {
|
||||
method: method,
|
||||
body: JSON.stringify(erm_package),
|
||||
headers: {
|
||||
'Content-Type': 'application/json;charset=utf-8'
|
||||
},
|
||||
}
|
||||
|
||||
fetch(apiUrl, options)
|
||||
.then(response => {
|
||||
editPackage(erm_package).then(response => {
|
||||
if (response.status == 200) {
|
||||
this.$router.push("/cgi-bin/koha/erm/eholdings/local/packages")
|
||||
setMessage(this.$t("Package updated"))
|
||||
} else if (response.status == 201) {
|
||||
} else {
|
||||
setError(response.message || response.statusText)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
createPackage(erm_package).then(response => {
|
||||
if (response.status == 201) {
|
||||
this.$router.push("/cgi-bin/koha/erm/eholdings/local/packages")
|
||||
setMessage(this.$t("Package created"))
|
||||
} else {
|
||||
setError(response.message || response.statusText)
|
||||
}
|
||||
}, (error) => {
|
||||
setError(error)
|
||||
}).catch(e => { console.log(e) })
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
components: {
|
||||
|
|
|
|||
|
|
@ -35,17 +35,6 @@
|
|||
>
|
||||
</span>
|
||||
</li>
|
||||
<li v-if="erm_package.external_id">
|
||||
<label>{{ $t("External ID") }}:</label>
|
||||
<span>
|
||||
<!-- FIXME Create a syspref to store the URL -->
|
||||
<a
|
||||
:href="`https://ptfs-europe-demo.folio.ebsco.com/eholdings/packages/${erm_package.vendor.external_id}-${erm_package.external_id}`"
|
||||
>
|
||||
{{ erm_package.external_id }}
|
||||
</a>
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<label>{{ $t("Package type") }}:</label>
|
||||
<span>{{
|
||||
|
|
|
|||
|
|
@ -1,107 +0,0 @@
|
|||
<template>
|
||||
<div class="modal-mask">
|
||||
<div class="modal-wrapper">
|
||||
<div class="modal-container">
|
||||
|
||||
<div class="modal-header">
|
||||
<slot name="header">
|
||||
default header
|
||||
</slot>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<slot name="body">
|
||||
<AgreementsList />
|
||||
</slot>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<slot name="footer">
|
||||
default footer
|
||||
<button class="modal-default-button" @click="$emit('close')">
|
||||
OK
|
||||
</button>
|
||||
</slot>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import AgreementsList from "./AgreementsList.vue"
|
||||
export default {
|
||||
|
||||
setup() {
|
||||
|
||||
},
|
||||
components:{
|
||||
AgreementsList
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
export default
|
||||
|
||||
<style scoped>
|
||||
.modal-mask {
|
||||
position: fixed;
|
||||
z-index: 9998;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
display: table;
|
||||
transition: opacity 0.3s ease;
|
||||
}
|
||||
|
||||
.modal-wrapper {
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.modal-container {
|
||||
width: 300px;
|
||||
margin: 0px auto;
|
||||
padding: 20px 30px;
|
||||
background-color: #fff;
|
||||
border-radius: 2px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.33);
|
||||
transition: all 0.3s ease;
|
||||
font-family: Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
.modal-header h3 {
|
||||
margin-top: 0;
|
||||
color: #42b983;
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.modal-default-button {
|
||||
float: right;
|
||||
}
|
||||
|
||||
/*
|
||||
* The following styles are auto-applied to elements with
|
||||
* transition="modal" when their visibility is toggled
|
||||
* by Vue.js.
|
||||
*
|
||||
* You can easily play with the modal transition by editing
|
||||
* these styles.
|
||||
*/
|
||||
|
||||
.modal-enter-from, .modal-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.modal-enter-active .modal-container,
|
||||
.modal-leave-active .modal-container {
|
||||
-webkit-transform: scale(1.1);
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
@ -104,6 +104,53 @@ export const fetchVendors = async function () {
|
|||
return vendors;
|
||||
};
|
||||
|
||||
const _createEditPackage = async function (method, erm_package) {
|
||||
let apiUrl = "/api/v1/erm/eholdings/local/packages";
|
||||
|
||||
if (method == "PUT") {
|
||||
apiUrl += "/" + erm_package.package_id;
|
||||
}
|
||||
delete erm_package.package_id;
|
||||
delete erm_package.resources;
|
||||
delete erm_package.vendor;
|
||||
delete erm_package.resources_count;
|
||||
delete erm_package.is_selected;
|
||||
|
||||
erm_package.package_agreements = erm_package.package_agreements.map(
|
||||
({ package_id, agreement, ...keepAttrs }) => keepAttrs
|
||||
);
|
||||
|
||||
const options = {
|
||||
method: method,
|
||||
body: JSON.stringify(erm_package),
|
||||
headers: {
|
||||
"Content-Type": "application/json;charset=utf-8",
|
||||
},
|
||||
};
|
||||
|
||||
let r;
|
||||
await fetch(apiUrl, options)
|
||||
.then(
|
||||
(response) => {
|
||||
r = response;
|
||||
},
|
||||
(error) => {
|
||||
setError(error);
|
||||
}
|
||||
)
|
||||
.catch((e) => {
|
||||
console.log(e);
|
||||
});
|
||||
return r;
|
||||
};
|
||||
|
||||
export const createPackage = function (erm_package) {
|
||||
return _createEditPackage("POST", erm_package);
|
||||
};
|
||||
export const editPackage = function (erm_package) {
|
||||
return _createEditPackage("PUT", erm_package);
|
||||
};
|
||||
|
||||
const _fetchPackage = async function (apiUrl, package_id) {
|
||||
if (!package_id) return;
|
||||
let erm_package;
|
||||
|
|
|
|||
|
|
@ -175,7 +175,7 @@ export const routes = [
|
|||
breadcrumb: () =>
|
||||
build_breadcrumb(
|
||||
breadcrumb_paths.agreements,
|
||||
"Edit agreement" // $t("Edit agreemetn")
|
||||
"Edit agreement" // $t("Edit agreement")
|
||||
),
|
||||
},
|
||||
},
|
||||
|
|
|
|||
Loading…
Reference in New Issue