description: Expected delivery time (in days)
external_id:
type:
- - integer
+ - string
- "null"
description: External id
additionalProperties: false
---
/erm/packages:
get:
- x-mojo-to: ERM::packages#list
- operationId: listErmpackages
+ x-mojo-to: ERM::Packages#list
+ operationId: listErmPackages
tags:
- package
summary: List packages
permissions:
erm: 1
post:
- x-mojo-to: ERM::packages#add
- operationId: addErmpackages
+ x-mojo-to: ERM::Packages#add
+ operationId: addErmPackages
tags:
- package
summary: Add package
erm: 1
"/erm/packages/{package_id}":
get:
- x-mojo-to: ERM::packages#get
- operationId: getErmpackages
+ x-mojo-to: ERM::Packages#get
+ operationId: getErmPackages
tags:
- package
summary: Get package
permissions:
erm: 1
put:
- x-mojo-to: ERM::packages#update
- operationId: updateErmpackages
+ x-mojo-to: ERM::Packages#update
+ operationId: updateErmPackages
tags:
- package
summary: Update package
permissions:
erm: 1
delete:
- x-mojo-to: ERM::packages#delete
- operationId: deleteErmpackages
+ x-mojo-to: ERM::Packages#delete
+ operationId: deleteErmPackages
tags:
- package
summary: Delete package
--- /dev/null
+import { mount } from "@cypress/vue";
+const dayjs = require("dayjs"); /* Cannot use our calendar JS code, it's in an include file (!)
+ Also note that moment.js is deprecated */
+
+function get_package() {
+ return {
+ package_id: 1,
+ name: "package 1",
+ package_type: "complete",
+ content_type: "print",
+ package_agreements: [],
+ };
+}
+
+describe("Package CRUD operations", () => {
+ beforeEach(() => {
+ cy.login("koha", "koha");
+ cy.title().should("eq", "Koha staff interface");
+ });
+
+ it("List package", () => {
+ // GET package returns 500
+ cy.intercept("GET", "/api/v1/erm/packages", {
+ statusCode: 500,
+ error: "Something went wrong",
+ });
+ cy.visit("/cgi-bin/koha/erm/erm.pl");
+ cy.get("#navmenulist").contains("Packages").click();
+ cy.get("main div[class='dialog alert']").contains(
+ /Something went wrong/
+ );
+
+ // GET packages returns empty list
+ cy.intercept("GET", "/api/v1/erm/packages*", []);
+ cy.visit("/cgi-bin/koha/erm/packages");
+ cy.get("#packages_list").contains("There are no packages defined.");
+
+ // GET packages returns something
+ let erm_package = get_package();
+ let packages = [erm_package];
+
+ cy.intercept("GET", "/api/v1/erm/packages*", {
+ statusCode: 200,
+ body: packages,
+ headers: {
+ "X-Base-Total-Count": "1",
+ "X-Total-Count": "1",
+ },
+ });
+ cy.intercept("GET", "/api/v1/erm/packages/*", erm_package);
+ cy.visit("/cgi-bin/koha/erm/packages");
+ cy.get("#packages_list").contains("Showing 1 to 1 of 1 entries");
+ });
+
+ it("Add package", () => {
+ // Click the button in the toolbar
+ cy.visit("/cgi-bin/koha/erm/packages");
+ cy.contains("New package").click();
+ cy.get("#packages_add h2").contains("New package");
+
+ // Fill in the form for normal attributes
+ let erm_package = get_package();
+
+ cy.get("#packages_add").contains("Submit").click();
+ cy.get("input:invalid,textarea:invalid,select:invalid").should(
+ "have.length",
+ 1
+ );
+ cy.get("#package_name").type(erm_package.name);
+ cy.get("#package_type").select(erm_package.package_type);
+ cy.get("#package_content_type").select(erm_package.content_type);
+
+ // Submit the form, get 500
+ cy.intercept("POST", "/api/v1/erm/packages", {
+ statusCode: 500,
+ error: "Something went wrong",
+ });
+ cy.get("#packages_add").contains("Submit").click();
+ cy.get("main div[class='dialog alert']").contains(
+ "Something went wrong: Internal Server Error"
+ );
+
+ // Submit the form, success!
+ cy.intercept("POST", "/api/v1/erm/packages", {
+ statusCode: 201,
+ body: erm_package,
+ });
+ cy.get("#packages_add").contains("Submit").click();
+ cy.get("main div[class='dialog message']").contains(
+ "Package created"
+ );
+ });
+
+ it("Edit package", () => {
+ let erm_package = get_package();
+ let packages = [erm_package];
+ // Click the 'Edit' button from the list
+ cy.intercept("GET", "/api/v1/erm/packages*", {
+ statusCode: 200,
+ body: packages,
+ headers: {
+ "X-Base-Total-Count": "1",
+ "X-Total-Count": "1",
+ },
+ });
+ cy.intercept("GET", "/api/v1/erm/packages/*", erm_package).as(
+ "get-package"
+ );
+ cy.visit("/cgi-bin/koha/erm/packages");
+ cy.get("#packages_list table tbody tr:first")
+ .contains("Edit")
+ .click();
+ cy.wait("@get-package");
+ cy.wait(500); // Cypress is too fast! Vue hasn't populated the form yet!
+ cy.get("#packages_add h2").contains("Edit package");
+
+ // Form has been correctly filled in
+ cy.get("#package_name").should("have.value", erm_package.name);
+ cy.get("#package_type").should("have.value", erm_package.package_type);
+ cy.get("#package_content_type").should("have.value", erm_package.content_type);
+
+ // Submit the form, get 500
+ cy.intercept("PUT", "/api/v1/erm/packages/*", {
+ statusCode: 500,
+ error: "Something went wrong",
+ });
+ cy.get("#packages_add").contains("Submit").click();
+ cy.get("main div[class='dialog alert']").contains(
+ "Something went wrong: Internal Server Error"
+ );
+
+ // Submit the form, success!
+ cy.intercept("PUT", "/api/v1/erm/packages/*", {
+ statusCode: 200,
+ body: erm_package,
+ });
+ cy.get("#packages_add").contains("Submit").click();
+ cy.get("main div[class='dialog message']").contains(
+ "Package updated"
+ );
+ });
+
+ it("Show package", () => {
+ let erm_package = get_package();
+ let packages = [erm_package];
+ // Click the "name" link from the list
+ cy.intercept("GET", "/api/v1/erm/packages*", {
+ statusCode: 200,
+ body: packages,
+ headers: {
+ "X-Base-Total-Count": "1",
+ "X-Total-Count": "1",
+ },
+ });
+ cy.intercept("GET", "/api/v1/erm/packages/*", erm_package).as(
+ "get-package"
+ );
+ cy.visit("/cgi-bin/koha/erm/packages");
+ let name_link = cy.get(
+ "#packages_list table tbody tr:first td:first a"
+ );
+ name_link.should(
+ "have.text",
+ erm_package.name + " (#" + erm_package.package_id + ")"
+ );
+ name_link.click();
+ cy.wait("@get-package");
+ cy.wait(500); // Cypress is too fast! Vue hasn't populated the form yet!
+ cy.get("#packages_show h2").contains(
+ "Package #" + erm_package.package_id
+ );
+ });
+
+ it("Delete package", () => {
+ let erm_package = get_package();
+ let packages = [erm_package];
+
+ // Click the 'Delete' button from the list
+ cy.intercept("GET", "/api/v1/erm/packages*", {
+ statusCode: 200,
+ body: packages,
+ headers: {
+ "X-Base-Total-Count": "1",
+ "X-Total-Count": "1",
+ },
+ });
+ cy.intercept("GET", "/api/v1/erm/packages/*", erm_package);
+ cy.visit("/cgi-bin/koha/erm/packages");
+
+ cy.get("#packages_list table tbody tr:first")
+ .contains("Delete")
+ .click();
+ cy.get("#packages_confirm_delete h2").contains("Delete package");
+ cy.contains("Package name: " + erm_package.name);
+
+ // Submit the form, get 500
+ cy.intercept("DELETE", "/api/v1/erm/packages/*", {
+ statusCode: 500,
+ error: "Something went wrong",
+ });
+ cy.contains("Yes, delete").click();
+ cy.get("main div[class='dialog alert']").contains(
+ "Something went wrong: Internal Server Error"
+ );
+
+ // Submit the form, success!
+ cy.intercept("DELETE", "/api/v1/erm/packages/*", {
+ statusCode: 204,
+ body: null,
+ });
+ cy.contains("Yes, delete").click();
+ cy.get("main div[class='dialog message']").contains(
+ "Package deleted"
+ );
+ });
+});
AFTER `deliverytime`
});
}
+
+ $dbh->do(q{
+ INSERT IGNORE INTO authorised_value_categories (category_name, is_system)
+ VALUES
+ ('ERM_PACKAGE_TYPE', 1),
+ ('ERM_PACKAGE_CONTENT_TYPE', 1)
+ });
+
+ $dbh->do(q{
+ INSERT IGNORE INTO authorised_values (category, authorised_value, lib)
+ VALUES
+ ('ERM_PACKAGE_TYPE', 'local', 'Local'),
+ ('ERM_PACKAGE_TYPE', 'complete', 'Complete'),
+ ('ERM_PACKAGE_CONTENT_TYPE', 'mixed_content', 'Aggregated full'),
+ ('ERM_PACKAGE_CONTENT_TYPE', 'mixed_content', 'Abstract and index'),
+ ('ERM_PACKAGE_CONTENT_TYPE', 'e_book', 'E-book'),
+ ('ERM_PACKAGE_CONTENT_TYPE', 'mixed_content', 'Mixed content'),
+ ('ERM_PACKAGE_CONTENT_TYPE', 'e_journal', 'E-journal'),
+ ('ERM_PACKAGE_CONTENT_TYPE', 'online_reference', 'Online reference'),
+ ('ERM_PACKAGE_CONTENT_TYPE', 'print', 'Print'),
+ ('ERM_PACKAGE_CONTENT_TYPE', 'streaming_media', 'Streaming media'),
+ ('ERM_PACKAGE_CONTENT_TYPE', 'unknown', 'Unknown')
+ });
}
};
('ERM_LICENSE_TYPE', 1),
('ERM_LICENSE_STATUS', 1),
('ERM_AGREEMENT_LICENSE_STATUS', 1),
- ('ERM_AGREEMENT_LICENSE_LOCATION', 1);
+ ('ERM_AGREEMENT_LICENSE_LOCATION', 1),
+ ('ERM_PACKAGE_TYPE', 1),
+ ('ERM_PACKAGE_CONTENT_TYPE', 1);
INSERT IGNORE INTO authorised_values (category, authorised_value, lib)
VALUES
('ERM_AGREEMENT_LICENSE_STATUS', 'future', 'Future'),
('ERM_AGREEMENT_LICENSE_STATUS', 'history', 'Historic'),
('ERM_AGREEMENT_LICENSE_LOCATION', 'filing_cabinet', 'Filing cabinet'),
- ('ERM_AGREEMENT_LICENSE_LOCATION', 'cupboard', 'Cupboard');
+ ('ERM_AGREEMENT_LICENSE_LOCATION', 'cupboard', 'Cupboard'),
+ ('ERM_PACKAGE_TYPE', 'local', 'Local'),
+ ('ERM_PACKAGE_TYPE', 'complete', 'Complete'),
+ ('ERM_PACKAGE_CONTENT_TYPE', 'mixed_content', 'Aggregated full'),
+ ('ERM_PACKAGE_CONTENT_TYPE', 'mixed_content', 'Abstract and index'),
+ ('ERM_PACKAGE_CONTENT_TYPE', 'e_book', 'E-book'),
+ ('ERM_PACKAGE_CONTENT_TYPE', 'mixed_content', 'Mixed content'),
+ ('ERM_PACKAGE_CONTENT_TYPE', 'e_journal', 'E-journal'),
+ ('ERM_PACKAGE_CONTENT_TYPE', 'online_reference', 'Online reference'),
+ ('ERM_PACKAGE_CONTENT_TYPE', 'print', 'Print'),
+ ('ERM_PACKAGE_CONTENT_TYPE', 'streaming_media', 'Streaming media'),
+ ('ERM_PACKAGE_CONTENT_TYPE', 'unknown', 'Unknown');
+
const agreement_renewal_priorities = [% To.json(AuthorisedValues.Get('ERM_AGREEMENT_RENEWAL_PRIORITY')) | $raw %];
const agreement_user_roles = [% To.json(AuthorisedValues.Get('ERM_AGREEMENT_USER_ROLES')) | $raw %];
- var table_settings = [% TablesSettings.GetTableSettings( 'erm', 'agreements', 'agreements', 'json' ) | $raw %];
+ var agreement_table_settings = [% TablesSettings.GetTableSettings( 'erm', 'agreements', 'agreements', 'json' ) | $raw %];
var agreements_table_url = '/api/v1/erm/agreements?';
[% IF agreement_name_filter %]
const license_types = [% To.json(AuthorisedValues.Get('ERM_LICENSE_TYPE')) | $raw %];
const license_statuses = [% To.json(AuthorisedValues.Get('ERM_LICENSE_STATUS')) | $raw %];
- var table_settings = [% TablesSettings.GetTableSettings( 'erm', 'agreements', 'agreements', 'json' ) | $raw %];
+ var license_table_settings = [% TablesSettings.GetTableSettings( 'erm', 'licenses', 'licenses', 'json' ) | $raw %];
var licenses_table_url = '/api/v1/erm/licenses?';
[% IF license_name_filter %]
const agreement_license_statuses = [% To.json(AuthorisedValues.Get('ERM_AGREEMENT_LICENSE_STATUS')) | $raw %];
const agreement_license_location = [% To.json(AuthorisedValues.Get('ERM_AGREEMENT_LICENSE_LOCATION')) | $raw %];
+ const package_types = [% To.json(AuthorisedValues.Get('ERM_PACKAGE_TYPE')) | $raw %];
+ const package_content_types = [% To.json(AuthorisedValues.Get('ERM_PACKAGE_CONTENT_TYPE')) | $raw %];
+
+ var package_table_settings = [% TablesSettings.GetTableSettings( 'erm', 'packages', 'packages', 'json' ) | $raw %];
+
+ var packages_table_url = '/api/v1/erm/packages?';
+ [% IF package_name_filter %]
+ var package_name_filter = {
+ 'name': {
+ "like": '%[%- package_name_filter | html -%]%'
+ }
+ };
+ packages_table_url += 'q='+ encodeURIComponent(JSON.stringify(package_name_filter));
+ [% END %]
+
</script>
[% Asset.js("js/vue/dist/main.js") | $raw %]
},
name: 'AgreementRelationships',
}
-</script>
\ No newline at end of file
+</script>
}
}
},
- props: {
- agreement_id: Number,
- },
components: {
AgreementPeriods,
AgreementUserRoles,
$("#" + table_id).find("thead th").eq(6).attr('data-filter', 'av_agreement_renewal_priorities')
}
- }, table_settings, 1)
+ }, agreement_table_settings, 1)
},
beforeUnmount() {
$('#agreement_list')
</li>
<li>
<router-link
+ to="/cgi-bin/koha/erm/packages"
+ >
+ <i class="fa fa-file-text-o"></i>
+ {{ $t("Packages") }}</router-link
+ >
+ </li>
+ <li>
+ <router-link
to="/cgi-bin/koha/erm/licenses"
>
<i class="fa fa-file-text-o"></i>
AVStore.av_license_statuses = license_statuses
AVStore.av_agreement_license_statuses = agreement_license_statuses
AVStore.av_agreement_license_location = agreement_license_location
+ AVStore.av_package_types = package_types
+ AVStore.av_package_content_types = package_content_types
return {
vendorStore,
}).catch(e => { console.log(e) })
},
},
- props: {
- license_id: Number,
- },
components: {
flatPickr
},
"searchable": true,
"orderable": true,
"render": function (data, type, row, meta) {
- return escape_str(row.started_on)
+ return $date(row.started_on)
}
},
{
"searchable": true,
"orderable": true,
"render": function (data, type, row, meta) {
- return escape_str(row.ended_on)
+ return $date(row.ended_on)
}
},
{
$("#" + table_id).find("thead th").eq(3).attr('data-filter', 'av_license_statuses')
}
- }, table_settings, 1)
+ }, license_table_settings, 1)
},
beforeUnmount() {
$('#license_list')
--- /dev/null
+<template>
+ <div v-if="!this.initialized">{{ $t("Loading") }}</div>
+ <div v-else id="packages_add">
+ <h2 v-if="erm_package.package_id">
+ {{ $t("Edit package.id", { id: erm_package.package_id }) }}
+ </h2>
+ <h2 v-else>{{ $t("New package") }}</h2>
+ <div>
+ <form @submit="onSubmit($event)">
+ <fieldset class="rows">
+ <ol>
+ <li>
+ <label class="required" for="package_name">{{
+ $t("Package name:")
+ }}</label>
+ <input
+ id="package_name"
+ v-model="erm_package.name"
+ :placeholder="$t('Package name')"
+ required
+ />
+ <span class="required">{{ $t("Required") }}</span>
+ </li>
+ <li>
+ <label for="package_vendor_id">{{
+ $t("Vendor:")
+ }}</label>
+ <select
+ id="package_vendor_id"
+ v-model="erm_package.vendor_id"
+ >
+ <option value=""></option>
+ <option
+ v-for="vendor in vendors"
+ :key="vendor.vendor_id"
+ :value="vendor.id"
+ :selected="
+ vendor.id == erm_package.vendor_id
+ ? true
+ : false
+ "
+ >
+ {{ vendor.name }}
+ </option>
+ </select>
+ </li>
+ <li>
+ <label for="package_type">{{ $t("Type: ") }}</label>
+ <select
+ id="package_type"
+ v-model="erm_package.package_type"
+ >
+ <option value=""></option>
+ <option
+ v-for="type in av_package_types"
+ :key="type.authorised_values"
+ :value="type.authorised_value"
+ :selected="
+ type.authorised_value ==
+ erm_package.package_type
+ ? true
+ : false
+ "
+ >
+ {{ type.lib }}
+ </option>
+ </select>
+ </li>
+ <li>
+ <label for="package_content_type">{{
+ $t("Content type: ")
+ }}</label>
+ <select
+ id="package_content_type"
+ v-model="erm_package.content_type"
+ >
+ <option value=""></option>
+ <option
+ v-for="type in av_package_content_types"
+ :key="type.authorised_values"
+ :value="type.authorised_value"
+ :selected="
+ type.authorised_value ==
+ erm_package.content_type
+ ? true
+ : false
+ "
+ >
+ {{ type.lib }}
+ </option>
+ </select>
+ </li>
+
+ <PackageAgreements
+ :package_agreements="erm_package.agreements"
+ />
+ </ol>
+ </fieldset>
+ <fieldset class="action">
+ <input type="submit" value="Submit" />
+ <router-link
+ to="/cgi-bin/koha/erm/packages"
+ role="button"
+ class="cancel"
+ >{{ $t("Cancel") }}</router-link
+ >
+ </fieldset>
+ </form>
+ </div>
+ </div>
+</template>
+
+<script>
+import PackageAgreements from "./PackageAgreements.vue"
+import { useVendorStore } from "../../stores/vendors"
+import { useAVStore } from "../../stores/authorised_values"
+import { setMessage, setError } from "../../messages"
+import { fetchPackage } from '../../fetch'
+import { storeToRefs } from "pinia"
+
+export default {
+ setup() {
+ const vendorStore = useVendorStore()
+ const { vendors } = storeToRefs(vendorStore)
+ const AVStore = useAVStore()
+ const {
+ av_package_types,
+ av_package_content_types,
+ } = storeToRefs(AVStore)
+
+ return {
+ vendors,
+ av_package_types,
+ av_package_content_types,
+ }
+ },
+ data() {
+ return {
+ erm_package: {
+ package_id: null,
+ name: '',
+ external_package_id: null,
+ package_type: '',
+ content_type: '',
+ },
+ initialized: false,
+ }
+ },
+ beforeRouteEnter(to, from, next) {
+ next(vm => {
+ if (to.params.package_id) {
+ vm.erm_package = vm.getPackage(to.params.package_id)
+ } else {
+ vm.initialized = true
+ }
+ })
+ },
+ methods: {
+ async getPackage(package_id) {
+ const erm_package = await fetchPackage(package_id)
+ this.erm_package = erm_package
+ this.initialized = true
+ },
+ onSubmit(e) {
+ e.preventDefault()
+
+ let erm_package = JSON.parse(JSON.stringify(this.erm_package)) // copy
+ let apiUrl = '/api/v1/erm/packages'
+
+ let method = 'POST'
+ if (erm_package.package_id) {
+ method = 'PUT'
+ apiUrl += '/' + erm_package.package_id
+ }
+ delete erm_package.package_id
+
+ const options = {
+ method: method,
+ body: JSON.stringify(erm_package),
+ headers: {
+ 'Content-Type': 'application/json;charset=utf-8'
+ },
+ }
+
+ fetch(apiUrl, options)
+ .then(response => {
+ if (response.status == 200) {
+ this.$router.push("/cgi-bin/koha/erm/packages")
+ setMessage('Package updated')
+ } else if (response.status == 201) {
+ this.$router.push("/cgi-bin/koha/erm/packages")
+ setMessage('Package created')
+ } else {
+ setError(response.message || response.statusText)
+ }
+ }, (error) => {
+ setError(error)
+ }).catch(e => { console.log(e) })
+ },
+ },
+ components: [
+ PackageAgreements,
+ ],
+ name: "PackagesFormAdd",
+}
+</script>
\ No newline at end of file
--- /dev/null
+<template>
+ <div v-if="!this.initialized">{{ $t("Loading") }}</div>
+ <div v-else id="packages_confirm_delete">
+ <h2>{{ $t("Delete package") }}</h2>
+ <div>
+ <form @submit="onSubmit($event)">
+ <fieldset class="rows">
+ <ol>
+ <li>
+ {{ $t("Package name:") }}
+ {{ erm_package.name }}
+ </li>
+ </ol>
+ </fieldset>
+ <fieldset class="action">
+ <input
+ type="submit"
+ variant="primary"
+ :value="$t('Yes, delete')"
+ />
+ <router-link
+ to="/cgi-bin/koha/erm/packages"
+ role="button"
+ class="cancel"
+ >{{ $t("No, do not delete") }}</router-link
+ >
+ </fieldset>
+ </form>
+ </div>
+ </div>
+</template>
+
+<script>
+import { fetchPackage } from "../../fetch"
+import { setMessage, setError } from "../../messages"
+
+export default {
+ data() {
+ return {
+ erm_package: {},
+ initialized: false,
+ }
+ },
+ beforeRouteEnter(to, from, next) {
+ next(vm => {
+ vm.getPackage(to.params.package_id)
+ })
+ },
+ methods: {
+ async getPackage(package_id) {
+ const erm_package = await fetchPackage(package_id)
+ this.erm_package = erm_package
+ this.initialized = true
+ },
+ onSubmit(e) {
+ e.preventDefault()
+
+ let apiUrl = '/api/v1/erm/packages/' + this.erm_package.package_id
+
+ const options = {
+ method: 'DELETE',
+ headers: {
+ 'Content-Type': 'application/json;charset=utf-8'
+ },
+ }
+
+ fetch(apiUrl, options)
+ .then(
+ (response) => {
+ if (response.status == 204) {
+ setMessage("Package deleted")
+ this.$router.push("/cgi-bin/koha/erm/packages")
+ } else {
+ setError(response.message || response.statusText)
+ }
+ }
+ ).catch(
+ (error) => {
+ setError(error)
+ }
+ )
+ }
+ },
+ name: "PackagesFormConfirmDelete",
+}
+</script>
--- /dev/null
+<template>
+ <div v-if="!this.initialized">{{ $t("Loading") }}</div>
+ <div v-else-if="this.packages" id="packages_list">
+ <Toolbar />
+ <table v-if="this.packages.length" id="package_list"></table>
+ <div v-else-if="this.initialized" class="dialog message">
+ {{ $t("There are no packages defined") }}
+ </div>
+ </div>
+</template>
+
+<script>
+import Toolbar from "./PackagesToolbar.vue"
+import { createVNode, render } from 'vue'
+import { useVendorStore } from "../../stores/vendors"
+import { useAVStore } from "../../stores/authorised_values"
+import { storeToRefs } from "pinia"
+import { fetchPackages } from "../../fetch"
+
+export default {
+ setup() {
+ const vendorStore = useVendorStore()
+ const { vendors } = storeToRefs(vendorStore)
+
+ const AVStore = useAVStore()
+ const { av_package_types, av_package_content_types } = storeToRefs(AVStore)
+
+ return {
+ vendors,
+ av_package_types,
+ av_package_content_types,
+ }
+ },
+ data: function () {
+ return {
+ packages: [],
+ initialized: false,
+ }
+ },
+ beforeRouteEnter(to, from, next) {
+ next(vm => {
+ vm.getPackages()
+ })
+ },
+ methods: {
+ async getPackages() {
+ const packages = await fetchPackages()
+ this.packages = packages
+ this.initialized = true
+ },
+ show_package: function (package_id) {
+ this.$router.push("/cgi-bin/koha/erm/packages/" + package_id)
+ },
+ edit_package: function (package_id) {
+ this.$router.push("/cgi-bin/koha/erm/packages/edit/" + package_id)
+ },
+ delete_package: function (package_id) {
+ this.$router.push("/cgi-bin/koha/erm/packages/delete/" + package_id)
+ },
+ },
+ updated() {
+ let show_package = this.show_package
+ let edit_package = this.edit_package
+ let delete_package = this.delete_package
+ 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_package_types'] = this.av_package_types.map(e => {
+ e['_id'] = e['authorised_value']
+ e['_str'] = e['lib']
+ return e
+ })
+ let av_package_types_map = this.av_package_types.reduce((map, e) => {
+ map[e.authorised_value] = e
+ return map
+ }, {})
+ window['av_package_content_types'] = this.av_package_content_types.map(e => {
+ e['_id'] = e['authorised_value']
+ e['_str'] = e['lib']
+ return e
+ })
+ let av_package_content_types_map = this.av_package_content_types.reduce((map, e) => {
+ map[e.authorised_value] = e
+ return map
+ }, {})
+
+ $('#package_list').kohaTable({
+ "ajax": {
+ "url": packages_table_url,
+ },
+ "order": [[1, "asc"]],
+ "columnDefs": [{
+ "targets": [0, 2],
+ "render": function (data, type, row, meta) {
+ if (type == 'display') {
+ return escape_str(data)
+ }
+ return data
+ }
+ }],
+ "columns": [
+ {
+ "title": __("Name"),
+ "data": ["me.package_id", "me.name"],
+ "searchable": true,
+ "orderable": true,
+ // Rendering done in drawCallback
+ },
+ {
+ "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": __("Type"),
+ "data": "package_type",
+ "searchable": true,
+ "orderable": true,
+ "render": function (data, type, row, meta) {
+ return row.package_type != undefined && row.package_type != "" ? escape_str(av_package_types_map[row.package_type].lib) : ""
+ }
+ },
+ {
+ "title": __("Content type"),
+ "data": "package_type",
+ "searchable": true,
+ "orderable": true,
+ "render": function (data, type, row, meta) {
+ return row.content_type != undefined && row.content_type != "" ? escape_str(av_package_content_types_map[row.content_type].lib) : ""
+ }
+ },
+ {
+ "title": __("Created on"),
+ "data": "created_on",
+ "searchable": true,
+ "orderable": true,
+ "render": function (data, type, row, meta) {
+ return $date(row.created_on)
+ }
+ },
+ {
+ "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 package_id = api.row(index).data().package_id
+ let editButton = createVNode("a", {
+ class: "btn btn-default btn-xs", role: "button", onClick: () => {
+ edit_package(package_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_package(package_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_package(row.package_id)
+ }
+ },
+ escape_str(`${row.name} (#${row.package_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(2).attr('data-filter', 'av_package_types')
+ $("#" + table_id).find("thead th").eq(3).attr('data-filter', 'av_package_content_types')
+ }
+
+ }, package_table_settings, 1)
+ },
+ beforeUnmount() {
+ $('#package_list')
+ .DataTable()
+ .destroy(true)
+ },
+ components: { Toolbar },
+ name: "packagesList",
+}
+</script>
--- /dev/null
+<template>
+ <div v-if="!this.initialized">{{ $t("Loading") }}</div>
+ <div v-else id="packages_show">
+ <h2>
+ {{ $t("Package.id", { id: erm_package.package_id }) }}
+ <span class="action_links">
+ <router-link
+ :to="`/cgi-bin/koha/erm/packages/edit/${erm_package.package_id}`"
+ :title="$t('Edit')"
+ ><i class="fa fa-pencil"></i
+ ></router-link>
+
+ <router-link
+ :to="`/cgi-bin/koha/erm/packages/delete/${erm_package.package_id}`"
+ :title="$t('Delete')"
+ ><i class="fa fa-trash"></i
+ ></router-link>
+ </span>
+ </h2>
+ <div>
+ <fieldset class="rows">
+ <ol>
+ <li>
+ <label>{{ $t("Package name:") }}</label>
+ <span>
+ {{ erm_package.name }}
+ </span>
+ </li>
+ <li>
+ <label>{{ $t("Vendor:") }}</label>
+ <span v-if="erm_package.vendor_id">
+ {{
+ vendors.find(
+ (e) => e.id == erm_package.vendor_id
+ ).name
+ }}
+ </span>
+ </li>
+ <li v-if="erm_package.external_package_id">
+ <label>{{ $t("External ID:") }}</label>
+ <span>
+ {{ erm_package.external_package_id }}
+ </span>
+ </li>
+ <li>
+ <label>{{ $t("Package type:") }}</label>
+ <span>{{
+ get_lib_from_av(
+ "av_package_types",
+ erm_package.package_type
+ )
+ }}</span>
+ </li>
+ <li>
+ <label>{{ $t("Content type:") }}</label>
+ <span>{{
+ get_lib_from_av(
+ "av_package_content_types",
+ erm_package.content_type
+ )
+ }}</span>
+ </li>
+ <li>
+ <label>{{ $t("Created on:") }}</label>
+ <span>{{ format_date(erm_package.created_on) }}</span>
+ </li>
+ </ol>
+ </fieldset>
+ <fieldset class="action">
+ <router-link
+ to="/cgi-bin/koha/erm/packages"
+ role="button"
+ class="cancel"
+ >{{ $t("Close") }}</router-link
+ >
+ </fieldset>
+ </div>
+ </div>
+</template>
+
+<script>
+import { useVendorStore } from "../../stores/vendors"
+import { useAVStore } from "../../stores/authorised_values"
+import { fetchPackage } from "../../fetch"
+import { storeToRefs } from "pinia"
+
+export default {
+ setup() {
+ const format_date = $date
+
+ const vendorStore = useVendorStore()
+ const { vendors } = storeToRefs(vendorStore)
+
+ const AVStore = useAVStore()
+ const { get_lib_from_av } = AVStore
+
+ return {
+ format_date,
+ get_lib_from_av,
+ vendors,
+ }
+ },
+ data() {
+ return {
+ erm_package: {
+ package_id: null,
+ vendor_id: null,
+ name: '',
+ external_package_id: '',
+ package_type: '',
+ content_type: '',
+ created_on: null,
+ },
+ initialized: false,
+ }
+ },
+ beforeRouteEnter(to, from, next) {
+ next(vm => {
+ vm.getPackage(to.params.package_id)
+ })
+ },
+ beforeRouteUpdate(to, from) {
+ this.erm_package = this.getPackage(to.params.package_id)
+ },
+ methods: {
+ async getPackage(package_id) {
+ const erm_package = await fetchPackage(package_id)
+ this.erm_package = erm_package
+ this.initialized = true
+ },
+ },
+ name: "PackagesShow",
+}
+</script>
+<style scoped>
+.action_links a {
+ padding-left: 0.2em;
+ font-size: 11px;
+}
+</style>
\ No newline at end of file
--- /dev/null
+<template>
+ <router-link to="/cgi-bin/koha/erm/packages/add" class="btn btn-default"
+ ><font-awesome-icon icon="plus" />
+ {{ $t("New package") }}</router-link
+ >
+</template>
+
+<script>
+export default {
+ name: "PackagesToolbar",
+}
+</script>
);
return vendors;
};
+
+export const fetchPackage = async function (package_id) {
+ if (!package_id) return;
+ const apiUrl = "/api/v1/erm/packages/" + package_id;
+ let erm_package;
+ await fetch(apiUrl)
+ .then((res) => res.json())
+ .then(
+ (result) => {
+ erm_package = result;
+ },
+ (error) => {
+ setError(error);
+ }
+ );
+ return erm_package;
+};
+
+export const fetchPackages = async function () {
+ const apiUrl = "/api/v1/erm/packages";
+ let packages;
+ await fetch(apiUrl)
+ .then((res) => res.json())
+ .then(
+ (result) => {
+ packages = result;
+ },
+ (error) => {
+ setError(error);
+ }
+ );
+ return packages;
+};
import AgreementsShow from "./components/ERM/AgreementsShow.vue";
import AgreementsFormAdd from "./components/ERM/AgreementsFormAdd.vue";
import AgreementsFormConfirmDelete from "./components/ERM/AgreementsFormConfirmDelete.vue";
+import PackagesList from "./components/ERM/PackagesList.vue";
+import PackagesShow from "./components/ERM/PackagesShow.vue";
+import PackagesFormAdd from "./components/ERM/PackagesFormAdd.vue";
+import PackagesFormConfirmDelete from "./components/ERM/PackagesFormConfirmDelete.vue";
import LicensesList from "./components/ERM/LicensesList.vue";
import LicensesShow from "./components/ERM/LicensesShow.vue";
import LicensesFormAdd from "./components/ERM/LicensesFormAdd.vue";
},
agreements: { text: "Agreements", path: "/cgi-bin/koha/erm/agreements" },
licenses: { text: "Licenses", path: "/cgi-bin/koha/erm/licenses" },
+ packages: { text: "Packages", path: "/cgi-bin/koha/erm/packages" },
};
export const routes = [
{ path: "/cgi-bin/koha/mainpage.pl" },
},
},
{
+ path: "/cgi-bin/koha/erm/packages",
+ component: PackagesList,
+ meta: {
+ breadcrumb: [
+ breadcrumbs.home,
+ breadcrumbs.erm_home,
+ breadcrumbs.packages,
+ ],
+ view: "list",
+ },
+ },
+ {
+ path: "/cgi-bin/koha/erm/packages/:package_id",
+ component: PackagesShow,
+ meta: {
+ breadcrumb: [
+ breadcrumbs.home,
+ breadcrumbs.erm_home,
+ breadcrumbs.packages,
+ ],
+ view: "show",
+ },
+ },
+ {
+ path: "/cgi-bin/koha/erm/packages/delete/:package_id",
+ component: PackagesFormConfirmDelete,
+ meta: {
+ breadcrumb: [
+ breadcrumbs.home,
+ breadcrumbs.erm_home,
+ breadcrumbs.packages,
+ ],
+ view: "confirm-delete-form",
+ },
+ },
+ {
+ path: "/cgi-bin/koha/erm/packages/add",
+ component: PackagesFormAdd,
+ meta: {
+ breadcrumb: [
+ breadcrumbs.home,
+ breadcrumbs.erm_home,
+ breadcrumbs.packages,
+ ],
+ view: "add",
+ },
+ },
+ {
+ path: "/cgi-bin/koha/erm/packages/edit/:package_id",
+ component: PackagesFormAdd,
+ meta: {
+ breadcrumb: [
+ breadcrumbs.home,
+ breadcrumbs.erm_home,
+ breadcrumbs.packages,
+ ],
+ view: "edit",
+ },
+ },
+ {
path: "/cgi-bin/koha/erm/licenses",
component: LicensesList,
meta: {
{ authorised_value: "has_frontfile_in", lib: "has_frontfile_in" },
{ authorised_value: "related_to", lib: "related_to" },
],
+ av_package_types: [],
+ av_package_content_types: [],
}),
actions: {
get_lib_from_av(arr_name, av) {
+ if (this[arr_name] === undefined) {
+ console.warn(
+ "The authorised value category for '%s' is not defined.".format(
+ arr_name
+ )
+ );
+ return;
+ }
let o = this[arr_name].find((e) => e.authorised_value == av);
return o ? o.lib : "";
},