Bug 32030: Use fetch.js, improve messages handling, remove top level modules

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-05-11 15:24:20 +02:00 committed by Tomas Cohen Arazi
parent 0cdaba2dad
commit 08ce593bd9
Signed by: tomascohen
GPG key ID: 0A272EA1B2F3C15F
18 changed files with 177 additions and 183 deletions

View file

@ -102,6 +102,7 @@
</template>
<script>
import { fetchLicenses } from '../../fetch'
export default {
name: 'AgreementLicenses',
data() {
@ -114,20 +115,8 @@ export default {
av_agreement_license_location: Array,
agreement_licenses: Array,
},
beforeCreate() {
// FIXME it's not called on setup, but setup() does not have 'this'.
const apiUrl = "/api/v1/erm/licenses"
fetch(apiUrl)
.then((res) => res.json())
.then(
(result) => {
this.licenses = result
},
(error) => {
this.$emit("set-error", error)
}
)
beforeCreate(){
fetchLicenses().then((licenses) => this.licenses = licenses )
},
methods: {
addLicense() {

View file

@ -76,9 +76,7 @@ export default {
props: {
periods: Array
},
beforeUpdate() {
if (!this.periods) return
beforeCreate() {
if (!this.dates_fixed) {
this.periods.forEach(p => {
p.started_on = $date(p.started_on)

View file

@ -58,21 +58,15 @@
</template>
<script>
import { useMainStore } from "../../stores/main"
import { fetchPatron } from "../../fetch"
export default {
setup() {
const mainStore = useMainStore()
const { setError } = mainStore
return { setError }
},
name: 'AgreementUserRoles',
props: {
av_agreement_user_roles: Array,
user_roles: Array,
},
beforeUpdate() {
if (!this.user_roles) return
beforeCreate() {
this.user_roles.forEach(u => {
u.patron_str = $patron_to_html(u.patron)
})
@ -102,19 +96,15 @@ export default {
newUserSelected(e) {
let c = e.currentTarget.counter
let selected_patron_id = document.getElementById("selected_patron_id").value
fetch('/api/v1/patrons/' + selected_patron_id)
.then(res => res.json())
.then(
(result) => {
this.user_roles[c].patron = result
this.user_roles[c].patron_str = $patron_to_html(result)
this.user_roles[c].user_id = result.patron_id
}).catch(
(error) => {
this.setError(error)
}
)
}
let patron
// FIXME We are missing a "loading..."
fetchPatron(selected_patron_id).then((p) => {
patron = p
this.user_roles[c].patron = patron
this.user_roles[c].patron_str = $patron_to_html(patron)
this.user_roles[c].user_id = patron.patron_id
})
},
},
}
</script>

View file

@ -201,7 +201,7 @@ import AgreementUserRoles from './AgreementUserRoles.vue'
import AgreementLicenses from './AgreementLicenses.vue'
import { useVendorStore } from "../../stores/vendors"
import { useAVStore } from "../../stores/authorised_values"
import { useMainStore } from "../../stores/main"
import { setMessage, setError } from "../../messages"
import { fetchAgreement } from '../../fetch'
import { storeToRefs } from "pinia"
@ -219,9 +219,6 @@ export default {
av_agreement_license_location,
} = storeToRefs(AVStore)
const mainStore = useMainStore()
const { setMessage, setError, resetMessages } = mainStore
return {
vendors,
av_agreement_statuses,
@ -230,7 +227,6 @@ export default {
av_agreement_user_roles,
av_agreement_license_statuses,
av_agreement_license_location,
setMessage, setError, resetMessages,
}
},
data() {
@ -306,12 +302,12 @@ export default {
.then(response => {
if (response.status == 200) {
this.$router.push("/cgi-bin/koha/erm/agreements")
this.setMessage('Agreement updated')
setMessage('Agreement updated')
} else if (response.status == 201) {
this.$router.push("/cgi-bin/koha/erm/agreements")
this.setMessage('Agreement created')
setMessage('Agreement created')
} else {
this.setError(response.message || response.statusText)
setError(response.message || response.statusText)
}
}).catch(
(error) => {

View file

@ -36,17 +36,10 @@
</template>
<script>
import { useMainStore } from "../../stores/main"
import { fetchAgreement } from "../../fetch"
import { setMessage, setError } from "../../messages"
export default {
setup() {
const mainStore = useMainStore()
const { setMessage, setError } = mainStore
return {
setMessage, setError,
}
},
data() {
return {
agreement: {},
@ -55,7 +48,7 @@ export default {
},
beforeRouteEnter(to, from, next) {
next(vm => {
vm.agreement = vm.getAgreement(to.params.agreement_id)
vm.getAgreement(to.params.agreement_id)
})
},
methods: {
@ -67,7 +60,7 @@ export default {
onSubmit(e) {
e.preventDefault()
let apiUrl = '/api/v1/erm/agreements/' + this.agreement_id
let apiUrl = '/api/v1/erm/agreements/' + this.agreement.agreement_id
const options = {
method: 'DELETE',
@ -80,22 +73,19 @@ export default {
.then(
(response) => {
if (response.status == 204) {
this.setMessage("Agreement deleted")
setMessage("Agreement deleted")
this.$router.push("/cgi-bin/koha/erm/agreements")
} else {
this.setError(response.message || response.statusText)
setError(response.message || response.statusText)
}
}
).catch(
(error) => {
this.setError(error)
setError(error)
}
)
}
},
props: {
agreement_id: Number
},
name: "AgreementsFormConfirmDelete",
}
</script>

View file

@ -1,6 +1,7 @@
<template>
<div v-if="!this.initialized">Loading...</div>
<div v-else>
<Toolbar />
<table v-if="agreements.length" id="agreement_list"></table>
<div v-else-if="this.initialized" class="dialog message">
There are no agreements defined.
@ -9,9 +10,10 @@
</template>
<script>
import Toolbar from "./AgreementsToolbar.vue"
import ButtonEdit from "./ButtonEdit.vue"
import ButtonDelete from "./ButtonDelete.vue"
import { createVNode, defineComponent, render, resolveComponent } from 'vue'
import { createVNode, render } from 'vue'
import { useVendorStore } from "../../stores/vendors"
import { useAVStore } from "../../stores/authorised_values"
import { storeToRefs } from "pinia"
@ -32,21 +34,11 @@ export default {
av_agreement_renewal_priorities,
}
},
created() {
const apiUrl = '/api/v1/erm/agreements'
fetch(apiUrl)
.then(res => res.json())
.then(
(result) => {
this.agreements = result
this.initialized = true
},
).catch(
(error) => {
this.setError(error)
}
)
data: function () {
return {
agreements: [],
initialized: false,
}
},
beforeRouteEnter(to, from, next) {
next(vm => {
@ -57,6 +49,16 @@ export default {
async getAgreements() {
const agreements = await fetchAgreements()
this.agreements = agreements
this.initialized = true
},
show_agreement: function (agreement_id) {
this.$router.push("/cgi-bin/koha/erm/agreements/" + agreement_id)
},
edit_agreement: function (agreement_id) {
this.$router.push("/cgi-bin/koha/erm/agreements/edit/" + agreement_id)
},
delete_agreement: function (agreement_id) {
this.$router.push("/cgi-bin/koha/erm/agreements/delete/" + agreement_id)
},
},
updated() {
@ -234,25 +236,7 @@ export default {
.DataTable()
.destroy(true)
},
data: function () {
return {
agreements: [],
initialized: false,
}
},
methods: {
show_agreement: function (agreement_id) {
this.$router.push("/cgi-bin/koha/erm/agreements/" + agreement_id)
},
edit_agreement: function (agreement_id) {
this.$router.push("/cgi-bin/koha/erm/agreements/edit/" + agreement_id)
},
delete_agreement: function (agreement_id) {
this.$router.push("/cgi-bin/koha/erm/agreements/delete/" + agreement_id)
},
},
props: {
},
components: {Toolbar},
name: "AgreementsList",
}
</script>

View file

@ -185,7 +185,6 @@ import AgreementPeriods from './AgreementPeriods.vue'
import AgreementUserRoles from './AgreementUserRoles.vue'
import { useVendorStore } from "../../stores/vendors"
import { useAVStore } from "../../stores/authorised_values"
import { useMainStore } from "../../stores/main"
import { fetchAgreement } from "../../fetch"
import { storeToRefs } from "pinia"
@ -212,8 +211,6 @@ export default {
av_agreement_license_location,
} = storeToRefs(AVStore)
const mainStore = useMainStore()
const { setError } = mainStore
return {
format_date,
patron_to_html,
@ -225,7 +222,6 @@ export default {
av_agreement_user_roles,
av_agreement_license_statuses,
av_agreement_license_location,
setError,
}
},
data() {

View file

@ -5,17 +5,13 @@
<script>
import { storeToRefs } from "pinia"
import { useMainStore } from '../../stores/main';
import { useMainStore } from "../../stores/main"
export default {
setup(){
const mainStore = useMainStore()
const { message, error } = storeToRefs(mainStore)
const { removeMessages } = mainStore
return { message, error, removeMessages }
return { message, error }
},
beforeUnmount() {
this.removeMessages()
}
};
</script>

View file

@ -4,6 +4,7 @@
<div class="row">
<div class="col-sm-10 col-sm-push-2">
<main>
<Dialog />
<router-view />
</main>
</div>
@ -41,9 +42,10 @@
<script>
import Breadcrumb from "./Breadcrumb.vue"
import Dialog from "./Dialog.vue"
import { useVendorStore } from "../../stores/vendors"
import { useAVStore } from "../../stores/authorised_values"
import { reactive, computed } from "vue"
import { fetchVendors } from "../../fetch"
export default {
setup() {
@ -68,26 +70,11 @@ export default {
}
},
beforeCreate() {
const apiUrl = "/api/v1/acquisitions/vendors"
fetch(apiUrl)
.then((res) => res.json())
.then(
(result) => {
this.vendorStore.vendors = result
},
(error) => {
this.$emit("set-error", error)
}
)
},
methods: {
switchComponent(component) {
this.component = component
},
fetchVendors().then((vendors) => this.vendorStore.vendors = vendors)
},
components: {
Breadcrumb,
Dialog,
},
};
</script>

View file

@ -118,7 +118,7 @@
<script>
import flatPickr from 'vue-flatpickr-component'
import { useAVStore } from "../../stores/authorised_values"
import { useMainStore } from "../../stores/main"
import { setMessage, setError } from "../../messages"
import { fetchLicense } from '../../fetch'
import { storeToRefs } from "pinia"
@ -131,13 +131,9 @@ export default {
av_license_statuses,
} = storeToRefs(AVStore)
const mainStore = useMainStore()
const { setMessage, setError, resetMessages } = mainStore
return {
av_license_types,
av_license_statuses,
setMessage, setError, resetMessages,
}
},
data() {
@ -206,15 +202,15 @@ export default {
.then(response => {
if (response.status == 200) {
this.$router.push("/cgi-bin/koha/erm/licenses")
this.setMessage('License updated')
setMessage('License updated')
} else if (response.status == 201) {
this.$router.push("/cgi-bin/koha/erm/licenses")
this.setMessage('License created')
setMessage('License created')
} else {
this.setError(response.message || response.statusText)
setError(response.message || response.statusText)
}
}, (error) => {
this.setError(error)
setError(error)
}).catch(e => { console.log(e) })
},
},

View file

@ -35,17 +35,10 @@
</template>
<script>
import { useMainStore } from "../../stores/main"
import { fetchLicense } from "../../fetch"
import { setMessage, setError } from "../../messages"
export default {
setup() {
const mainStore = useMainStore()
const { setMessage, setError } = mainStore
return {
setMessage, setError,
}
},
data() {
return {
license: {},
@ -67,7 +60,7 @@ export default {
onSubmit(e) {
e.preventDefault()
let apiUrl = '/api/v1/erm/licenses/' + this.license_id
let apiUrl = '/api/v1/erm/licenses/' + this.license.license_id
const options = {
method: 'DELETE',
@ -80,15 +73,15 @@ export default {
.then(
(response) => {
if (response.status == 204) {
this.$router.push("/cgi-bin/koha/erm/agreements")
this.setMessage("License deleted")
this.$router.push("/cgi-bin/koha/erm/licenses")
setMessage("License deleted")
} else {
this.setError(response.message || response.statusText)
setError(response.message || response.statusText)
}
}
).catch(
(error) => {
this.setError(error)
setError(error)
}
)
}

View file

@ -1,6 +1,7 @@
<template>
<div v-if="!this.initialized">Loading...</div>
<div v-else>
<Toolbar />
<table v-if="licenses.length" id="license_list"></table>
<div v-else-if="this.initialized" class="dialog message">
There are no licenses defined.
@ -9,11 +10,13 @@
</template>
<script>
import Toolbar from "./LicensesToolbar.vue"
import ButtonEdit from "./ButtonEdit.vue"
import ButtonDelete from "./ButtonDelete.vue"
import { createVNode, defineComponent, render, resolveComponent } from 'vue'
import { createVNode, render } from 'vue'
import { useAVStore } from "../../stores/authorised_values"
import { storeToRefs } from "pinia"
import { fetchLicenses } from "../../fetch"
export default {
setup() {
@ -28,21 +31,6 @@ export default {
av_license_statuses,
}
},
created() {
const apiUrl = '/api/v1/erm/licenses'
fetch(apiUrl)
.then(res => res.json())
.then(
(result) => {
this.licenses = result
this.initialized = true
},
(error) => {
this.setError(error)
}
)
},
updated() {
let show_license = this.show_license
let edit_license = this.edit_license
@ -193,7 +181,17 @@ export default {
initialized: false,
}
},
beforeRouteEnter(to, from, next) {
next(vm => {
vm.getLicenses()
})
},
methods: {
async getLicenses() {
const licenses = await fetchLicenses()
this.licenses = licenses
this.initialized = true
},
show_license: function (license_id) {
this.$router.push("/cgi-bin/koha/erm/licenses/" + license_id)
},
@ -208,6 +206,7 @@ export default {
av_license_types: Array,
av_license_statuses: Array,
},
components: { Toolbar },
name: "LicensesList",
}
</script>

View file

@ -55,7 +55,6 @@
<script>
import { useAVStore } from "../../stores/authorised_values"
import { useMainStore } from "../../stores/main"
import { storeToRefs } from "pinia"
import { fetchLicense } from "../../fetch"
@ -75,15 +74,11 @@ export default {
av_license_statuses,
} = storeToRefs(AVStore)
const mainStore = useMainStore()
const { setError } = mainStore
return {
format_date,
get_lib_from_av,
av_license_types,
av_license_statuses,
setError,
}
},
data() {

View file

@ -1,3 +1,5 @@
import { setError } from "./messages";
export const fetchAgreement = async function (agreement_id) {
if (!agreement_id) return;
const apiUrl = "/api/v1/erm/agreements/" + agreement_id;
@ -14,14 +16,14 @@ export const fetchAgreement = async function (agreement_id) {
agreement = result;
},
(error) => {
this.setError(error);
setError(error);
}
);
return agreement;
};
export const fetchAgreements = async function () {
const apiUrl = "/api/v1/erm/agreements"
const apiUrl = "/api/v1/erm/agreements";
let agreements;
await fetch(apiUrl)
.then((res) => res.json())
@ -30,7 +32,7 @@ export const fetchAgreements = async function () {
agreements = result;
},
(error) => {
this.setError(error);
setError(error);
}
);
return agreements;
@ -47,8 +49,57 @@ export const fetchLicense = async function (license_id) {
license = result;
},
(error) => {
this.setError(error);
setError(error);
}
);
return license;
};
export const fetchLicenses = async function () {
const apiUrl = "/api/v1/erm/licenses";
let licenses;
await fetch(apiUrl)
.then((res) => res.json())
.then(
(result) => {
licenses = result;
},
(error) => {
setError(error);
}
);
return licenses;
};
export const fetchPatron = async function (patron_id) {
if (!patron_id) return;
const apiUrl = "/api/v1/patrons/" + patron_id;
let patron;
await fetch(apiUrl)
.then((res) => res.json())
.then(
(result) => {
patron = result;
},
(error) => {
setError(error);
}
);
return patron;
};
export const fetchVendors = async function () {
const apiUrl = "/api/v1/acquisitions/vendors";
let vendors;
await fetch(apiUrl)
.then((res) => res.json())
.then(
(result) => {
vendors = result;
},
(error) => {
setError(error);
}
);
return vendors;
};

View file

@ -14,8 +14,15 @@ import { routes } from "./routes";
const router = createRouter({ history: createWebHistory(), routes });
import { useMainStore } from "./stores/main";
createApp(App)
.use(createPinia())
.use(router)
.component("font-awesome-icon", FontAwesomeIcon)
.mount("#erm");
const mainStore = useMainStore();
const { removeMessages } = mainStore;
router.beforeEach((to, from) => {
removeMessages(); // This will actually flag the messages as displayed already
});

View file

@ -0,0 +1,19 @@
import { useMainStore } from "./stores/main";
import { storeToRefs } from "pinia";
export const setError = function (new_error) {
const mainStore = useMainStore();
const { setError } = mainStore;
setError("Something went wrong: " + new_error);
};
export const setMessage = function (message) {
const mainStore = useMainStore();
const { setMessage } = mainStore;
setMessage(message);
};
export const removeMessages = function () {
const mainStore = useMainStore();
const { removeMessages } = mainStore;
removeMessages();
};

View file

@ -1,9 +1,9 @@
import ERMHome from "./components/ERM/ERMHome.vue";
import Agreements from "./components/ERM/Agreements.vue";
import AgreementsList from "./components/ERM/AgreementsList.vue";
import AgreementsShow from "./components/ERM/AgreementsShow.vue";
import AgreementsFormAdd from "./components/ERM/AgreementsFormAdd.vue";
import AgreementsFormConfirmDelete from "./components/ERM/AgreementsFormConfirmDelete.vue";
import Licenses from "./components/ERM/Licenses.vue";
import LicensesList from "./components/ERM/LicensesList.vue";
import LicensesShow from "./components/ERM/LicensesShow.vue";
import LicensesFormAdd from "./components/ERM/LicensesFormAdd.vue";
import LicensesFormConfirmDelete from "./components/ERM/LicensesFormConfirmDelete.vue";
@ -27,7 +27,7 @@ export const routes = [
},
{
path: "/cgi-bin/koha/erm/agreements",
component: Agreements,
component: AgreementsList,
meta: {
breadcrumb: [
breadcrumbs.home,
@ -87,7 +87,7 @@ export const routes = [
},
{
path: "/cgi-bin/koha/erm/licenses",
component: Licenses,
component: LicensesList,
meta: {
breadcrumb: [
breadcrumbs.home,

View file

@ -1,22 +1,30 @@
import { defineStore } from 'pinia'
import { defineStore } from "pinia";
export const useMainStore = defineStore('main', {
state: () => ({
export const useMainStore = defineStore("main", {
state: () => ({
message: null,
error: null,
previousMessage: null,
previousError: null,
displayed_already: false,
}),
actions: {
setMessage(message) {
this.error = null;
this.message = message;
this.displayed_already = false;
},
setError(error) {
this.error = "Something went wrong: " + error;
this.message = null;
this.displayed_already = false;
},
removeMessages() {
this.error = null;
this.message = null;
if (this.displayed_already) {
this.error = null;
this.message = null;
}
this.displayed_already = true;
},
},
});
});