Bugzilla – Attachment 172636 Details for
Bug 10190
Overdue notice triggers based on item type
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 10190: Add a vue app for circulation triggers
Bug-10190-Add-a-vue-app-for-circulation-triggers.patch (text/plain), 16.74 KB, created by
Martin Renvoize (ashimema)
on 2024-10-10 16:19:49 UTC
(
hide
)
Description:
Bug 10190: Add a vue app for circulation triggers
Filename:
MIME Type:
Creator:
Martin Renvoize (ashimema)
Created:
2024-10-10 16:19:49 UTC
Size:
16.74 KB
patch
obsolete
>From 80274d71d397d723aa8afcf94c78f0119d2041f8 Mon Sep 17 00:00:00 2001 >From: Matt Blenkinsop <matt.blenkinsop@ptfs-europe.com> >Date: Tue, 13 Aug 2024 14:15:44 +0000 >Subject: [PATCH] Bug 10190: Add a vue app for circulation triggers > >This patch adds a new vue based page for administering circulation >triggers. This aims to replace the 'Overdue notice/status triggers' >page available from Tools. > >The new page is available from Koha administration > Circulation triggers > >Sponsored-by: Glasgow Colleges Library Group <https://library.cityofglasgowcollege.ac.uk> >Signed-off-by: George Harkins <George.Harkins@cityofglasgowcollege.ac.uk> >--- > admin/circulation_triggers.pl | 45 +++++++++++++ > debian/templates/apache-shared-intranet.conf | 1 + > .../prog/en/modules/admin/admin-home.tt | 4 ++ > .../en/modules/admin/circulation_triggers.tt | 42 ++++++++++++ > .../Admin/CirculationTriggers/Main.vue | 65 +++++++++++++++++++ > .../vue/fetch/circulation-rules-api-client.js | 38 +++++++++++ > .../vue/modules/admin/circulation_triggers.ts | 57 ++++++++++++++++ > .../vue/routes/admin/circulation_triggers.js | 47 ++++++++++++++ > .../prog/js/vue/stores/circulation-rules.js | 49 ++++++++++++++ > webpack.config.js | 1 + > 10 files changed, 349 insertions(+) > create mode 100755 admin/circulation_triggers.pl > create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/admin/circulation_triggers.tt > create mode 100644 koha-tmpl/intranet-tmpl/prog/js/vue/components/Admin/CirculationTriggers/Main.vue > create mode 100644 koha-tmpl/intranet-tmpl/prog/js/vue/fetch/circulation-rules-api-client.js > create mode 100644 koha-tmpl/intranet-tmpl/prog/js/vue/modules/admin/circulation_triggers.ts > create mode 100644 koha-tmpl/intranet-tmpl/prog/js/vue/routes/admin/circulation_triggers.js > create mode 100644 koha-tmpl/intranet-tmpl/prog/js/vue/stores/circulation-rules.js > >diff --git a/admin/circulation_triggers.pl b/admin/circulation_triggers.pl >new file mode 100755 >index 00000000000..a8db14f9981 >--- /dev/null >+++ b/admin/circulation_triggers.pl >@@ -0,0 +1,45 @@ >+#!/usr/bin/perl >+ >+# Copyright 2024 PTFS Europe Ltd >+# >+# This file is part of Koha. >+# >+# Koha is free software; you can redistribute it and/or modify it >+# under the terms of the GNU General Public License as published by >+# the Free Software Foundation; either version 3 of the License, or >+# (at your option) any later version. >+# >+# Koha is distributed in the hope that it will be useful, but >+# WITHOUT ANY WARRANTY; without even the implied warranty of >+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+# GNU General Public License for more details. >+# >+# You should have received a copy of the GNU General Public License >+# along with Koha; if not, see <http://www.gnu.org/licenses>. >+ >+use Modern::Perl; >+ >+use CGI qw ( -utf8 ); >+use C4::Auth qw( get_template_and_user ); >+use C4::Output qw( output_html_with_http_headers ); >+ >+my $query = CGI->new; >+ >+my ( $template, $loggedinuser, $cookie ) = get_template_and_user( >+ { >+ template_name => "admin/circulation_triggers.tt", >+ query => $query, >+ type => "intranet", >+ } >+); >+ >+my $letters = C4::Letters::GetLettersAvailableForALibrary( >+ { >+ branchcode => undef, >+ module => "circulation", >+ } >+); >+ >+$template->param( letters => $letters ); >+ >+output_html_with_http_headers $query, $cookie, $template->output; >diff --git a/debian/templates/apache-shared-intranet.conf b/debian/templates/apache-shared-intranet.conf >index 49b742f868a..86dcb7bf0c6 100644 >--- a/debian/templates/apache-shared-intranet.conf >+++ b/debian/templates/apache-shared-intranet.conf >@@ -24,6 +24,7 @@ RewriteRule ^/cgi-bin/koha/erm/.*$ /cgi-bin/koha/erm/erm.pl [PT] > RewriteCond %{REQUEST_URI} !^/cgi-bin/koha/preservation/.*.pl$ > RewriteRule ^/cgi-bin/koha/preservation/.*$ /cgi-bin/koha/preservation/home.pl [PT] > RewriteRule ^/cgi-bin/koha/admin/record_sources(.*)?$ /cgi-bin/koha/admin/record_sources.pl$1 [PT] >+RewriteRule ^/cgi-bin/koha/admin/circulation_triggers(.*)?$ /cgi-bin/koha/admin/circulation_triggers.pl$1 [PT] > > Alias "/api" "/usr/share/koha/api" > <Directory "/usr/share/koha/api"> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/admin-home.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/admin-home.tt >index 554b4dc1b92..897bb05bc4d 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/admin-home.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/admin-home.tt >@@ -99,6 +99,10 @@ > <dt><a href="/cgi-bin/koha/admin/smart-rules.pl">Circulation and fine rules</a></dt> > <dd>Define circulation and fine rules for combinations of libraries, patron categories, and item types</dd> > [% END %] >+ [% IF ( CAN_user_tools_edit_notice_status_triggers ) %] >+ <dt><a href="/cgi-bin/koha/admin/circulation_triggers">Circulation triggers</a></dt> >+ <dd>Define triggers for circulation notices</dd> >+ [% END %] > [% IF ( CAN_user_parameters_manage_patron_attributes ) %] > <dt><a href="/cgi-bin/koha/admin/patron-attr-types.pl">Patron attribute types</a></dt> > <dd>Define extended attributes (identifiers and statistical categories) for patron records</dd> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/circulation_triggers.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/circulation_triggers.tt >new file mode 100644 >index 00000000000..57ba3129856 >--- /dev/null >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/circulation_triggers.tt >@@ -0,0 +1,42 @@ >+[% USE raw %] >+[% USE To %] >+[% USE Asset %] >+[% USE KohaDates %] >+[% USE TablesSettings %] >+[% USE AuthorisedValues %] >+[% SET footerjs = 1 %] >+[% PROCESS 'i18n.inc' %] >+[% INCLUDE 'doc-head-open.inc' %] >+<title>[% FILTER collapse %] >+ [% t("Circulation triggers") | html %] › >+ [% t("Administration") | html %] › >+ [% t("Koha") | html %] >+[% END %]</title> >+[% INCLUDE 'doc-head-close.inc' %] >+</head> >+ >+<body id="circulation_triggers" class="circulation_triggers"> >+[% WRAPPER 'header.inc' %] >+ [% INCLUDE 'prefs-admin-search.inc' %] >+[% END %] >+ >+<div id="__app"> <!-- this is closed in intranet-bottom.inc --> >+ >+[% MACRO jsinclude BLOCK %] >+ [% INCLUDE 'calendar.inc' %] <!-- FIXME: this shouldn't be needed --> >+ [% INCLUDE 'datatables.inc' %] >+ [% INCLUDE 'columns_settings.inc' %] >+ [% INCLUDE 'js-patron-format.inc' %] >+ [% INCLUDE 'js-date-format.inc' %] >+ >+ <script> >+ >+ const letters = [% To.json(letters) | $raw %]; >+ >+ </script> >+ >+ [% Asset.js("js/vue/dist/admin/circulation_triggers.js") | $raw %] >+ >+[% END %] >+ >+[% INCLUDE 'intranet-bottom.inc' %] >diff --git a/koha-tmpl/intranet-tmpl/prog/js/vue/components/Admin/CirculationTriggers/Main.vue b/koha-tmpl/intranet-tmpl/prog/js/vue/components/Admin/CirculationTriggers/Main.vue >new file mode 100644 >index 00000000000..2010cedbc62 >--- /dev/null >+++ b/koha-tmpl/intranet-tmpl/prog/js/vue/components/Admin/CirculationTriggers/Main.vue >@@ -0,0 +1,65 @@ >+<template> >+ <div> >+ <div id="sub-header"> >+ <Breadcrumbs /> >+ <Help /> >+ </div> >+ <div class="main container-fluid"> >+ <div class="row"> >+ <div class="col-sm-10 col-sm-push-2"> >+ <main> >+ <Dialog /> >+ <router-view /> >+ </main> >+ </div> >+ >+ <div class="col-sm-2 col-sm-pull-10"></div> >+ </div> >+ </div> >+ </div> >+</template> >+ >+<script> >+import Breadcrumbs from "../../Breadcrumbs.vue" >+import Help from "../../Help.vue" >+import Dialog from "../../Dialog.vue" >+import "vue-select/dist/vue-select.css" >+import { inject } from "vue" >+ >+export default { >+ setup() { >+ const circRulesStore = inject("circRulesStore") >+ letters.unshift({ >+ name: "No letter", >+ code: "", >+ }) >+ circRulesStore.letters = letters >+ >+ return { >+ letters, >+ } >+ }, >+ components: { >+ Breadcrumbs, >+ Dialog, >+ Help, >+ }, >+} >+</script> >+ >+<style> >+form .v-select { >+ display: inline-block; >+ background-color: white; >+ width: 30%; >+} >+ >+.v-select, >+input:not([type="submit"]):not([type="search"]):not([type="button"]):not([type="checkbox"]):not([type="radio"]), >+textarea { >+ border-color: rgba(60, 60, 60, 0.26); >+ border-width: 1px; >+ border-radius: 4px; >+ min-width: 30%; >+} >+</style> >diff --git a/koha-tmpl/intranet-tmpl/prog/js/vue/fetch/circulation-rules-api-client.js b/koha-tmpl/intranet-tmpl/prog/js/vue/fetch/circulation-rules-api-client.js >new file mode 100644 >index 00000000000..e6e749ffcea >--- /dev/null >+++ b/koha-tmpl/intranet-tmpl/prog/js/vue/fetch/circulation-rules-api-client.js >@@ -0,0 +1,38 @@ >+import HttpClient from "./http-client"; >+ >+export class CircRuleAPIClient extends HttpClient { >+ constructor() { >+ super({ >+ baseURL: "/api/v1/", >+ }); >+ } >+ >+ get circRules() { >+ return { >+ getAll: (query, params, headers) => >+ this.getAll({ >+ endpoint: "circulation_rules", >+ query, >+ params, >+ headers, >+ }), >+ update: rule => >+ this.put({ >+ endpoint: "circulation_rules", >+ body: rule, >+ }), >+ count: (query = {}) => >+ this.count({ >+ endpoint: >+ "circulation_rules?" + >+ new URLSearchParams({ >+ _page: 1, >+ _per_page: 1, >+ ...(query && { q: JSON.stringify(query) }), >+ }), >+ }), >+ }; >+ } >+} >+ >+export default CircRuleAPIClient; >diff --git a/koha-tmpl/intranet-tmpl/prog/js/vue/modules/admin/circulation_triggers.ts b/koha-tmpl/intranet-tmpl/prog/js/vue/modules/admin/circulation_triggers.ts >new file mode 100644 >index 00000000000..f5e6a50c50b >--- /dev/null >+++ b/koha-tmpl/intranet-tmpl/prog/js/vue/modules/admin/circulation_triggers.ts >@@ -0,0 +1,57 @@ >+import { createApp } from "vue"; >+import { createPinia } from "pinia"; >+import { createWebHistory, createRouter } from "vue-router"; >+ >+import { library } from "@fortawesome/fontawesome-svg-core"; >+import { >+ faPlus, >+ faMinus, >+ faPencil, >+ faTrash, >+ faSpinner, >+} from "@fortawesome/free-solid-svg-icons"; >+import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome"; >+import vSelect from "vue-select"; >+import { useNavigationStore } from "../../stores/navigation"; >+import { useMainStore } from "../../stores/main"; >+import { useCircRulesStore } from "../../stores/circulation-rules"; >+import routesDef from "../../routes/admin/circulation_triggers"; >+ >+library.add(faPlus, faMinus, faPencil, faTrash, faSpinner); >+ >+const pinia = createPinia(); >+const navigationStore = useNavigationStore(pinia); >+const mainStore = useMainStore(pinia); >+const circRulesStore = useCircRulesStore(pinia); >+const { removeMessages } = mainStore; >+const { setRoutes } = navigationStore; >+const routes = setRoutes(routesDef); >+ >+const router = createRouter({ >+ history: createWebHistory(), >+ linkExactActiveClass: "current", >+ routes, >+}); >+ >+import App from "../../components/Admin/CirculationTriggers/Main.vue"; >+import i18n from "../../i18n"; >+ >+const app = createApp(App); >+ >+const rootComponent = app >+ .use(i18n) >+ .use(pinia) >+ .use(router) >+ .component("font-awesome-icon", FontAwesomeIcon) >+ .component("v-select", vSelect); >+ >+app.config.unwrapInjectedRef = true; >+app.provide("mainStore", mainStore); >+app.provide("navigationStore", navigationStore); >+app.provide("circRulesStore", circRulesStore); >+app.mount("#__app"); >+ >+router.beforeEach(to => { >+ navigationStore.$patch({ current: to.matched, params: to.params || {} }); >+ removeMessages(); // This will actually flag the messages as displayed already >+}); >diff --git a/koha-tmpl/intranet-tmpl/prog/js/vue/routes/admin/circulation_triggers.js b/koha-tmpl/intranet-tmpl/prog/js/vue/routes/admin/circulation_triggers.js >new file mode 100644 >index 00000000000..9619c176ac5 >--- /dev/null >+++ b/koha-tmpl/intranet-tmpl/prog/js/vue/routes/admin/circulation_triggers.js >@@ -0,0 +1,47 @@ >+import { markRaw } from "vue"; >+import { $__ } from "../../i18n"; >+ >+import CirculationTriggersList from "../../components/Admin/CirculationTriggers/CirculationTriggersList.vue"; >+import CirculationTriggersFormAdd from "../../components/Admin/CirculationTriggers/CirculationTriggersFormAdd.vue"; >+ >+export default { >+ title: $__("Administration"), >+ path: "", >+ href: "/cgi-bin/koha/admin/admin-home.pl", >+ is_base: true, >+ is_default: true, >+ children: [ >+ { >+ title: $__("Circulation triggers"), >+ path: "/cgi-bin/koha/admin/circulation_triggers", >+ children: [ >+ { >+ path: "", >+ name: "CirculationTriggersList", >+ component: markRaw(CirculationTriggersList), >+ title: $__("Home"), >+ children: [ >+ { >+ path: "add", >+ name: "CirculationTriggersFormAdd", >+ component: markRaw(CirculationTriggersFormAdd), >+ title: $__("Add new trigger"), >+ meta: { >+ showModal: true, >+ }, >+ }, >+ { >+ path: "edit", >+ name: "CirculationTriggersFormEdit", >+ component: markRaw(CirculationTriggersFormAdd), >+ title: $__("Edit trigger"), >+ meta: { >+ showModal: true, >+ }, >+ }, >+ ], >+ }, >+ ], >+ }, >+ ], >+}; >diff --git a/koha-tmpl/intranet-tmpl/prog/js/vue/stores/circulation-rules.js b/koha-tmpl/intranet-tmpl/prog/js/vue/stores/circulation-rules.js >new file mode 100644 >index 00000000000..da89e140cb8 >--- /dev/null >+++ b/koha-tmpl/intranet-tmpl/prog/js/vue/stores/circulation-rules.js >@@ -0,0 +1,49 @@ >+import { defineStore } from "pinia"; >+ >+export const useCircRulesStore = defineStore("circRules", { >+ state: () => ({ >+ letters: [], >+ }), >+ actions: { >+ splitCircRulesByTriggerNumber(rules) { >+ const ruleSuffixes = ["delay", "notice", "mtt", "restrict"]; >+ let numberOfTabs = 1; >+ const rulesPerTrigger = rules.reduce((acc, rule) => { >+ const regex = /overdue_(\d+)_delay/g; >+ const numberOfTriggers = Object.keys(rule).filter(key => >+ regex.test(key) >+ ).length; >+ numberOfTabs = this.setNumberOfTabs( >+ numberOfTriggers, >+ numberOfTabs >+ ); >+ const triggerNumbers = Array.from( >+ { length: numberOfTriggers }, >+ (_, i) => i + 1 >+ ); >+ triggerNumbers.forEach(i => { >+ const ruleCopy = JSON.parse(JSON.stringify(rule)); >+ const rulesToDelete = triggerNumbers.filter( >+ num => num !== i >+ ); >+ ruleSuffixes.forEach(suffix => { >+ rulesToDelete.forEach(number => { >+ delete ruleCopy[`overdue_${number}_${suffix}`]; >+ }); >+ }); >+ ruleCopy.triggerNumber = i; >+ acc.push(ruleCopy); >+ }); >+ return acc; >+ }, []); >+ >+ return { numberOfTabs, rulesPerTrigger }; >+ }, >+ setNumberOfTabs(triggerCount, tabCount) { >+ if (triggerCount > tabCount) { >+ return Array.from({ length: triggerCount }, (_, i) => i + 1); >+ } >+ return tabCount; >+ }, >+ }, >+}); >diff --git a/webpack.config.js b/webpack.config.js >index ae87653c244..1b52cbae448 100644 >--- a/webpack.config.js >+++ b/webpack.config.js >@@ -8,6 +8,7 @@ module.exports = { > erm: "./koha-tmpl/intranet-tmpl/prog/js/vue/modules/erm.ts", > preservation: "./koha-tmpl/intranet-tmpl/prog/js/vue/modules/preservation.ts", > "admin/record_sources": "./koha-tmpl/intranet-tmpl/prog/js/vue/modules/admin/record_sources.ts", >+ "admin/circulation_triggers": "./koha-tmpl/intranet-tmpl/prog/js/vue/modules/admin/circulation_triggers.ts", > }, > output: { > filename: "[name].js", >-- >2.47.0
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 10190
:
170357
|
170358
|
170359
|
170360
|
170361
|
170362
|
170363
|
170364
|
170365
|
170366
|
170367
|
170368
|
170369
|
170370
|
170371
|
170372
|
170373
|
170374
|
170375
|
170376
|
170380
|
170449
|
171727
|
171728
|
171729
|
171730
|
171731
|
171732
|
171733
|
171734
|
171735
|
171736
|
171737
|
171738
|
171739
|
171740
|
171741
|
171742
|
171743
|
171744
|
171745
|
171746
|
171747
|
171748
|
171749
|
171750
|
171751
|
171752
|
171753
|
171754
|
171755
|
172588
|
172589
|
172590
|
172591
|
172592
|
172593
|
172594
|
172595
|
172596
|
172597
|
172598
|
172599
|
172600
|
172601
|
172602
|
172603
|
172604
|
172605
|
172606
|
172607
|
172608
|
172609
|
172612
|
172614
|
172617
|
172619
|
172621
|
172622
|
172623
|
172624
|
172625
|
172626
|
172630
|
172631
|
172632
|
172633
|
172634
|
172635
| 172636 |
172637
|
172638
|
172639
|
172640
|
172641
|
172642
|
172643
|
172644
|
172645
|
172646
|
172647
|
172648
|
172649
|
172650
|
172651
|
172652
|
172653
|
172654
|
172655
|
172656
|
172657
|
172658
|
172659
|
172660
|
172661
|
172662
|
172663