Bug 32030: Add/remove resources to/from EBSCO's holdings

Add an "Add to holdings" and "Remove from holdings" buttons on the
resource page.

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:
Jonathan Druart 2022-08-03 14:19:03 +02:00 committed by Tomas Cohen Arazi
parent b9a9b1255f
commit 98ab918470
Signed by: tomascohen
GPG key ID: 0A272EA1B2F3C15F
6 changed files with 214 additions and 6 deletions

View file

@ -4,7 +4,7 @@ use Modern::Perl;
use HTTP::Request;
use LWP::UserAgent;
use JSON qw( from_json decode_json );
use JSON qw( from_json decode_json encode_json );
use List::Util qw( first );
use Koha::Exceptions;
@ -237,14 +237,16 @@ sub build_query {
}
sub request {
my ( $self, $method, $url, $params ) = @_;
my ( $self, $method, $url, $params, $payload ) = @_;
$url = $self->build_query($url, $params) if $params;
warn $url;
my $config = $self->config;
my $base_url = 'https://api.ebsco.io/rm/rmaccounts/' . $config->{custid};
my $request = HTTP::Request->new( $method => $base_url . $url);
my $request = HTTP::Request->new(
$method => $base_url . $url,
undef, ( $payload ? encode_json($payload) : undef )
);
$request->header( 'x-api-key' => $config->{api_key} );
my $ua = LWP::UserAgent->new;
my $response = $ua->simple_request($request);
@ -271,7 +273,10 @@ sub request {
die sprintf "ERROR requesting EBSCO API\n%s\ncode %s: %s\n", $url, $response->code,
$message;
}
} elsif ( $response->code == 204 ) { # No content
return
}
return decode_json( $response->decoded_content );
}

View file

@ -61,4 +61,21 @@ sub get {
}
}
=head3 edit
Controller function that handles editing a single Koha::ERM::EHoldings::Resource object
=cut
sub edit {
my $c = shift->openapi->valid_input or return;
my $provider = $c->validation->param('provider');
if ( $provider eq 'ebsco' ) {
return Koha::REST::V1::ERM::EHoldings::Resources::EBSCO::edit($c);
} else {
die "invalid action";
}
}
1;

View file

@ -173,4 +173,74 @@ sub get {
};
}
=head3 edit
=cut
sub edit {
my $c = shift->openapi->valid_input or return;
return try {
my $body = $c->validation->param('body');
my $is_selected = $body->{is_selected};
my ( $vendor_id, $package_id, $resource_id ) = split '-',
$c->validation->param('resource_id');
my $ebsco = Koha::ERM::Providers::EBSCO->new;
my $t = try {
return $ebsco->request( GET => '/vendors/'
. $vendor_id
. '/packages/'
. $package_id
. '/titles/'
. $resource_id );
}
catch {
if ( blessed $_ ) {
if ( $_->isa('Koha::Exceptions::ObjectNotFound') ) {
return $c->render(
status => 404,
openapi => { error => $_->error }
);
}
}
$c->unhandled_exception($_);
};
unless ($t) {
return $c->render(
status => 404,
openapi => { error => "Resource not found" }
);
}
$ebsco->request(
PUT => '/vendors/'
. $vendor_id
. '/packages/'
. $package_id
. '/titles/'
. $resource_id,
undef,
{
isSelected => $is_selected,
titleName => $t->{titleName},
pubType => $t->{pubType}
}
);
return $c->render(
status => 200,
openapi => { is_selected => $is_selected } # We don't want to refetch the resource to make sure it has been updated
);
}
catch {
$c->unhandled_exception($_);
};
}
1;

View file

@ -129,3 +129,64 @@
x-koha-embed:
- resources
- resources.package
patch:
x-mojo-to: ERM::EHoldings::Resources#edit
operationId: editErmEHoldingsResources
tags:
- eholdings
summary: Edit a resource
produces:
- application/json
parameters:
- description: Provider name
in: path
name: provider
required: true
type: string
- description: A JSON object containing the fields to edit
in: body
name: body
required: true
schema:
type: object
properties:
is_selected:
description: Add or remove this resource from remote holdings
type: boolean
additionalProperties: false
- $ref: "../swagger.yaml#/parameters/eholdings_resource_id_pp"
responses:
200:
description: What has been modified
schema:
type: object
properties:
is_selected:
description: Add or remove this resource from remote holdings
type: boolean
additionalProperties: false
401:
description: Authentication required
schema:
$ref: "../swagger.yaml#/definitions/error"
403:
description: Access forbidden
schema:
$ref: "../swagger.yaml#/definitions/error"
404:
description: Ressource not found
schema:
$ref: "../swagger.yaml#/definitions/error"
500:
description: |-
Internal server error. Possible `error_code` attribute values:
* `internal_server_error`
schema:
$ref: "../swagger.yaml#/definitions/error"
503:
description: Under maintenance
schema:
$ref: "../swagger.yaml#/definitions/error"
x-koha-authorization:
permissions:
erm: 1

View file

@ -3,6 +3,23 @@
<div v-else-if="resource" id="eholdings_resources_show">
<h2>
{{ $t("Resource .id", { id: resource.resource_id }) }}
<span v-if="!updating_is_selected">
<a
v-if="!resource.is_selected"
class="btn btn-default btn-xs"
role="button"
@click="add_to_holdings"
><font-awesome-icon icon="plus" /> Add to holdings</a
>
<a
v-else
class="btn btn-default btn-xs"
role="button"
id="remove-from-holdings"
@click="remove_from_holdings"
><font-awesome-icon icon="minus" /> Remove from holdings</a
> </span
><span v-else><font-awesome-icon icon="spinner" /></span>
</h2>
<div>
<fieldset class="rows">
@ -98,6 +115,8 @@
import { fetchEBSCOResource } from "../../fetch"
import { useVendorStore } from "../../stores/vendors"
import { storeToRefs } from "pinia"
import { checkError } from '../../fetch.js'
export default {
setup() {
const format_date = $date
@ -122,6 +141,7 @@ export default {
package: {},
},
initialized: false,
updating_is_selected: false,
}
},
@ -138,6 +158,35 @@ export default {
const resource = await fetchEBSCOResource(resource_id)
this.resource = resource
this.initialized = true
this.updating_is_selected = false
},
edit_selected(is_selected) {
this.updating_is_selected = true
fetch('/api/v1/erm/eholdings/ebsco/resources/' + this.resource.resource_id, {
method: "PATCH",
body: JSON.stringify({ is_selected }),
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
})
.then(checkError)
.then(
(result) => {
// Refresh the page. We should not need that actually.
this.getResource(this.resource.resource_id)
},
).catch(
(error) => {
setError(error)
}
)
},
add_to_holdings() {
this.edit_selected(true)
},
remove_from_holdings() {
this.edit_selected(false)
},
},
name: "EHoldingsEBSCOResourcesShow",

View file

@ -3,11 +3,17 @@ import { createWebHistory, createRouter } from "vue-router";
import { createPinia } from "pinia";
import { library } from "@fortawesome/fontawesome-svg-core";
import { faPlus, faPencil, faTrash } from "@fortawesome/free-solid-svg-icons";
import {
faPlus,
faMinus,
faPencil,
faTrash,
faSpinner,
} from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
import vSelect from "vue-select";
library.add(faPlus, faPencil, faTrash);
library.add(faPlus, faMinus, faPencil, faTrash, faSpinner);
import App from "./components/ERM/ERMMain.vue";