Bugzilla – Attachment 178182 Details for
Bug 38010
Migrate vendors to Vue
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 38010: Add vue app and list component
Bug-38010-Add-vue-app-and-list-component.patch (text/plain), 31.19 KB, created by
Matt Blenkinsop
on 2025-02-18 13:46:36 UTC
(
hide
)
Description:
Bug 38010: Add vue app and list component
Filename:
MIME Type:
Creator:
Matt Blenkinsop
Created:
2025-02-18 13:46:36 UTC
Size:
31.19 KB
patch
obsolete
>From ed9a239bbce14d12cb951c0df57356aef01052cb Mon Sep 17 00:00:00 2001 >From: Matt Blenkinsop <matt.blenkinsop@ptfs-europe.com> >Date: Wed, 11 Sep 2024 09:11:32 +0000 >Subject: [PATCH] Bug 38010: Add vue app and list component > >This patch adds the base vue app as well as the component to list vendors >--- > acqui/booksellers.pl | 8 + > acqui/vendors.pl | 54 ++++ > api/v1/swagger/definitions/vendor.yaml | 5 +- > .../swagger/paths/acquisitions_vendors.yaml | 3 +- > debian/templates/apache-shared-intranet.conf | 3 +- > .../prog/en/includes/acquisitions-toolbar.inc | 2 +- > .../prog/en/modules/acqui/acqui-home.tt | 9 +- > .../prog/en/modules/acqui/vendors.tt | 47 ++++ > .../prog/js/vue/components/Vendors/Home.vue | 9 + > .../prog/js/vue/components/Vendors/Main.vue | 156 +++++++++++ > .../js/vue/components/Vendors/VendorList.vue | 250 ++++++++++++++++++ > .../js/vue/fetch/acquisition-api-client.js | 33 ++- > .../prog/js/vue/modules/vendors.ts | 62 +++++ > .../prog/js/vue/routes/vendors.js | 43 +++ > .../prog/js/vue/stores/vendors.js | 8 +- > rspack.config.js | 1 + > webpack.config.js | 1 + > 17 files changed, 681 insertions(+), 13 deletions(-) > create mode 100644 acqui/vendors.pl > create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/acqui/vendors.tt > create mode 100644 koha-tmpl/intranet-tmpl/prog/js/vue/components/Vendors/Home.vue > create mode 100644 koha-tmpl/intranet-tmpl/prog/js/vue/components/Vendors/Main.vue > create mode 100644 koha-tmpl/intranet-tmpl/prog/js/vue/components/Vendors/VendorList.vue > create mode 100644 koha-tmpl/intranet-tmpl/prog/js/vue/modules/vendors.ts > create mode 100644 koha-tmpl/intranet-tmpl/prog/js/vue/routes/vendors.js > >diff --git a/acqui/booksellers.pl b/acqui/booksellers.pl >index fed8060a726..afe288563d0 100755 >--- a/acqui/booksellers.pl >+++ b/acqui/booksellers.pl >@@ -176,4 +176,12 @@ $template->param( > ); > $template->{VARS}->{'allbaskets'} = $allbaskets; > >+$template->param( >+ loop_suppliers => $loop_suppliers, >+ supplier => ( $booksellerid || $supplier ), >+ count => $supplier_count, >+ has_budgets => $has_budgets, >+); >+$template->{VARS}->{'allbaskets'} = $allbaskets; >+ > output_html_with_http_headers $query, $cookie, $template->output; >diff --git a/acqui/vendors.pl b/acqui/vendors.pl >new file mode 100644 >index 00000000000..a160284308c >--- /dev/null >+++ b/acqui/vendors.pl >@@ -0,0 +1,54 @@ >+#!/usr/bin/perl >+ >+# Copyright 2024 PTFS Europe >+# >+# 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 C4::Auth qw( get_template_and_user haspermission ); >+use C4::Output qw( output_html_with_http_headers ); >+use CGI qw ( -utf8 ); >+ >+use C4::Context; >+ >+use Koha::Acquisition::Currencies; >+ >+my $query = CGI->new; >+my ( $template, $loggedinuser, $cookie, $userflags ) = get_template_and_user( >+ { >+ template_name => 'acqui/vendors.tt', >+ query => $query, >+ type => 'intranet', >+ flagsrequired => { acquisition => '*' }, >+ } >+); >+ >+my $user_permissions = {}; >+my $var_data = $template->{VARS}; >+foreach my $key ( keys %{$var_data} ) { >+ $user_permissions->{$key} = $var_data->{$key} if ( $key =~ /CAN_user_(.*)/ ); >+} >+ >+my @gst_values = map { option => $_ + 0.0 }, split( '\|', C4::Context->preference("TaxRates") ); >+ >+$template->param( >+ user_permissions => $user_permissions, >+ currencies => Koha::Acquisition::Currencies->search->unblessed, >+ gst_values => \@gst_values, >+ edifact => C4::Context->preference('EDIFACT') >+); >+ >+output_html_with_http_headers $query, $cookie, $template->output; >diff --git a/api/v1/swagger/definitions/vendor.yaml b/api/v1/swagger/definitions/vendor.yaml >index 262db4fb10b..5f285dc9bc4 100644 >--- a/api/v1/swagger/definitions/vendor.yaml >+++ b/api/v1/swagger/definitions/vendor.yaml >@@ -119,6 +119,9 @@ properties: > description: List of aliases > items: > $ref: "vendor_alias.yaml" >+ baskets: >+ type: array >+ description: List of baskets > subscriptions_count: > type: > - integer >@@ -126,4 +129,4 @@ properties: > description: Number of linked subscriptions > additionalProperties: false > required: >- - name >+ - name >\ No newline at end of file >diff --git a/api/v1/swagger/paths/acquisitions_vendors.yaml b/api/v1/swagger/paths/acquisitions_vendors.yaml >index 311cb0ac478..4670ff81259 100644 >--- a/api/v1/swagger/paths/acquisitions_vendors.yaml >+++ b/api/v1/swagger/paths/acquisitions_vendors.yaml >@@ -35,6 +35,7 @@ > type: string > enum: > - aliases >+ - baskets > - subscriptions+count > collectionFormat: csv > responses: >@@ -268,4 +269,4 @@ > $ref: "../swagger.yaml#/definitions/error" > x-koha-authorization: > permissions: >- acquisition: vendors_manage >+ acquisition: vendors_manage >\ No newline at end of file >diff --git a/debian/templates/apache-shared-intranet.conf b/debian/templates/apache-shared-intranet.conf >index 49b742f868a..d34a65c20f7 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/vendors(.*)?$ /cgi-bin/koha/acqui/vendors.pl$1 [PT] > > Alias "/api" "/usr/share/koha/api" > <Directory "/usr/share/koha/api"> >@@ -35,4 +36,4 @@ Alias "/api" "/usr/share/koha/api" > RewriteBase /api/ > RewriteCond %{REQUEST_URI} !^/api/v[0-1]+/app.pl > RewriteRule ^(v[0-9]+)/(.*)$ /api/$1/app.pl/api/$1/$2 [L] >-</Directory> >+</Directory> >\ No newline at end of file >diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/acquisitions-toolbar.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/acquisitions-toolbar.inc >index b920393f97b..1ac26f6b086 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/includes/acquisitions-toolbar.inc >+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/acquisitions-toolbar.inc >@@ -33,7 +33,7 @@ > [% END %] > [% ELSIF ( CAN_user_acquisition_vendors_manage ) %] > <div class="btn-group" >- ><a class="btn btn-default" href="/cgi-bin/koha/acqui/supplier.pl?op=enter"><i class="fa fa-plus"></i> New vendor</a></div >+ ><a class="btn btn-default" href="/cgi-bin/koha/vendors"><i class="fa fa-plus"></i> New vendor</a></div > > > [% END %] > </div> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/acqui-home.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/acqui-home.tt >index 76ac361d9b7..2658c38bc1c 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/acqui-home.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/acqui-home.tt >@@ -48,13 +48,8 @@ > <div class="col"> > <div id="acqui_acqui_home_order"> > <fieldset> >- <legend>Search vendors</legend> >- <form name="findsupplier" action="/cgi-bin/koha/acqui/booksellers.pl" method="get"> >- <p >- ><label for="supplierpage">Vendor: </label><input type="text" size="25" name="supplier" id="supplierpage" class="focus" /> >- <input type="submit" class="btn btn-primary" value="Search" /> >- </p> >- </form> >+ <legend>View vendors</legend> >+ <a href="/cgi-bin/koha/vendors" class="btn btn-default">Vendor list</a> > </fieldset> > </div> > </div> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/vendors.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/vendors.tt >new file mode 100644 >index 00000000000..e6d5c1c0fa1 >--- /dev/null >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/vendors.tt >@@ -0,0 +1,47 @@ >+[% USE raw %] >+[% USE To %] >+[% USE Asset %] >+[% USE KohaDates %] >+[% USE TablesSettings %] >+[% PROCESS 'i18n.inc' %] >+[% SET footerjs = 1 %] >+[% PROCESS 'patron-search.inc' %] >+[% INCLUDE 'doc-head-open.inc' %] >+<title >+ >[% FILTER collapse %] >+ [% t("Vendors") | html %] >+ › [% t("Koha") | html %] >+ [% END %]</title >+> >+[% INCLUDE 'doc-head-close.inc' %] >+</head> >+ >+<body id="acq_booksellers" class="acq"> >+[% WRAPPER 'header.inc' %] >+ [% INCLUDE 'acquisitions-search.inc' %] >+[% END %] >+ >+<div id="__vendors"> >+ <!-- this is closed in intranet-bottom.inc --> >+ >+ [% MACRO jsinclude BLOCK %] >+ [% INCLUDE 'calendar.inc' %] >+ [% INCLUDE 'datatables.inc' %] >+ [% INCLUDE 'columns_settings.inc' %] >+ [% INCLUDE 'js-patron-format.inc' %] >+ [% INCLUDE 'js-date-format.inc' %] >+ <script> >+ const userPermissions = [% To.json(user_permissions) | $raw %]; >+ const currencies = [% To.json(currencies) | $raw %]; >+ const gstValues = [% To.json(gst_values) | $raw %]; >+ const edifact = [% To.json(edifact) | $raw %] >+ const viewBaskets = [% To.json(viewbaskets) | $raw %] >+ </script> >+ [% Asset.js("js/vue/dist/acquisitions.js") | $raw %] >+ [% INCLUDE 'select2.inc' %] >+ [% SET columns = ['cardnumber','name','category','branch','action'] %] >+ [% PROCESS patron_search_modal columns => columns, modal_title => t("Select user") %] >+ [% PROCESS patron_search_js columns => columns, filter => erm_users, actions => ["select"], preview_on_name_click => 1 %] >+ [% END %] >+ [% INCLUDE 'intranet-bottom.inc' %]</div >+> >diff --git a/koha-tmpl/intranet-tmpl/prog/js/vue/components/Vendors/Home.vue b/koha-tmpl/intranet-tmpl/prog/js/vue/components/Vendors/Home.vue >new file mode 100644 >index 00000000000..7d0f1dad1b2 >--- /dev/null >+++ b/koha-tmpl/intranet-tmpl/prog/js/vue/components/Vendors/Home.vue >@@ -0,0 +1,9 @@ >+<template> >+ <h1>Vendors</h1> >+</template> >+ >+<script> >+export default {}; >+</script> >+ >+<style></style> >diff --git a/koha-tmpl/intranet-tmpl/prog/js/vue/components/Vendors/Main.vue b/koha-tmpl/intranet-tmpl/prog/js/vue/components/Vendors/Main.vue >new file mode 100644 >index 00000000000..a620936b7fa >--- /dev/null >+++ b/koha-tmpl/intranet-tmpl/prog/js/vue/components/Vendors/Main.vue >@@ -0,0 +1,156 @@ >+<template> >+ <div v-if="initialized"> >+ <div id="sub-header"> >+ <Breadcrumbs /> >+ <Help /> >+ </div> >+ <div class="main container-fluid"> >+ <div class="row"> >+ <div class="col-md-10 order-md-2 order-sm-1"> >+ <main> >+ <Dialog /> >+ <router-view /> >+ </main> >+ </div> >+ >+ <div class="col-md-2 order-sm-2 order-md-1"> >+ <LeftMenu :title="$__('Vendors')"></LeftMenu> >+ </div> >+ </div> >+ </div> >+ </div> >+ <div class="main container-fluid" v-else> >+ <Dialog /> >+ </div> >+</template> >+ >+<script> >+import { inject } from "vue"; >+import Breadcrumbs from "../Breadcrumbs.vue"; >+import Help from "../Help.vue"; >+import LeftMenu from "../LeftMenu.vue"; >+import Dialog from "../Dialog.vue"; >+import "vue-select/dist/vue-select.css"; >+import { storeToRefs } from "pinia"; >+import { APIClient } from "../../fetch/api-client"; >+ >+export default { >+ setup() { >+ const vendorStore = inject("vendorStore"); >+ >+ const AVStore = inject("AVStore"); >+ >+ const mainStore = inject("mainStore"); >+ >+ const { loading, loaded, setError } = mainStore; >+ >+ return { >+ vendorStore, >+ AVStore, >+ setError, >+ loading, >+ loaded, >+ AVStore, >+ }; >+ }, >+ beforeCreate() { >+ this.loading(); >+ >+ const fetchConfig = () => { >+ let promises = []; >+ >+ const av_client = APIClient.authorised_values; >+ const authorised_values = { >+ av_vendor_types: "VENDOR_TYPE", >+ av_vendor_interface_types: "VENDOR_INTERFACE_TYPE", >+ }; >+ >+ let av_cat_array = Object.keys(authorised_values).map( >+ function (av_cat) { >+ return '"' + authorised_values[av_cat] + '"'; >+ } >+ ); >+ >+ promises.push( >+ av_client.values >+ .getCategoriesWithValues(av_cat_array) >+ .then(av_categories => { >+ Object.entries(authorised_values).forEach( >+ ([av_var, av_cat]) => { >+ const av_match = av_categories.find( >+ element => element.category_name == av_cat >+ ); >+ this.AVStore[av_var] = >+ av_match.authorised_values; >+ } >+ ); >+ }) >+ ); >+ >+ return Promise.all(promises); >+ }; >+ >+ fetchConfig().then(() => { >+ this.vendorStore.currencies = currencies; >+ this.vendorStore.gstValues = gstValues.map(gv => { >+ return { >+ label: `${(gv.option * 100).toFixed(2)}%`, >+ value: gv.option, >+ }; >+ }); >+ this.loaded(); >+ this.initialized = true; >+ }); >+ }, >+ data() { >+ return { >+ initialized: true, >+ }; >+ }, >+ methods: {}, >+ components: { >+ Breadcrumbs, >+ Dialog, >+ Help, >+ LeftMenu, >+ }, >+}; >+</script> >+ >+<style> >+#menu ul ul, >+#navmenulist ul ul { >+ padding-left: 2em; >+ font-size: 100%; >+} >+ >+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%; >+} >+.flatpickr-input { >+ width: 30%; >+} >+#navmenulist ul li a.current.disabled { >+ background-color: inherit; >+ border-left: 5px solid #e6e6e6; >+ color: #000; >+} >+#navmenulist ul li a.disabled { >+ color: #666; >+ pointer-events: none; >+ font-weight: 700; >+} >+</style> >diff --git a/koha-tmpl/intranet-tmpl/prog/js/vue/components/Vendors/VendorList.vue b/koha-tmpl/intranet-tmpl/prog/js/vue/components/Vendors/VendorList.vue >new file mode 100644 >index 00000000000..a2bce0a3fbb >--- /dev/null >+++ b/koha-tmpl/intranet-tmpl/prog/js/vue/components/Vendors/VendorList.vue >@@ -0,0 +1,250 @@ >+<template> >+ <div v-if="!initialized">{{ $__("Loading") }}</div> >+ <div v-else id="vendors_list"> >+ <Toolbar> >+ <ToolbarButton >+ :to="{ name: 'VendorList' }" >+ icon="plus" >+ :title="$__('New vendor')" >+ /> >+ </Toolbar> >+ <div v-if="vendor_count > 0" class="page-section"> >+ <KohaTable >+ ref="table" >+ v-bind="tableOptions" >+ @show="doShow" >+ @edit="doEdit" >+ @delete="doDelete" >+ @select="doSelect" >+ ></KohaTable> >+ </div> >+ <div v-else class="alert alert-info"> >+ {{ $__("There are no vendors defined") }} >+ </div> >+ </div> >+</template> >+ >+<script> >+import flatPickr from "vue-flatpickr-component"; >+import Toolbar from "../Toolbar.vue"; >+import ToolbarButton from "../ToolbarButton.vue"; >+import { inject, ref, reactive } from "vue"; >+import { APIClient } from "../../fetch/api-client.js"; >+import { storeToRefs } from "pinia"; >+import { build_url } from "../../composables/datatables"; >+import KohaTable from "../KohaTable.vue"; >+ >+export default { >+ setup() { >+ const vendorStore = inject("vendorStore"); >+ const { vendors } = storeToRefs(vendorStore); >+ >+ const { setConfirmationDialog, setMessage } = inject("mainStore"); >+ >+ const { get_lib_from_av, map_av_dt_filter } = inject("AVStore"); >+ >+ const table = ref(); >+ >+ // const filters = reactive({ >+ // by_expired: false, >+ // max_expiration_date: "", >+ // by_mine: false, >+ // }) >+ return { >+ vendors, >+ get_lib_from_av, >+ map_av_dt_filter, >+ table, >+ setConfirmationDialog, >+ setMessage, >+ escape_str, >+ // filters, >+ }; >+ }, >+ data() { >+ return { >+ fp_config: flatpickr_defaults, >+ vendor_count: 0, >+ initialized: false, >+ tableOptions: { >+ columns: this.getTableColumns(), >+ options: { embed: "aliases,baskets,subscriptions" }, >+ url: () => this.table_url(), >+ add_filters: true, >+ filters_options: { >+ 1: [ >+ { _id: 0, _str: this.$__("Inactive") }, >+ { _id: 1, _str: this.$__("Active") }, >+ ], >+ ...(this.map_av_dt_filter("av_vendor_types").length && { >+ 2: () => this.map_av_dt_filter("av_vendor_types"), >+ }), >+ }, >+ actions: { >+ 0: ["show"], >+ "-1": ["edit", "delete"], >+ }, >+ }, >+ before_route_entered: false, >+ building_table: false, >+ }; >+ }, >+ beforeRouteEnter(to, from, next) { >+ next(vm => { >+ vm.getVendorCount().then(() => (vm.initialized = true)); >+ }); >+ }, >+ methods: { >+ async getVendorCount() { >+ const client = APIClient.acquisition; >+ await client.vendors.count().then( >+ count => { >+ this.vendor_count = count; >+ }, >+ error => {} >+ ); >+ }, >+ doShow: function ({ id }, dt, event) { >+ event.preventDefault(); >+ this.$router.push({ >+ name: "VendorShow", >+ params: { vendor_id: id }, >+ }); >+ }, >+ doEdit: function ({ id }, dt, event) { >+ this.$router.push({ >+ name: "Home", >+ }); >+ }, >+ doDelete: function (vendor, dt, event) { >+ this.setConfirmationDialog( >+ { >+ title: this.$__( >+ "Are you sure you want to remove this vendor?" >+ ), >+ message: vendor.name, >+ accept_label: this.$__("Yes, delete"), >+ cancel_label: this.$__("No, do not delete"), >+ }, >+ () => { >+ const client = APIClient.erm; >+ client.vendors.delete(vendor.id).then( >+ success => { >+ this.setMessage( >+ this.$__("Vendor %s deleted").format( >+ vendor.name >+ ), >+ true >+ ); >+ dt.draw(); >+ }, >+ error => {} >+ ); >+ } >+ ); >+ }, >+ doSelect: function (vendor, dt, event) { >+ this.$emit("select-vendor", vendor.id); >+ this.$emit("close"); >+ }, >+ table_url: function () { >+ let url = "/api/v1/acquisitions/vendors"; >+ return url; >+ }, >+ getTableColumns: function () { >+ const escape_str = this.escape_str; >+ const get_lib_from_av = this.get_lib_from_av; >+ >+ return [ >+ { >+ title: __("Name"), >+ data: "me.name:me.id", >+ searchable: true, >+ orderable: true, >+ render: function (data, type, row, meta) { >+ return ( >+ '<a href="/cgi-bin/koha/vendors/' + >+ row.id + >+ '" class="show">' + >+ escape_str(`${row.name} (#${row.id})`) + >+ "</a>" >+ ); >+ }, >+ }, >+ { >+ title: __("Status"), >+ data: "active", >+ searchable: true, >+ orderable: true, >+ render: function (data, type, row, meta) { >+ return escape_str( >+ row.active ? __("Active") : __("Inactive") >+ ); >+ }, >+ }, >+ { >+ title: __("Type"), >+ data: "type", >+ searchable: true, >+ orderable: true, >+ render(data, type, row, meta) { >+ return get_lib_from_av("av_vendor_types", row.type); >+ }, >+ }, >+ { >+ title: __("Currency"), >+ data: "invoice_currency", >+ searchable: true, >+ orderable: true, >+ }, >+ { >+ title: __("Baskets"), >+ data: "baskets", >+ searchable: false, >+ orderable: true, >+ render: function (data, type, row, meta) { >+ return row.baskets.length >+ ? '<a href="/cgi-bin/koha/vendors/' + >+ row.id + >+ '" class="show">' + >+ escape_str( >+ `${row.baskets.length} basket(s)` >+ ) + >+ "</a>" >+ : escape_str(__("No baskets")); >+ }, >+ }, >+ { >+ title: __("Subscriptions"), >+ data: "subscriptions", >+ searchable: false, >+ orderable: true, >+ render: function (data, type, row, meta) { >+ return row.subscriptions.length >+ ? '<a href="/cgi-bin/koha/serials/serials-search.pl?bookseller_filter=' + >+ row.name + >+ "&searched=1" + >+ '" class="show">' + >+ escape_str( >+ `${row.subscriptions.length} subscription(s)` >+ ) + >+ "</a>" >+ : escape_str(__("No subscriptions")); >+ }, >+ }, >+ ]; >+ }, >+ }, >+ components: { flatPickr, Toolbar, ToolbarButton, KohaTable }, >+ name: "VendorList", >+ emits: ["select-vendor", "close"], >+}; >+</script> >+ >+<style scoped> >+.filters > label[for="by_mine_filter"], >+.filters > input[type="checkbox"], >+.filters > input[type="button"] { >+ margin-left: 1rem; >+} >+</style> >diff --git a/koha-tmpl/intranet-tmpl/prog/js/vue/fetch/acquisition-api-client.js b/koha-tmpl/intranet-tmpl/prog/js/vue/fetch/acquisition-api-client.js >index 154515fd3eb..74e7006316b 100644 >--- a/koha-tmpl/intranet-tmpl/prog/js/vue/fetch/acquisition-api-client.js >+++ b/koha-tmpl/intranet-tmpl/prog/js/vue/fetch/acquisition-api-client.js >@@ -9,15 +9,46 @@ export class AcquisitionAPIClient extends HttpClient { > > get vendors() { > return { >+ get: id => >+ this.get({ >+ endpoint: "vendors/" + id, >+ headers: { >+ "x-koha-embed": "aliases", >+ }, >+ }), > getAll: (query, params) => > this.getAll({ > endpoint: "vendors", > query, > params: { _order_by: "name", ...params }, > headers: { >- "x-koha-embed": "aliases", >+ "x-koha-embed": "aliases,baskets", > }, > }), >+ delete: id => >+ this.delete({ >+ endpoint: "vendors/" + id, >+ }), >+ create: vendor => >+ this.post({ >+ endpoint: "vendors", >+ body: vendor, >+ }), >+ update: (vendor, id) => >+ this.put({ >+ endpoint: "vendors/" + id, >+ body: vendor, >+ }), >+ count: (query = {}) => >+ this.count({ >+ endpoint: >+ "vendors?" + >+ new URLSearchParams({ >+ _page: 1, >+ _per_page: 1, >+ ...(query && { q: JSON.stringify(query) }), >+ }), >+ }), > }; > } > } >diff --git a/koha-tmpl/intranet-tmpl/prog/js/vue/modules/vendors.ts b/koha-tmpl/intranet-tmpl/prog/js/vue/modules/vendors.ts >new file mode 100644 >index 00000000000..26e61adf75f >--- /dev/null >+++ b/koha-tmpl/intranet-tmpl/prog/js/vue/modules/vendors.ts >@@ -0,0 +1,62 @@ >+import { createApp } from "vue"; >+import { createWebHistory, createRouter } from "vue-router"; >+import { createPinia } from "pinia"; >+ >+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"; >+ >+library.add(faPlus, faMinus, faPencil, faTrash, faSpinner); >+ >+import App from "../components/Vendors/Main.vue"; >+ >+import { routes as routesDef } from "../routes/vendors"; >+ >+import { useMainStore } from "../stores/main"; >+import { useVendorStore } from "../stores/vendors"; >+import { useAVStore } from "../stores/authorised-values"; >+import { useNavigationStore } from "../stores/navigation"; >+import i18n from "../i18n"; >+ >+const pinia = createPinia(); >+ >+const mainStore = useMainStore(pinia); >+const AVStore = useAVStore(pinia); >+const navigationStore = useNavigationStore(pinia); >+const routes = navigationStore.setRoutes(routesDef); >+ >+const router = createRouter({ >+ history: createWebHistory(), >+ linkActiveClass: "current", >+ routes, >+}); >+ >+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("vendorStore", useVendorStore(pinia)); >+app.provide("mainStore", mainStore); >+app.provide("AVStore", AVStore); >+app.provide("navigationStore", navigationStore); >+ >+app.mount("#__vendors"); >+ >+const { removeMessages } = mainStore; >+router.beforeEach((to, from) => { >+ 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/vendors.js b/koha-tmpl/intranet-tmpl/prog/js/vue/routes/vendors.js >new file mode 100644 >index 00000000000..8a2908e57cb >--- /dev/null >+++ b/koha-tmpl/intranet-tmpl/prog/js/vue/routes/vendors.js >@@ -0,0 +1,43 @@ >+import { markRaw } from "vue"; >+ >+import Home from "../components/Vendors/Home.vue"; >+import VendorList from "../components/Vendors/VendorList.vue"; >+import VendorShow from "../components/Vendors/VendorShow.vue"; >+ >+import { $__ } from "../i18n"; >+ >+export const routes = [ >+ { >+ path: "/cgi-bin/koha/acqui/booksellers.pl", >+ is_default: true, >+ is_base: true, >+ title: $__("Vendors"), >+ children: [ >+ { >+ path: "", >+ name: "Home", >+ component: markRaw(Home), >+ is_navigation_item: false, >+ }, >+ { >+ path: "/cgi-bin/koha/vendors", >+ title: $__("Vendor list"), >+ icon: "fa fa-check-circle", >+ is_end_node: true, >+ children: [ >+ { >+ path: "", >+ name: "VendorList", >+ component: markRaw(VendorList), >+ }, >+ { >+ path: ":vendor_id", >+ name: "VendorShow", >+ component: markRaw(VendorShow), >+ title: $__("Show vendor"), >+ }, >+ ], >+ }, >+ ], >+ }, >+]; >diff --git a/koha-tmpl/intranet-tmpl/prog/js/vue/stores/vendors.js b/koha-tmpl/intranet-tmpl/prog/js/vue/stores/vendors.js >index f6efa8754ea..34b3351af89 100644 >--- a/koha-tmpl/intranet-tmpl/prog/js/vue/stores/vendors.js >+++ b/koha-tmpl/intranet-tmpl/prog/js/vue/stores/vendors.js >@@ -3,6 +3,12 @@ import { defineStore } from "pinia"; > export const useVendorStore = defineStore("vendors", { > state: () => ({ > vendors: [], >- config: { settings: {} }, >+ currencies: [], >+ gstValues: [], >+ config: { >+ settings: { >+ edifact: false, >+ }, >+ }, > }), > }); >diff --git a/rspack.config.js b/rspack.config.js >index 351e60d2d64..842e754e72f 100644 >--- a/rspack.config.js >+++ b/rspack.config.js >@@ -14,6 +14,7 @@ module.exports = [ > "./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", >+ vendors: "./koha-tmpl/intranet-tmpl/prog/js/vue/modules/vendors.ts", > islands: "./koha-tmpl/intranet-tmpl/prog/js/vue/modules/islands.ts", > }, > output: { >diff --git a/webpack.config.js b/webpack.config.js >index 09d210be790..620bc7247ab 100644 >--- a/webpack.config.js >+++ b/webpack.config.js >@@ -10,6 +10,7 @@ module.exports = { > "./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", >+ vendors: "./koha-tmpl/intranet-tmpl/prog/js/vue/modules/vendors.ts", > }, > output: { > filename: "[name].js", >-- >2.48.1
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 38010
:
174119
|
174120
|
174121
|
174122
|
174123
|
174124
|
174125
|
174126
|
174128
|
174129
|
174130
|
174131
|
174132
|
174133
|
174134
|
174135
|
174136
|
174137
|
174138
|
174139
|
174140
|
174141
|
174142
|
174143
|
174144
|
174145
|
174146
|
174147
|
174148
|
174151
|
174152
|
174153
|
174154
|
174155
|
174156
|
174157
|
174158
|
174159
|
174160
|
174161
|
174162
|
174163
|
174164
|
174165
|
174166
|
174167
|
174168
|
174169
|
174170
|
174171
|
174172
|
174173
|
174174
|
174175
|
174176
|
174177
|
174178
|
174179
|
174194
|
174196
|
174197
|
174198
|
174199
|
174200
|
174201
|
174202
|
174203
|
174204
|
174205
|
174206
|
174207
|
174208
|
174209
|
174210
|
174211
|
174212
|
174213
|
174214
|
174215
|
174216
|
174217
|
174218
|
174220
|
174221
|
174222
|
174223
|
174224
|
174225
|
174226
|
174248
|
174266
|
174267
|
174269
|
174270
|
174273
|
174327
|
174328
|
174329
|
174330
|
174331
|
174332
|
174333
|
174334
|
174335
|
174336
|
174337
|
174338
|
174339
|
174340
|
174341
|
174342
|
174343
|
174344
|
174345
|
174346
|
174347
|
174348
|
174349
|
174350
|
174351
|
174352
|
174353
|
174354
|
174355
|
174356
|
174357
|
174358
|
174359
|
174360
|
174603
|
175098
|
175099
|
175100
|
175101
|
175102
|
175103
|
175104
|
175105
|
175106
|
175107
|
175108
|
175109
|
175110
|
175111
|
175112
|
175113
|
175114
|
175115
|
175116
|
175117
|
175118
|
175119
|
175120
|
175121
|
175122
|
175123
|
175124
|
175125
|
175126
|
175127
|
175128
|
175129
|
175130
|
175131
|
175133
|
175134
|
175135
|
175136
|
175137
|
175167
|
175168
|
175170
|
175240
|
175241
|
175242
|
175243
|
175248
|
175249
|
175266
|
175791
|
175799
|
176547
| 178182 |
178183
|
178184
|
178185
|
178186
|
178187
|
178188
|
178189
|
178190
|
178191
|
178192
|
178193
|
178194
|
178195
|
178196
|
178197
|
178198
|
178199
|
178200
|
178201
|
178202
|
178203
|
178204
|
178205
|
178206
|
178207
|
178208
|
178209
|
178210
|
178211
|
178212
|
178213
|
178214
|
178215
|
178216
|
178217
|
178218
|
178219
|
178220
|
178221
|
178222
|
178223
|
178224
|
178225
|
178226
|
178227
|
178228
|
178229
|
178230
|
178231
|
178232
|
178233
|
178234
|
178235
|
178236
|
178237
|
178238
|
178239
|
178240
|
178241
|
178242