Commit Graph

27 Commits

Author SHA1 Message Date
David Cook 448419f918
Bug 43401: (QA follow-up) tweak rspack.config.js comment and fix Makefile.PL
Signed-off-by: David Cook <dcook@prosentient.com.au>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
2026-09-11 15:06:54 +00:00
Paul Derscheid 8339307961
Bug 43401: (follow-up) Note the Makefile.PL coupling in rspack.config.js
- Add a file-level comment reminding that every shipped output.path needs a
  matching 'NONE' target-map entry and cp step in Makefile.PL

Signed-off-by: Paul Derscheid <paul.derscheid@lmscloud.de>
Signed-off-by: David Cook <dcook@prosentient.com.au>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
2026-09-11 15:06:53 +00:00
Chloé Zermatten d2c575a93d
Bug 10190: Complete Vue.js rewrite of Circulation Triggers administration interface
This patch introduces a modern Vue.js-based interface for managing circulation triggers (overdue notice/status triggers), replacing the legacy Tools-based interface with a more intuitive, feature-rich administration page.

New Features

Enhanced Visibility & Navigation
- Exhaustive effective rule lists showing all rules that apply to each context
- Toggle between "all exhaustive rules" and "explicitly set rules" views
- Advanced filtering by patron category and/or item type
- Clear display of fallback/default rules for each context

Rule Management Actions
- Delete triggers (last trigger in a sequence for any given library)
- Reset entire rule sets for a given context (with safeguards)
- Edit existing triggers with improved context awareness
- Add new triggers with intelligent delay constraints

Improved User Experience
- Multi-step form wizard with clear workflow progression
- Context-aware letter template filtering (only shows applicable templates)
- Placeholder values showing fallback rules when clearing inputs
- Dynamic min/max constraints for delay values based on neighboring triggers
- Real-time form validation and feedback
- Partial page reloads (only reload affected sections, not entire page)
- Specific loading messages for different operations

Technical Improvements
- Centralized Vuex store for state management
- Reusable CirculationTriggersForm component
- API clients for libraries, circulation rules, item types, and patron categories
- Consistent async/await pattern throughout
- Separation of repositories, utilities, and services
- Improved naming consistency and code maintainability
- "Dumb" TriggersTable component for better separation of concerns

Test Plan

Prerequisites
1. Log in to staff interface with appropriate permissions (tools_edit_notice_status_triggers)
2. Ensure you have test data: multiple libraries, patron categories, item types, and notice templates
3. Navigate to Administration > Circulation triggers (new interface)

Part 1: Basic Navigation & Interface
1. Verify the new "Circulation triggers" link appears in Administration home under the Circulation section
2. Access the new interface and confirm it loads successfully
3. Verify the default view shows either "All libraries" or your logged-in library based on DefaultToLoggedInLibraryOverdueTriggers system preference
4. Confirm the interface displays a list of triggers organized by context (library/patron category/item type combinations)

Part 2: Viewing and Filtering Rules
1. Toggle between "All exhaustive rules" and "Explicitly set rules" views
  - Verify "All exhaustive rules" shows inherited/fallback rules
  - Verify "Explicitly set rules" shows only rules you've specifically configured
2. Test the patron category filter:
  - Select a specific patron category
  - Confirm only rules for that category are displayed
3. Test the item type filter:
  - Select a specific item type
  - Confirm only rules for that item type are displayed
4. Test combined filters (patron category + item type simultaneously)
5. Clear filters and verify all rules display again

Part 3: Adding New Triggers
1. Click "Add trigger" button
2. Step 1 - Confirm Context:
  - Select Library (required)
  - Select Patron category (required)
  - Select Item type (required)
  - Click "Confirm context"
3. Step 2 - Review Existing Triggers:
  - Verify existing triggers for this context are displayed
  - Note the trigger numbers and delays
4. Step 3 - Configure New Trigger:
  - Enter a delay value (should be constrained by neighboring triggers)
  - Try entering an invalid delay (too low or too high) - verify validation
  - Set "Restricts checkouts" (Yes/No/Fallback to default)
  - Note the placeholder showing the fallback value
  - Select a letter template
  - Verify only templates for the selected library context appear
  - Set "Debarring" options if desired
  - Select "Charged notice fees" if applicable
5. Submit the form
6. Verify the new trigger appears in the list without a full page reload
7. Verify success message is displayed

Part 4: Editing Existing Triggers
1. Locate an existing trigger in the list
2. Click the edit icon/button
3. Verify the form pre-populates with existing values
4. Test delay modification:
  - Try changing the delay within valid bounds - should succeed
  - Try changing delay beyond neighboring triggers - should show validation error
  - Use the increment/decrement buttons to adjust delay
5. Test clearing values:
  - Clear a field (e.g., delay or restrict checkouts)
  - Verify placeholder shows the fallback/default value
  - Submit with cleared value - should save as null and inherit fallback
6. Change the letter template to a different valid template
7. Submit changes
8. Verify the trigger updates in the list without full page reload
9. Verify the changes persist after refreshing the page

Part 5: Deleting Triggers
1. Identify a trigger that is the last in its sequence
2. Click the delete button/icon
3. Verify a confirmation dialog appears
4. Confirm deletion
5. Verify the trigger is removed from the list without page reload
6. Verify the deletion persists after page refresh
7. Test delete constraints:
  - Try to delete a trigger that's not the last in sequence
  - Verify appropriate error/warning message

Part 6: Resetting Rule Sets
1. Locate a context with explicitly set rules (not just inherited)
2. Ensure this is not the only rule set for this trigger sequence
3. Click the "Reset" button for that context
4. Verify confirmation dialog explains what will be reset
5. Confirm the reset
6. Verify the explicit rules are removed and context now shows inherited rules
7. Verify changes persist after page refresh
8. Test reset constraints:
  - Try to reset when it would leave no rules for that trigger
  - Verify appropriate warning/prevention

Part 7: Context-Specific Behavior
1. Test library-specific letter filtering:
  - Create/edit a trigger for a specific library
  - Verify only letter templates with matching branchcode or default templates appear
  - Switch to a different library context
  - Verify the letter list updates accordingly
2. Test default rules:
  - View rules for "All libraries" / "All patron categories" / "All item types"
  - Verify these are labeled as "Default rule for [context]"
  - Confirm these serve as fallback for more specific rules
3. Test DefaultToLoggedInLibraryOverdueTriggers preference:
  - Set preference to "Yes"
  - Reload circulation triggers page
  - Verify it defaults to your logged-in library
  - Set preference to "No"
  - Verify it defaults to "All libraries"

Part 8: Form Workflow & Validation
1. Test required fields:
  - Try submitting add/edit form without selecting library - should fail
  - Try submitting without patron category - should fail
  - Try submitting without item type - should fail
2. Test stepper navigation:
  - Start adding a trigger
  - Verify you must confirm context before proceeding
  - Verify you see existing triggers before editing/adding
  - Verify trigger form only appears after context confirmation
3. Test cancellation:
  - Start adding/editing a trigger
  - Click Cancel
  - Verify you return to the list without changes
  - Verify no partial data was saved

Part 9: Loading States & Messages
1. On slow connections or with many rules:
  - Verify "Loading context..." appears while fetching context data
  - Verify "Loading rule set information..." appears while fetching rules
  - Verify section-specific loading messages appear during updates
2. After form submission:
  - Verify appropriate success/error messages display
  - Verify loading indicators during async operations

Part 10: Permissions
1. Log in as a user without tools_edit_notice_status_triggers permission
2. Verify the "Circulation triggers" link does not appear in Administration
3. Try accessing /cgi-bin/koha/admin/circulation_triggers directly
4. Verify access is denied

Part 11: Data Integrity & Persistence
1. Create a complex set of rules with multiple triggers across different contexts
2. Refresh the page and verify all rules persist
3. Restart the Koha services
4. Verify all rules still display correctly
5. Check the database circulation_rules table:
  - Verify rules are stored with correct rule_name pattern (overdue_1_delay, etc.)
  - Verify null values are properly stored for inheritance
  - Verify the overdue_X_has_rules rule kind is present

Part 12: Edge Cases
1. Test with no existing triggers - verify empty state message
2. Test with maximum trigger sequences (e.g., trigger 1, 2, 3)
3. Test rapid successive edits
4. Test with special characters in letter template names
5. Test browser back/forward buttons during form workflow

Part 13: Comparison with Legacy Interface
1. Access the old interface if still available (via Tools menu)
2. Create a trigger using the new interface
3. Verify it appears correctly in the old interface (if applicable)
4. Create a trigger using the old interface (if still available)
5. Verify it appears correctly in the new interface

Signed-off-by: Michaela <michaela.sieber@kit.edu>
Signed-off-by: Nick Clemens <nick@bywatersolutions.com>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
2026-09-10 14:24:25 +00:00
Paul Derscheid 8ebc1d0f2b
Bug 43091: Stop emitting staff-only Vue islands into the OPAC dist
Both islands builds share modules/islands.ts, which hardcodes every
island. The OPAC compilation therefore emits staff-only lazy chunks
(acquisitions-menu, vendor-menu, admin-menu) into
koha-tmpl/opac-tmpl/bootstrap/js/vue/dist/, and the OPAC islands.esm.js
bundles the staff Pinia stores.

- split modules/islands.ts into shared machinery and per-application
  entry points (islands-intranet.ts, islands-opac.ts)
- declare each application's islands as a Map literal and feed it
  through registerIsland(), the same path plugin islands take
- pass store definitions into hydrate() instead of importing every
  store in the shared module
- keep the full plugin import surface (registerIsland, hydrate, Vue
  re-exports) on both entries via star re-exports
- point the rspack islands entries at the per-application modules

Test plan:
1. yarn build
2. ls koha-tmpl/opac-tmpl/bootstrap/js/vue/dist/
   => only islands.esm.js and a patron-self-renewal chunk are emitted
3. ls koha-tmpl/intranet-tmpl/prog/js/vue/dist/
   => acquisitions-menu, vendor-menu and admin-menu chunks are still
   present
4. In the staff interface, visit pages using the acquisitions, vendor
   and admin menu islands and verify they render
5. Enable self-renewal for a patron's category and put the patron
   inside the availability window, e.g.:
   UPDATE categories SET self_renewal_enabled = 1
     WHERE categorycode =
     (SELECT categorycode FROM borrowers WHERE userid = 'koha');
   UPDATE borrowers
     SET dateexpiry = DATE_ADD(CURDATE(), INTERVAL 7 DAY),
     debarred = NULL WHERE userid = 'koha';
6. Log into the OPAC as that patron and open 'your summary'
   => the patron-self-renewal chunk loads from
   /opac-tmpl/bootstrap/js/vue/dist/ and the self-renewal modal
   completes successfully

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Signed-off-by: Matt Blenkinsop <matt.blenkinsop@openfifth.co.uk>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
2026-08-03 13:00:36 +00:00
Pedro Amorim 6dab32ee02
Bug 37762: VueJS ILL Module
Signed-off-by: Jason Robb <jrobb@sekls.org>
Signed-off-by: Lisette Scheer <lisette@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-05-08 12:25:38 -06:00
Matt Blenkinsop 133946e50c
Bug 26355: Add a Vue island for the self-renewal modal
Signed-off-by: Christopher Brannon <cbrannon@cdalibrary.org>
Signed-off-by: Andrew Fuerste Henry <andrew@bywatersolutions.com>
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-05-01 09:30:00 -06:00
Martin Renvoize bb4407a0ff
Bug 41587: (follow-up) Clean Cypress plugin dist on rebuild to prevent stale sourcemaps
Add output.clean: true to the Cypress plugin rspack build config.

Before Bug 36674 (Nov 2025), this build emitted .map files into
t/cypress/plugins/dist/. After devtool: false was added, the map files
were no longer generated but stale ones persisted on developer machines
(dist/ is gitignored).

When the rspack update in Bug 41587 rebuilt api-client.cjs.js with
dynamic chunk loading, Cypress's webpack created a context module for
the require() expression and matched the stale .map files (webpack's
context regex matches substrings, so *.js.map matches *.js). Webpack
then failed trying to parse JSON sourcemaps as JavaScript.

output.clean: true ensures the dist directory is wiped on every build,
so stale files from previous configurations can never accumulate.

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
2026-03-20 15:16:28 +00:00
David Cook 8b17f6158d
Bug 38365: Set __webpack_nonce__ for style-loader plugin and fix fontawesome imports
By setting __webpack_nonce__ webpack/rspack will add the nonce to styles
added using style-loader plugin.

Also, stop fontawesome from auto injecting CSS elements, and instead
manually import them so that they can be picked up by style-loader

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
2026-03-16 11:57:39 +01:00
Paul Derscheid 87fb6f273a
Bug 36674: (follow-up) Stop emitting Cypress API client source maps
- Use devtool: false to prevent emitting source maps for cypress.
- Add package script to clean built assets, artifacts.

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-12-02 10:07:13 -07:00
Pedro Amorim 38fe4442d2
Bug 37893: SIP2 VueJS module scaffolding
Signed-off-by: Andrew Fuerste Henry <andrew@bywatersolutions.com>
Signed-off-by: Lisette Scheer <lisette@bywatersolutions.com>
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-11-18 11:20:45 -07:00
Jonathan Druart 70b7bb0f33
Bug 38201: Move cypress components under t/cypress
(cherry picked from commit 5cf8a60eb99e37abc365639d05e9da9ca931f7d6)
Signed-off-by: Michaela Sieber <michaela.sieber@kit.edu>
Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-10-02 09:40:23 -06:00
Matt Blenkinsop 7d5bd4b9ae
Bug 38201: Rename the '@k' alias to koha-vue
Signed-off-by: Michaela Sieber <michaela.sieber@kit.edu>
Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-10-02 09:39:59 -06:00
Jonathan Druart d80916696f
Bug 38201: Do not export $__ from the base resource
We had this following warning in the console:
[Vue warn]: setup() return property "$__" should not start with "$" or "_" which are reserved prefixes for Vue internals.

Trying to fix this and realized we could do better in our handling of
the i18n functions.

This patch suggests to:
1. Have "@k" available as the Koha Vue root path so that we can easily
   import without relative paths
   TODO - Should be applied to all other imports
2. Import the i18n functions from the components when we need it
3. Do not have them available in the i18n object exported by the
   base resource
4. Remove direct use of __() from scripts and always use $__()

(cherry picked from commit 247675939ef28a90d21be863c6a57382cf3de966)
Signed-off-by: Michaela Sieber <michaela.sieber@kit.edu>
Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-10-02 09:39:58 -06:00
Jonathan Druart 0985c64a54
Bug 40173: Make http-client reusable from Cypress tests
We will need to call REST API endpoints from Cypress tests, and more
specifically from Cypress's tasks.

It will be useful to reuse what has been done in http-client.js instead
of using the low-level fetch JS function.

1. Add missing get and getAll functions
2. Allow overwrite of return_response and mark_submitting
3. Add a "default" client that will bring flexibility (can call any
   routes)
4. Add rspack config to generate
   t/cypress/plugins/dist/api-client.cjs.js that will make it reusable
   from Cypress's tasks

Signed-off-by: Owen Leonard <oleonard@myacpl.org>
Signed-off-by: Matt Blenkinsop <matt.blenkinsop@openfifth.co.uk>
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-07-21 14:01:07 -06:00
Matt Blenkinsop 30606d2373
Bug 38010: (QA follow-up) Rebase on main
Signed-off-by: Michaela Sieber <michaela.sieber@kit.edu>
Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
2025-05-02 17:19:15 +02:00
Matt Blenkinsop 5b07a872f3
Bug 38010: Rename routes to acquisitions
This patch renames the app from vendors to acquisitions to allow further acquisitions pages to be migrated

Signed-off-by: Michaela Sieber <michaela.sieber@kit.edu>
Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
2025-05-02 17:18:30 +02:00
Matt Blenkinsop b71b62059a
Bug 38010: Add vue app and list component
This patch adds the base vue app as well as the component to list vendors

Amended-by: Jonathan Druart
chmod 755 acqui/vendors.pl

Signed-off-by: Michaela Sieber <michaela.sieber@kit.edu>
Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
2025-05-02 17:18:27 +02:00
Paul Derscheid b724ffc16c
Bug 37911: (follow-up) Use style-, css-loader to preserve compatiblity with Koha's Vue components, e.g. Dialog.vue
- For now let's not rely on rspack's native css loader to parse and
  bundle styles as we need to preserve compatibility.
- Reintroduce configuration block for style-, css-loader for islands.

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
2025-04-25 18:35:01 +02:00
Paul Derscheid c7f5e2740c
Bug 37911: (follow-up) Let style-, css-loader handle styles in Koha's Vue apps
- Remove 'experiments: css' for the first config block since it seems to do 2 passes when building the css.
- Remove style-, css-loader configuration for islands as I assume it is unneeded in this case.

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
2025-04-25 18:35:00 +02:00
Paul Derscheid e3d3224f6f
Bug 37911: (follow-up) Tidy and remove leftover entry point for islands in first config block
Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
2025-04-25 18:35:00 +02:00
Paul Derscheid bd15b1829e
Bug 37911: (follow-up) Allow for initialisation of islands on demand
- Split the rspack config into a umd and an esm section.
- Don't hydrate by default.
    - Instead check the "init" attribute for the currentScript when using the umd.
    - Allow for manual import and call when using the esm.
    - Add examples for both in intranet-main.tt (to be removed).
- Add a DialogIsland wrapper for the shared Dialog component (to map props to stored refs).
- Move DialogIsland as well as Demo components into an Islands directory under components.
- Add i18n initialisation to hydrate's idle callback.

Signed-off-by: Matt Blenkinsop <matt.blenkinsop@ptfs-europe.com>

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
2025-04-25 18:34:57 +02:00
Paul Derscheid aa5283dd62
Bug 37911: (follow-up) Prevent resolution failure of dynamic imports when building in mode --production
Signed-off-by: Matt Blenkinsop <matt.blenkinsop@ptfs-europe.com>

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
2025-04-25 18:34:56 +02:00
Paul Derscheid 4c40cf8f9f
Bug 37911: (follow-up) Update to vue ^3.5.4, use vue's web component implementation instead
- This would require us to update vue to a new minor version.
	- We could then use the defineCustomElement function with the shadowRoot option set to false (this is important).
- The current implementation in islands.ts is naive and would result in an intolerable bundle size.
	- The right way to do code splitting here is to use dynamic imports.

Signed-off-by: Matt Blenkinsop <matt.blenkinsop@ptfs-europe.com>

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
2025-04-25 18:34:53 +02:00
Paul Derscheid cdd5194183
Bug 37911: Prototype vue islands within static pages
This is pretty bare bones, but might still be interesting to take a look at.

Signed-off-by: Matt Blenkinsop <matt.blenkinsop@ptfs-europe.com>

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
2025-04-25 18:34:52 +02:00
Paul Derscheid 27524f87e3
Bug 38993: (follow-up) Add 'fetch' alias to rspack config
Signed-off-by: Paul Derscheid <paul.derscheid@lmscloud.de>
Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>
Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
2025-03-17 11:59:52 +01:00
Paul Derscheid db4f151be5
Bug 37824: (QA follow-up) Fix improper handling of jQuery and DataTables libraries by marking them as externals
This commit addresses an issue where jQuery and DataTables libraries (datatables.net and related extensions) were not functioning correctly when bundled with rspack. These libraries expect to be loaded in the global scope rather than as bundled modules, leading to initialization issues.

To resolve this, jQuery and all related DataTables libraries (datatables.net, datatables.net-buttons, datatables.net-buttons/js/buttons.html5, etc.) are marked as externals in the rspack configuration. This ensures they are treated as global dependencies, preventing conflicts and allowing proper initialization.

Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
2024-09-16 18:41:17 +02:00
Paul Derscheid 28b6294461
Bug 37824: Replace webpack with rspack for fun and profit
I left the webpack.config.js as well as the devDependencies in place for now.
We can remove them in a follow-up patch on this bug after testing it out.

To test:
1) Run js:build and js:build:prod
2) Note the build time
3) Apply patch
4) Run yarn install
5) Run js:build and js:build:prod again
6) Note the much faster build time
7) Extra credit: take a look at the ERM or preservations module and make sure everything works as expected.
8) Extra credit: run the cypress tests.
9) Sign off or give your opinion

Signed-off-by: Marcel de Rooy <m.de.rooy@rijksmuseum.nl>
Looks faster to me. Where webpack failed for me (Killed, error 137), this passed.
Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>
Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
2024-09-16 13:47:06 +02:00