Bug 38201 - VueJS architecture rethink
Summary: VueJS architecture rethink
Status: Pushed to main
Alias: None
Product: Koha
Classification: Unclassified
Component: Architecture, internals, and plumbing (show other bugs)
Version: Main
Hardware: All All
: P5 - low enhancement
Assignee: Matt Blenkinsop
QA Contact: Jonathan Druart
URL: https://github.com/openfifth/koha/tre...
Keywords:
: 39575 (view as bug list)
Depends on: 38446 40483 40512 40809
Blocks: 37893 38311 39224 39320 39571 40878
  Show dependency treegraph
 
Reported: 2024-10-18 08:21 UTC by Pedro Amorim
Modified: 2025-10-02 17:59 UTC (History)
13 users (show)

See Also:
GIT URL:
Change sponsored?: ---
Patch complexity: ---
Documentation contact:
Documentation submission:
Text to go in the release notes:
The idea behind this bug was to introduce a framework for building Vue applications and components that would allow a developer to make use of pre-existing components and logic, rather than having to write everything from scratch. Currently in Koha, we have a lot of bespoke logic for each different form/display page as well as a lot of repeated code. This can make regressions more likely and reduce code consistency. To address this, we have introduced standardised components for rendering form elements (e.g. inputs, selects) and displaying data, as well as a standardised ‘list’ component. This means that each new Vue module can be built very quickly without the need to write out all the HTML structure and logic for creating a form/display page - the developer can simply access the pre-written logic in the framework to do the heavy lifting for them. The FormElement and ShowElement components are at the core of this work, as they render the different input and display options in a standardised manner. These are made use of by ResourceFormSave, ResourceShow and ResourceList which act as generic components that can be used by the developer to handle any Koha data type. To prove this, all the existing Vue modules (ERM, Preservation, Record Resources and Vendors) have been migrated to use it. A new suite of cypress tests has been written to verify the functionality as well as catch regressions and part of this is introducing component testing into Koha for any future Vue work that may need it. Moving forwards, the aim would be that new modules are built using this framework. It is important to note that the framework is not restrictive - it is possible to inject bespoke components directly into FormElement and ShowElement where there are particularly niche requirements. However, the goal is that if the developer feels that there could be a need for that requirement in future for someone else, then the goal should be to expand the framework to support it so that all can benefit. We have documented this through the use of JSDoc in base-resource.js, as well as with an example SkeletonResource.vue to show how it should be used. There are also the live examples in the modules mentioned above.
Version(s) released in:
25.11.00
Circulation function:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Pedro Amorim 2024-10-18 08:21:50 UTC
The goal is to streamline and provide a standard to how a regular CRUD component is implemented, instead of having to implement everything every time a new CRUD is required.
Comment 1 Pedro Amorim 2024-10-18 08:26:04 UTC
Have a WIP on a branch at the moment, for discussion.
Comment 2 Pedro Amorim 2024-10-18 08:35:17 UTC
Bug 37301 is the first step. The idea here is to go one step furhter.
To have all CRUD forms be rendered dynamically from a list of resource attributes, instead of having to be implemented every time for every CRUD.
Tables to be rendered dynamically from the same list of resource attributes, instead of having to be implemented every time for every CRUD.
This would greatly ease future components development, and ensure further consistency and less bugs by having common overlapping code DRY.
Have one single way of rendering an AV dropdown on a form, have one single way of rendering a boolean input on a form, and so on.
Comment 3 Pedro Amorim 2024-10-18 09:13:11 UTC
Chatting with Matt, this should likely be based on bug 37930.
Comment 4 Jonathan Druart 2025-01-30 15:12:27 UTC
1. I think this is problematic for translatability:
+                    {{ $__("Remove this %s").format(resourceName) }}</a

+            {{ $__("Add new %s").format(resourceName) }}</a

+            $__("There are no %s created yet").format(resourceName)

2.
http://localhost:8081/cgi-bin/koha/preservation/trains/1
 a. Toolbar button "Add items" is not correctly styled: https://snipboard.io/W3Be1Y.jpg
 b. warning in the console:
[Vue warn]: Property "class" was accessed during render but is not defined on instance. 
  at <Toolbar key=0 to= 
Object { name: "TrainsFormAddItem", params: {…} }
 icon="plus"  ... > 

3. Create a train, then delete it from the list view
 a. The table is not refreshed and the train is still displayed
 b. warning in the console:
[Vue Router warn]: Discarded invalid param(s) "train_item_id" when navigating. See https://github.com/vuejs/router/blob/main/packages/router/CHANGELOG.md#414-2022-08-22 for more details.

4. AgreementResource.vue
+                                nameLC: __("user"),
+                                nameUC: __("Agreement user"),
+                                namePL: __("users"),


LC, UC, PL? Can it be verbose so we don't need to guess what it means?

5. Update users for an agreement:
https://snipboard.io/FywJhr.jpg
Change one field and all are updated, wrong binding here.

Oops, it actually happens for other linked resources.

See also the duplication of the error there: https://snipboard.io/jmvBbL.jpg

6.
(In reply to Pedro Amorim from comment #3)
> Chatting with Matt, this should likely be based on bug 37930.

It is currently not.
And bugs encountered on bug 37301 are fixed here. Can we have a clear tree?

7. Is there a TODO list? It seems that other components need adjustment to use this change (the remaining FormAdd, List, Show components). What's missing to make it ready for testing/QA and push?

8. With the additional abstractions everything is harder to read IMO, we should add documentation, at least for the "Base" components.

9. There is way too many changes for a single bug report, please split into smaller chunks next time. It's really hard to follow.

10. Cypress tests are failing:
       Spec                                              Tests  Passing  Failing
 │ ✖  AdditionalFields_spec.ts                 02:22       12        2       10        
 │ ✖  InfiniteScrollSelect_spec.ts             00:56        4        -        4        
 │ ✖  Admin/RecordSources_spec.ts              00:51        5        1        4        
 │ ✖  ERM/Agreements_spec.ts                   01:06        5        -        5        
 │ ✖  ERM/Licenses_spec.ts                     01:04        5        -        5
 │ ✖  ERM/UserRoles_spec.ts                    00:15        1        -        1        

11. I cannot save an agreement with a license
400 - Object { message: "Expected string - got null.", path: "/body/agreement_licenses/0/status" }

====

Overall I think the idea is good but it adds some "magic" that won't help new developer to grasp our VueJS code. I feel like you have been too far, and things won't be as easy to maintain as you think.

This is something weird:
 310                         {
 311                             name: "ended_on",
 312                             type: "component",
 313                             label: __("End date"),
 314                             componentPath: "./FlatPickrWrapper.vue",
 315                             required: false,
 316                             props: {
 317                                 id: {
 318                                     type: "string",
 319                                     value: "ended_on_",
 320                                     indexRequired: true,
 321                                 },
 322                             },
 323                         },

I expect more to see something like "type: date", and not a component path to the flatpickr component.

Same for this:
 122                 {
 123                     name: "vendor_id",
 124                     type: "component",
 125                     label: __("Vendor"),
 126                     showElement: {
 127                         type: "text",
 128                         value: "vendor.name",
 129                         link: {
 130                             href: "/cgi-bin/koha/acqui/supplier.pl",
 131                             params: {
 132                                 bookseller_id: "vendor_id",
 133                             },
 134                         },
 135                     },
 136                     componentPath: "./FormSelectVendors.vue",
 137                     props: {
 138                         id: {
 139                             type: "string",
 140                             value: "agreement_id_",
 141                             indexRequired: true,
 142                         },
 143                     },
 144                 },

This should be shorter, you don't want to duplicate this whenever a component will be linked to a vendor.
It could be "vendor_id is a vendor, and the value for this component is vendor.name, and is required". The other info will be copy/pasted, and increase the risk of regressions, inconsistencies, etc.



The 500 lines of definition of the agreement (resourceAttrs in AgreementResource.vue) are not trivial to understand, neither to know what does what.
I think we could make it a bit more readable by moving some redundant code that is in there: the relationshipWidget are defined in LicenseResource and AgreementResource for instance.

We should make sure the order of the attributes are always the same (how??), otherwise it get messy, for instance:
 339                             name: "notes",
 340                             required: false,
 341                             type: "text",
 342                             label: __("Notes"),

vs

 421                             name: "role",
 422                             type: "select",
 423                             label: __("Role"),
 424                             avCat: "av_user_roles",
 425                             required: true,



This pattern looks wrong:
 482                         resourceRelationships: {
 483                             type: "resourceProperty",
 484                             resourceProperty: "agreement_licenses",
 485                         },

But I don't have anything else to suggest now.


Sorry for the messy notes...
Comment 5 Pedro Amorim 2025-01-30 16:08:34 UTC
Thank you for your time here, Joubu. Your feedback is obviously very important and valuable.
We are going to fix the bugs you have raised and are still finishing this up, some things still require polish (some of this code was written as recently as today). Having said that, we're very grateful you've had the chance to review it right now.

(In reply to Jonathan Druart from comment #4)
> 
> 8. With the additional abstractions everything is harder to read IMO, we
> should add documentation, at least for the "Base" components.

Yes, we plan to have documentation here but we've not gotten to that point yet.
It will be great to have Koha developer documentation once we have this established pattern in place, to help guide new developers on how to setup their own VueJS module.

(In reply to Jonathan Druart from comment #4)
> 
> Overall I think the idea is good but it adds some "magic" that won't help
> new developer to grasp our VueJS code. I feel like you have been too far,
> and things won't be as easy to maintain as you think.

I'm really happy to read that you think the idea is good!
In terms of maintainability, I have to disagree. Particularly developing bug 37893 (which is a new full VueJS module), as a module implementer I have close to zero implementation work, as all the heavy lifting is already done for me and I have much less code that I need to write, thus much less chances of adding new buggy code.

We believe VueJS is the direction of travel in Koha development. Our goal is to ensure consistency on every existing and future VueJS module, something that does not happen in the rest of (old) Koha.

We want developers going forward to invest as little time as possible in:
- Implementing the 'create' routine of a 'Resource'
- Implementing the 'delete' routine of a 'Resource'
- Implementing the 'edit' routine of a 'Resource'
- Implementing the 'show' (read) routine of a 'Resource'
- Implementing a relationship form element with relational fields
- Implementing a relationship form dropdown element
- Implementing a 'date' form input element
- Implementing a toolbar for their module
- Implementing a table
- etc

All these things should only be implemented ONCE, and maintained in a single place. This work is not there yet but that's our goal. I agree that some of the 'magic' could be less obscure, but this is not final (nothing ever is) and we expect to iterate on this long after it's been pushed to core.
We want developers to invest time in the actual features their module should have. Not all the boilerplate.
By having all the modules share the same base components, we ensure far less bugs and establish a new coding paradigm that will encourage developers to implement new functionality at the 'Base' level whenever they need to do so, in a way that every other developer can also make use of it, instead of doing these things on their own specific module form, button, etc.

Thanks again, we'll come back when this is ready for review.
Comment 6 David Cook 2025-01-31 01:44:24 UTC
(In reply to Pedro Amorim from comment #5)
> All these things should only be implemented ONCE, and maintained in a single
> place. This work is not there yet but that's our goal. I agree that some of
> the 'magic' could be less obscure, but this is not final (nothing ever is)
> and we expect to iterate on this long after it's been pushed to core.
> We want developers to invest time in the actual features their module should
> have. Not all the boilerplate.
> By having all the modules share the same base components, we ensure far less
> bugs and establish a new coding paradigm that will encourage developers to
> implement new functionality at the 'Base' level whenever they need to do so,
> in a way that every other developer can also make use of it, instead of
> doing these things on their own specific module form, button, etc.

+100
Comment 7 Jonathan Druart 2025-02-03 11:54:27 UTC
(In reply to David Cook from comment #6)
> +100

+100 to DRY? Yes I think we all agree on that :D
Comment 8 Matt Blenkinsop 2025-02-14 13:45:37 UTC
(In reply to Jonathan Druart from comment #4)
> 1. I think this is problematic for translatability:
> +                    {{ $__("Remove this %s").format(resourceName) }}</a
> 
> +            {{ $__("Add new %s").format(resourceName) }}</a
> 
> +            $__("There are no %s created yet").format(resourceName)

We're now passing an i18n object with translated strings from the resource
 
> 2.
> http://localhost:8081/cgi-bin/koha/preservation/trains/1
>  a. Toolbar button "Add items" is not correctly styled:
> https://snipboard.io/W3Be1Y.jpg
>  b. warning in the console:
> [Vue warn]: Property "class" was accessed during render but is not defined
> on instance. 
>   at <Toolbar key=0 to= 
> Object { name: "TrainsFormAddItem", params: {…} }
>  icon="plus"  ... > 

This should be fixed now that the 'class' prop is gone from the toolbar

> 3. Create a train, then delete it from the list view
>  a. The table is not refreshed and the train is still displayed
>  b. warning in the console:
> [Vue Router warn]: Discarded invalid param(s) "train_item_id" when
> navigating. See
> https://github.com/vuejs/router/blob/main/packages/router/CHANGELOG.md#414-
> 2022-08-22 for more details.

This should also now be fixed, there was an issue with the reference to the datatable object


> 4. AgreementResource.vue
> +                                nameLC: __("user"),
> +                                nameUC: __("Agreement user"),
> +                                namePL: __("users"),
> 
> 
> LC, UC, PL? Can it be verbose so we don't need to guess what it means?

This is done

> 5. Update users for an agreement:
> https://snipboard.io/FywJhr.jpg
> Change one field and all are updated, wrong binding here.
> 
> Oops, it actually happens for other linked resources.
> 
> See also the duplication of the error there: https://snipboard.io/jmvBbL.jpg

This has been resolved, linked resources update independently
 
> 6.
> (In reply to Pedro Amorim from comment #3)
> > Chatting with Matt, this should likely be based on bug 37930.
> 
> It is currently not.
> And bugs encountered on bug 37301 are fixed here. Can we have a clear tree?

This isn't currently based on that work, 37930 is still in discussion so we could do with a clear direction on that bug before integrating it here, otherwise we may have to make a lot of changes depending on the outcome of 37930
 
> 7. Is there a TODO list? It seems that other components need adjustment to
> use this change (the remaining FormAdd, List, Show components). What's
> missing to make it ready for testing/QA and push?

Nothing official, there are a few nice to haves that we have noted for the future but all the critical stuff is included now (as far as we've spotted, see if you have any other ideas). We still need to migrate Preservation to this work. There are also some components that we would like to remove in the future like Agreement*Display.vue and also transferring FormSelectVendors to FormRelationshipSelect but these are possibly out of scope for now and could be follow-ups. Usage Statistics is probably also out of scope for this as it has some very specific functionality, same with the EBSCO components
 
> 8. With the additional abstractions everything is harder to read IMO, we
> should add documentation, at least for the "Base" components.

We've got JSDocs on the methods, we were considering adding a 'SkeletonResource.vue' component as an example like we have for atomic updates
 
> 9. There is way too many changes for a single bug report, please split into
> smaller chunks next time. It's really hard to follow.
> 
> 10. Cypress tests are failing:
>        Spec                                              Tests  Passing 
> Failing
>  │ ✖  AdditionalFields_spec.ts                 02:22       12        2      
> 10        
>  │ ✖  InfiniteScrollSelect_spec.ts             00:56        4        -      
> 4        
>  │ ✖  Admin/RecordSources_spec.ts              00:51        5        1      
> 4        
>  │ ✖  ERM/Agreements_spec.ts                   01:06        5        -      
> 5        
>  │ ✖  ERM/Licenses_spec.ts                     01:04        5        -      
> 5
>  │ ✖  ERM/UserRoles_spec.ts                    00:15        1        -      
> 1        

We haven't updated the tests yet while its still WIP, I was considering writing new tests to check all the different abstracted features 


> 11. I cannot save an agreement with a license
> 400 - Object { message: "Expected string - got null.", path:
> "/body/agreement_licenses/0/status" }

I believe this is also fixed 
 
> Overall I think the idea is good but it adds some "magic" that won't help
> new developer to grasp our VueJS code. I feel like you have been too far,
> and things won't be as easy to maintain as you think.
> 
> This is something weird:
>  310                         {
>  311                             name: "ended_on",
>  312                             type: "component",
>  313                             label: __("End date"),
>  314                             componentPath: "./FlatPickrWrapper.vue",
>  315                             required: false,
>  316                             props: {
>  317                                 id: {
>  318                                     type: "string",
>  319                                     value: "ended_on_",
>  320                                     indexRequired: true,
>  321                                 },
>  322                             },
>  323                         },
> 
> I expect more to see something like "type: date", and not a component path
> to the flatpickr component.

This is done, same for vendors

> 
> The 500 lines of definition of the agreement (resourceAttrs in
> AgreementResource.vue) are not trivial to understand, neither to know what
> does what.
> I think we could make it a bit more readable by moving some redundant code
> that is in there: the relationshipWidget are defined in LicenseResource and
> AgreementResource for instance.
> 
> We should make sure the order of the attributes are always the same (how??),
> otherwise it get messy, for instance:
>  339                             name: "notes",
>  340                             required: false,
>  341                             type: "text",
>  342                             label: __("Notes"),
> 
> vs
> 
>  421                             name: "role",
>  422                             type: "select",
>  423                             label: __("Role"),
>  424                             avCat: "av_user_roles",
>  425                             required: true,
> 

This would probably need a QA script check?
> 
> This pattern looks wrong:
>  482                         resourceRelationships: {
>  483                             type: "resourceProperty",
>  484                             resourceProperty: "agreement_licenses",
>  485                         },

This has also been fixed, its is now just one line with a key of 'resourceProperty'
Comment 9 Esther Melander 2025-04-08 16:07:28 UTC
*** Bug 39575 has been marked as a duplicate of this bug. ***
Comment 10 Jonathan Druart 2025-06-24 10:03:19 UTC
We need a solution for bug 34417 here.
Comment 11 Pedro Amorim 2025-06-24 10:27:56 UTC
(In reply to Jonathan Druart from comment #10)
> We need a solution for bug 34417 here.

Yes, we should use the resource's nameAttr.

It's how we get the resource's name when deleting:
https://github.com/openfifth/koha/blob/new_bug_38201/koha-tmpl/intranet-tmpl/prog/js/vue/composables/base-resource.js#L406

It should also be how we get the resource's name when showing on the breadcrumb (and anywhere else this is needed).
Comment 12 Matt Blenkinsop 2025-06-24 13:24:05 UTC
Having a look now
Comment 13 Michaela Sieber 2025-07-31 08:06:23 UTC
Tested on a sandbox with a user that is NOT a superlibrarian.

403 request returns {"error":"Authorization failure. Missing required permission(s).","required_permissions":{"parameters":"manage_additional_fields"}}

But there is no configuration for any additional fields in this sandbox.

See also Bug 38446
Comment 14 Michaela Sieber 2025-07-31 17:20:11 UTC
In General:

- performance / loading a page sometimes needs several seconds, altough there are only a few records to diplay, e.g. 

- Layout / wasted space : more than 50 % of the screen is not used because there is only one column. 
Especially if you compare the vendors details page today this becomes obvious.


Preservation:

- the filters on top of the trains result list look weird, to much space between the radio buttons


Vendors:
- it is not possible to search for vendors with staff users that have not full acq module permissions , disable for example the Manage budgets (period_manage) permission
Comment 15 Michaela Sieber 2025-09-23 16:36:28 UTC
Test the latest branch
Comment 16 Michaela Sieber 2025-09-23 16:39:35 UTC
(In reply to Michaela Sieber from comment #14)
> In General:
> 
> - performance / loading a page sometimes needs several seconds, altough
> there are only a few records to diplay, e.g. 
> 
> - Layout / wasted space : more than 50 % of the screen is not used because
> there is only one column. 
> Especially if you compare the vendors details page today this becomes
> obvious.
> 
> 
> Preservation:
> 
> - the filters on top of the trains result list look weird, to much space
> between the radio buttons
> 
> 
> Vendors:
> - it is not possible to search for vendors with staff users that have not
> full acq module permissions , disable for example the Manage budgets
> (period_manage) permission


In the latest version all those things are fixed and I sign-off.
Matt will add my Sign-off lines later
Comment 17 Matt Blenkinsop 2025-09-24 09:47:33 UTC
Sign-off lines added
Comment 18 Jonathan Druart 2025-09-26 03:56:05 UTC
we will need the merge request linked with misc4dev's #94 to run component tests

https://gitlab.com/koha-community/koha-misc4dev/-/issues/94
Comment 19 Jonathan Druart 2025-10-02 13:39:08 UTC
Passing QA the following tree: 

76e41ab2052 Bug 38201: Fix Dataproviders_spec.ts
7db74aec773 Bug 38201: Remove DT warnings from Cypress tests
a97cd037032 Bug 38201: Remove discarded params error from DataProviders
06fee97480a Bug 38201: Avoid parseFloat when value is an empty string
3c288270f16 Bug 38201: Improve Agreements/Edit tests
006b5a9bea0 Bug 38201: Add missing newlines at end of file
4a209284ea4 Bug 38201: Remove cy.wait(500)
82ca5e9d0e3 Bug 38201: Do not duplicated CSS rules
3d3b4ba1175 Bug 38201: Fix radio inputs
26f494a9961 Bug 38201: Cypress fixes
d70062ae662 Bug 38201: Make all framework tests db independent
00d1128c9a4 Bug 38201: (follow-up) Fix JS warning for deliverytime on the Vendor edit for
76e206f9b3d Bug 38201: Fix number fields in the vendor form
d784d64bde8 Bug 38201: Fix vendor tax rate
ad5e7016725 Bug 38201: Cypress fixes
7746b4601c3 Bug 38201: Assign 'show' events dynamically
ca8931046f0 Bug 38201: Update unit tests for split pane mode
392faedfb1d Bug 38201: Allow for multiple split screen panels
19e5c34c148 Bug 38201: Restore subscriptions and allow appendToShow to ignore panes where required
737cf3b7c4f Bug 38201: Introduce a split pane view to ResourceShow
378bc2e62d5 Bug 38201: Pre-select the 'All' option on the Trains list
1cd8931745c Bug 38201: Fix JS warning for deliverytime on the Vendor edit form
ce30ed33273 Bug 38201: Load Cypress components - componentPath
54dc2de53d4 Bug 38201: Move cypress components under t/cypress
500bc02316e Bug 38201: Fix the spacing of the Trains list filters
5aa8deabb0a Bug 38201: Restore format_date to vendor resource
08b72de894b Bug 38201: Remove redundant code from base-resource.js and resolve additionalFilter error
9148e0b6156 Bug 38201: Add component tests for useBaseResource
de7db1a3ce7 Bug 38201: Add component tests for FormElement
f3f1d8afdf5 Bug 38201: Add disabled attribute to all FormElements
7d42d87e489 Bug 38201: Use Vue alias for imports
aa47b19ac53 Bug 38201: Mock the router for component testing
967b49d481d Bug 38201: install i18n on mount for component testing
4733b57270c Bug 38201: Remove ARM dependency from package.json
bf0bac66512 Bug 38201: Add framework tests for ResourceFormSave
181d9f22724 Bug 38201: Add component tests for ShowElement
4d8d88fa0dc Bug 38201: Address radio type issues in ShowElemeent
06e8d5d05eb Bug 38201: Add VueFramework cypress tests
33822db4a92 Bug 38201: DRY out cypress object deletion
e7dc50d5465 Bug 38201: Add cypress tests for breadcrumbs
e972c090c73 Bug 38201: Add radio column definition to getTableColumns
d7ed1dd30fc Bug 38201: Rebase for changes in bug 40483 (vendor alias searching)
d9e6e23cf71 Bug 38201: Add breadcrumb data where required
e13352e76a1 Bug 38201: Rename table variable filters due to conflict with DT properties
082c9452f82 Bug 38201: Element fields are already grouped in an elements directory
c103d2ed024 Bug 38201: Group table related config options together
8fc10c76492 Bug 38201: Fix cypress tests
8cef8e9ebe0 Bug 38201: Group components in the resourceConfig
2e2ea537e3a Bug 38201: Rename resourceToAddOrEdit to resourceToSave for consistency
64d3ba6fcbd Bug 38201: Rename instancedResource to resourceConfig in base-resource.js
babb9a63d22 Bug 38201: Add further context to embed docs
31d46bc0573 Bug 38201: Add an example SkeletonResource.vue
4b6ea49944b Bug 38201: Fix refresh regression in agreements list filters
4e02c6c858a Bug 38201: Breadcrumb tidy up
af48fad00db Bug 38201: Allow edit form breadcrumb to be dynamic
561496cec2b Bug 38201: Rename onSubmit to onFormSave
da7c5f90768 Bug 38201: Tidy up missed variable in base-resource
26ad8255905 Bug 38201: Add JSDoc for the instancedResource passed to base-resource
cae9b22414b Bug 38201: Group methods in base-resource.js
1dc71deb582 Bug 38201: Fix display of packages on 'show title' - EBSCO
eb91421a7de Bug 38201: Restore access to the preservation module when not configured
6adf5f1c8b2 Bug 38201: Do not freeze the app if ERMModule is turned off
b5772fc5a9e Bug 38201: Restore dropdown buttons to vendor show
9d5307cd1b1 Bug 38201: Fix cypress tests
985a28e64f4 Bug 38201: Fix broken action buttons on vendor list
6f538c45933 Bug 38201: Fix duplicate IDs on vendor form
631ff6228dc Bug 38201: Fix EBSCO pages
d8ab62d30ae Bug 38201: Fix UI issue in titles show
eef7816ab0e Bug 38201: Fix console warnings for user roles
a1ce198fd3e Bug 38201: Prevent 'no resources' message showing in relationshipWidget if resources do exist
ffb86109598 Bug 38201: Rename the '@k' alias to koha-vue
0efdcfbd8e3 Bug 38201: Do not export $__ from the base resource
6016167502d Bug 38201: Fix missing select labels when adding items to a train
c1470bc8146 Bug 38201: DT - Remove 'autoWidth: false'
f9ad9bc7775 Bug 38201: Remove JS warning
36eaf32970f Bug 38201: Avoid redundant regex test when replacing breadcrumb placeholders
13578d3c322 Bug 38201: Fix composition API migration omissions
e054273e983 Bug 38201: Allow the breadcrumb to be dynamic in the show component
e3b72d6a6c0 Bug 38201: Remove console warning for readonly computed value
c4044b8553f Bug 38201: Move 'created' call into base-resource
5e46631ad8b Bug 38201: Add missing JSDocs to base-resource and base-element
5dba0cf28e4 Bug 38201: Add missing 'created' calls to preservation resources
cf665ae5b73 Bug 38201: Restore ERM provider filtering to the left menu
d67b7ed8d1b Bug 38201: Restore physical address in vendor show view
91a0804eeef Bug 38201: Support sticky toolbars in the framework
7dcda257abe Bug 38201: Remove duplicate 'close' link from Trains show
49a4233ed13 Bug 38201: Pre-select the 'all' option in the trains table filters
939302f3e64 Bug 38201: Allow the train items table to update when items are removed
ef542183a4f Bug 38201: Clear items added to the waiting list state once items added to train
3b52a421c44 Bug 38201: Compute appendToShow into the fieldGroupings to avoid separate logic
477498ec3ef Bug 38201: Allow modal confirmations to accept a size property
0042ee37d7f Bug 38201: Add an accordion wrapper to allow usage in ResourceShow
72ffebbf366 Bug 38201: Add a tabs wrapper to allow usage in ResourceShow
7d4979608f8 Bug 38201: Delete redundant vendors components
8ec6c7cb0d4 Bug 38201: Restore show password option to vendor interfaces
4d0181d2f26 Bug 38201: Allow field validation methods to be passed with the attribute
2dd490f2daf Bug 38201: Allow a fallbackType for av selects that have no values
37b90c10981 Bug 38201: Migrate permissions store to a composable
5ccfe8ac97a Bug 38201: Allow Kohatable to accept an array of data
2c03cd5beed Bug 38201: Add permissions logic to framework
1383bea5717 Bug 38201: Migrate vendors to the framework
cbbe2e8f998 Bug 38201: Add a radio option to ShowElement
e113d282908 Bug 38201: Convert remaining components to the composition API
20913fb26cc Bug 38201: Remove instancedResource from FormElement
9627bbae5fc Bug 38201: Re-write AV logic to match bug 37930
50120ed2fcb Bug 38201: Convert BaseElement to the composition API
0215590f92a Bug 38201: Restore refreshTemplateState functionality
d6462bf4ac7 Bug 38201: Remove optional resource props from BaseResource
2fd7bd90e4f Bug 38201: Migrate waiting lists to the composition API
8a6e6030ff0 Bug 38201: Migrate trains to the composition API
642b477b0d4 Bug 38201: Migrate record sources to the composition API
b4c5a6a32d2 Bug 38201: Migrate packages to the composition API
46cf772eda5 Bug 38201: Migrate titles to the composition API
f9837f8a8d3 Bug 38201: Migrate licenses to the composition API
cb6b7171d2e Bug 38201: Fix merge conflicts
9145e2dd90e Bug 38201: Remove redundant code
3b2f6571265 Bug 38201: Remove remaining options API blocks
52aa2c68ce9 Bug 38201: Drop extends in favour of the composition API
2a0a2c5cfd1 Bug 38201: Recursively find the parent route with a resource
6cc2f44beab Bug 38201: Remove outdated toolbar methods
1ee7b16d705 Bug 38201: Add an InputRadioElement component
c448b1d4ba3 Bug 38201: Split InputElement into text and number variants
fefd4944691 Bug 38201: Add an InputCheckboxElement component
5505be42dec Bug 38201: Add a TextareaElement component
cc04735f2c1 Bug 38201: Add an InputElement component
accf969e4b7 Bug 38201: Prevent 'Invalid Date' from displaying
8c2a2bfa669 Bug 38201: Remove additional fields from resourceAttrs
6886c31561b Bug 38201: Introduce 'hideIn' array to simplify attribute definitions
00ec42efff5 Bug 38201: Improve consistency of table columns definition
28ed7bbbe87 Bug 38201: Rename resourceListFiltersRequired
a7849f277dd Bug 38201: Fix translation tags
ff25a1de056 Bug 38201: Migrate WaitingList
3a9f89ba059 Bug 38201: Allow toolbar buttons to access component props
9a6374c1ad0 Bug 38201: Implement copy item to train modal
90c067d2825 Bug 38201: Move getResource to BaseResource
1b63ee59368 Bug 38201: Migrate Dialog to use FormElement
b21ddece9d9 Bug 38201: Migrate the train items table to appendToShow
f251b3ea371 Bug 38201: Add a afterResourceFetch hook
cb83849e270 Bug 38201: Move additionalProps to data
3f75db5039b Bug 38201: Enable custom Kohatable action buttons
1e17a3e9da4 Bug 38201: Add additional toolbar buttons to Trains
71c4b0d2ddf Bug 38201: Add missing fields to show trains
83b7989ab8f Bug 38201: Rename getFilters to getFilterValues
48836096754 Bug 38201: Rename getTableFilters to getTableFilterFormElements
b7b7d4058dd Bug 38201: Fix filter options
6eef088b7e9 Bug 38201: Add default to trains not_for_loan
d62ac15e16c Bug 38201: Add missing i18n strings for Trains
88db7cf460a Bug 38201: Correct embedded property for the toolbar
df475f8ecc2 Bug 38201: Radio FormElement - pass default FIXME/DEBUG
ad38c0ef479 Bug 38201: Add 'Filter by:' label before the filters
8f3b4a5c817 Bug 38201: Radio FormElement follow-up
76120d0bdff Bug 38201: Preservation - toolbar
7fa10e749b9 Bug 38201: Toolbar - add on click
e0bbfa2f363 Bug 38201: Preservation toolbar
99e9d29a824 Bug 38201: Move preservation
c985257f4d8 Bug 38201: Fix preservation route
49b8bc20dbb Bug 38201: Improve code
f2100b21dc7 Bug 38201: Add 'radio' support to filters
9a29c304cb3 Bug 38201: Pass type='date' for date columns
3b500a42334 Bug 38201: Add 'required' support to FormRelationshipSelect
7b6b588ee50 Bug 38201: Allow ordering of toolbar buttons
869529c4c8e Bug 38201: Extend additional toolbar buttons
cc9e21f3341 Bug 38201: Use getToolbarButtons for "show"
60f5884ae61 Bug 38201: Fix i18n
116b3ea86a6 Bug 38201: Fix UI regression caused by RelationshipSelect
9f80c93ef83 Bug 38201: Restore 'href' to table links
6bcab126422 Bug 38201: Update Cypress tests
65cd324f041 Bug 38201: Ensure all HTML ids use plural form of resource name
42c63322097 Bug 38201: Fix setWarning call in titles+packages
ae2a9974b75 Bug 38201: Delete LicensesList
9aec7344451 Bug 38201: Remove accordion display from agreements
413b84e3f61 Bug 38201: Move tableColumns logic to the List component
a0fc56e2b7f Bug 38201: Add table_settings to missing resources
6d2f8756b5f Bug 38201: Revert UsageStatistics WIP
d793ace9955 Bug 38201: 37273 compatibility rebase
41455676e3f Bug 38201: 38993 compatibility rebase
269f3cf5330 Bug 38201: Add appendToShow functionality
577d1d854ba Bug 38201: Update cypress tests
030395b7b46 Bug 38201: Fix for inverse boolean checks
5da329d2feb Bug 38201: Fix custom toolbar buttons for eholdings titles
8eae274d424 Bug 38201: Add 'id' property to FormRelationshipSelect
d6bba3337b8 Bug 38201: Add a loading tag to the patron search
c16683c8f4f Bug 38201: Fix PatronSearch
10463fb188a Bug 38201: Ensure related user roles have index
eba2f60eb9a Bug 38201: Clean-up FormElement where it's not needed
d9e270e3b41 Bug 38201: Fix index concat on FormElement
4bbdba76309 Bug 38201: DRY label in FormElement
f6195b82c91 Bug 38201: Add inheritAttrs: false
9d28ef0935c Bug 38201: Restore resourceName in ResourceList
ffc769744ad Bug 38201: Only consider length of the field.type is relationshipWidget
e01c2e962c1 Bug 38201: Check for resourceAttrs before using it
fce132a5260 Bug 38201: Add formGroupsDisplayMode to common resource props
7937d324c63 Bug 38201: Fix and add relationshipRequiredKey
6bffee8689a Bug 38201: Add allowMultipleChoices prop to FormRelationshipSelect to consider multiple relationship choices
53595e8e247 Bug 38201: Consider a 'formatForForm' resource attribute option
cf56fc02782 Bug 38201: Add optional :multiple attribute to 'select' form elements
1cb16c94ed1 Bug 38201: DRY out getTableColumns
1367935b995 Bug 38201: Create a vendor type field
ed79e78eab5 Bug 38201: Create a date type field for FlatPickr
210f11fb869 Bug 38201: Add JSDoc comments to BaseResource
fcdcd18ba35 Bug 38201: Move filters to a slot and dynamically assign resource component props"
8abf7196ce0 Bug 38201: Remove unused component imports
b433d633a4b Bug 38201: Add group accordion mode
8efa5ea1374 Bug 38201: Add type 'number' to FormElement
7baf32a4b6d Bug 38201: Use resourceAttrs to generate new objects
4265a6e0075 Bug 38201: Move component routing to BaseResource
70770135b5e Bug 38201: Move additional fields logic to the element component tree
812484dd856 Bug 38201: Prevent ResourceShow from showing groups with no data
8ef80faa915 Bug 38201: Fix casing in formadd
8808ea26f12 Bug 38201: Improve terminology and variable naming
c579622c82a Bug 38201: Allow for form display groups as tabs
c92c0e89f8c Bug 38201: DRY assignAVs
a741bf484dc Bug 38201: Migrate local packages
8af0ec8530e Bug 38201: Add a ToolTip component
c0a50174a55 Bug 38201: DRY required in FormElement
4f80f955cef Bug 38201: Prevent form fields from being bound to multiple objects
91458167cab Bug 38201: Make resource naming verbose
ca1c257ba94 Bug 38201: Introduce RelationshipTableDisplay for nested Kohatables
035ccedd105 Bug 38201: Migrate local titles for list and formadd
cb423878121 Bug 38201: Migrate UserRoles and Documents to RelationshipWidget
4bd1d676684 Bug 38201: Remove 'relationship' type and replace with groupings
8381b47369d Bug 38201: Allow text/textarea placeholder
3c3a3fbfe25 Bug 38201: Fix translatability of RelationshipWidget
8ecd537f672 Bug 38201: Convert 'action' to 'routeAction'
a6669ec141e Bug 38201: Migrate AgreementRelationships to RelationshipWidget
8d27db12e9e Bug 38201: Fix delete resource from resourceShow
83c99a7c464 Bug 38201: Add FormRelationshipSelect
dc24434dafe Bug 38201: Abstract AgreementLicenses and AgreementPeriods
d7421ce5e61 Bug 38201: Apply new additional fields check
75708961717 Bug 38201: Migrate record sources
91669b0cfcc Bug 38201: Migrate licenses
f4f89f3232d Bug 38201: Use a defined resource path
22222c5cea1 Bug 38201: Make casing consistent
4faf9df036b Bug 38201: Allow grouping of form fields
11d99cd6d8a Bug 38201: Allow embedding of resource list
a78713af194 Bug 38201: Remove old components
bac44f44e9b Bug 38201: Add a ResourceList component
c8f981022c2 Bug 38201: Add a ResourceFormAdd component
46ffd6cf80e Bug 38201: Make a ResourceShow component
de0107844cf Bug 38201: Rebase for additional fields
bb0585499af Bug 38201: Add a BaseElement
157d6a152e8 Bug 38201: Remove old code
cd2663fbd63 Bug 38201: Add components for displaying non-standard data
2dcc1eb50a0 Bug 38201: Add a link wrapper
18794dab535 Bug 38201: Add tables to ShowElement
4a7a181d4cf Bug 38201: DRY form components
d55432b5107 Bug 38201: VueJS rework WIP
d6b7f9ff997 Bug 38201: (QA follow-up): Fix Dialog_spec.ts
06855aa59ea Bug 38201: Update cypress
07189a4533f Bug 38201: Apply changes to preservation trains
09a187a8acb Bug 38201: Apply changes to usage statistics data providers
f9a5c7a5d23 Bug 38201: Add required faicon for fontawesome compnent
b41768be363 Bug 38201: Fix: URL param needs to match attr_id
f65336e0da6 Bug 38201: Move setWarning to BaseResource
d45ef6c2fc2 Bug 38201: Apply changes to eholdings titles
c604138bdb6 Bug 38201: Restore possibility of a custom toolbar button
20077a7a038 Bug 38201: Apply changes to eHoldings local packages
4fb646a2f94 Bug 38201: Apply changes to licenses
dd6d35fc635 Bug 38201: Move table_url declaration to resource class
cbed4a787ab Bug 38201: DRY delete
123e1c61e3a Bug 38201: Get rid of e.preventDefault
82c95535f49 Bug 38201: Add goToResourceShow to BaseResource
ee9f35911e0 Bug 38201: Remove toToResource* methods to BaseResource
12ec83f09af Bug 38201: (follow-up) PoC (Continuation): Add BaseResource and AgreementResource
433406cf9c3 Bug 38201: PoC (Continuation): Add BaseResource and AgreementResource
2501fc968df Bug 38201: Rename 'type' with 'action'
327d683a36e Bug 38201: Remove methods
6b9c4a63d62 Bug 38201: [PoC] DRY ToolbarButton
Comment 20 Jonathan Druart 2025-10-02 13:40:33 UTC
QA comment:

Over the last 4 months, I have iterated with Matt on this project. We have reached a state that is highly satisfying: all existing modules written in Vue have been successfully migrated, and everything is functioning flawlessly. Test coverage has been significantly improved, making the codebase more robust and easier to maintain than before.

This patchset is a fundamental shift from our previous approach. The technical outcome is strong but I have one major concern: visibility. A core community member recently shared that they were unaware of these changes, which means that we failed at communicating. This suggests that other contributors may also lack awareness of the work done here.

If Matt and/or me leave the project, the community could face challenges in maintaining or extending this new code. Especially given the rewrite of the acquisition module that is coming next.

For me it's technically ready for inclusion, but I think broader involvement is critical now to ensure long-term sustainability.
Comment 21 Lucas Gass (lukeg) 2025-10-02 16:25:53 UTC
Pushed to main for 25.11.00
Comment 22 Tomás Cohen Arazi (tcohen) 2025-10-02 17:59:32 UTC
(In reply to Lucas Gass (lukeg) from comment #21)
> Pushed to main for 25.11.00

Great job everyone. As Jonathan said, it is now important to share info about this. I expect the newsletter to have an explanation or a blog post so we are all onboard.

I'm really happy to see this in.

Go team!