Bugzilla – Attachment 187563 Details for
Bug 39320
Create a 'landing page' for ERM
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 39320: Follow-up: Add 'move up' and 'move down' options
Bug-39320-Follow-up-Add-move-up-and-move-down-opti.patch (text/plain), 16.34 KB, created by
Pedro Amorim
on 2025-10-08 12:15:50 UTC
(
hide
)
Description:
Bug 39320: Follow-up: Add 'move up' and 'move down' options
Filename:
MIME Type:
Creator:
Pedro Amorim
Created:
2025-10-08 12:15:50 UTC
Size:
16.34 KB
patch
obsolete
>From d6237c130998f99837186b195c846566311c2f44 Mon Sep 17 00:00:00 2001 >From: Pedro Amorim <pedro.amorim@openfifth.co.uk> >Date: Wed, 8 Oct 2025 12:14:14 +0000 >Subject: [PATCH] Bug 39320: Follow-up: Add 'move up' and 'move down' options > >--- > .../ModuleDashboard/ModuleDashboard.vue | 65 ++++++++++++++----- > .../WidgetDashboardWrapper.vue | 28 +++++++- > .../ModuleDashboard/WidgetWrapper.vue | 10 ++- > .../ModuleDashboard/Widgets/ERMCounts.vue | 1 + > .../Widgets/ERMLatestSUSHIJobs.vue | 1 + > .../Widgets/ERMLicensesNeedingAction.vue | 1 + > .../Widgets/ERMRunUsageReport.vue | 1 + > .../prog/js/vue/composables/base-widget.js | 6 +- > .../intranet-tmpl/prog/js/vue/modules/erm.ts | 6 +- > .../integration/ERM/ModuleDashboard_spec.ts | 36 +++++++++- > 10 files changed, 130 insertions(+), 25 deletions(-) > >diff --git a/koha-tmpl/intranet-tmpl/prog/js/vue/components/ModuleDashboard/ModuleDashboard.vue b/koha-tmpl/intranet-tmpl/prog/js/vue/components/ModuleDashboard/ModuleDashboard.vue >index 0ec96c92ffe..fdd2738ff35 100644 >--- a/koha-tmpl/intranet-tmpl/prog/js/vue/components/ModuleDashboard/ModuleDashboard.vue >+++ b/koha-tmpl/intranet-tmpl/prog/js/vue/components/ModuleDashboard/ModuleDashboard.vue >@@ -20,10 +20,11 @@ > > > <component > v-for="(widget, index) in selectedWidgetsLeft" >- :key="widget.name" >+ :key="widget.name + '-' + index" > :is="widget" > display="dashboard" > dashboardColumn="left" >+ :dashboardTopRow="index === 0" > @moveWidget="moveWidget" > @removed="removeWidget(widget)" > ></component> >@@ -39,10 +40,11 @@ > > > <component > v-for="(widget, index) in selectedWidgetsRight" >- :key="widget.name" >+ :key="widget.name + '-' + index" > :is="widget" > display="dashboard" > dashboardColumn="right" >+ :dashboardTopRow="index === 0" > @moveWidget="moveWidget" > @removed="removeWidget(widget)" > ></component> >@@ -103,33 +105,62 @@ export default { > } > } > >- function moveWidget(widget) { >- if ( >- selectedWidgetsLeft.value.some( >- element => element.name === widget.componentName >- ) >- ) { >+ function moveWidget(params) { >+ if (params.direction === "right") { > selectedWidgetsRight.value.unshift( > selectedWidgetsLeft.value.find( >- element => element.name === widget.componentName >+ element => element.name === params.widgetComponentName > ) > ); > selectedWidgetsLeft.value = selectedWidgetsLeft.value.filter( >- element => element.name !== widget.componentName >+ element => element.name !== params.widgetComponentName > ); >- } else if ( >- selectedWidgetsRight.value.some( >- element => element.name === widget.componentName >- ) >- ) { >+ } else if (params.direction === "left") { > selectedWidgetsLeft.value.unshift( > selectedWidgetsRight.value.find( >- element => element.name === widget.componentName >+ element => element.name === params.widgetComponentName > ) > ); > selectedWidgetsRight.value = selectedWidgetsRight.value.filter( >- element => element.name !== widget.componentName >+ element => element.name !== params.widgetComponentName > ); >+ } else if ( >+ params.direction === "up" || >+ params.direction === "down" >+ ) { >+ const list = >+ params.currentColumn === "left" >+ ? selectedWidgetsLeft.value >+ : selectedWidgetsRight.value; >+ >+ const currentIndex = list.findIndex( >+ element => element.name === params.widgetComponentName >+ ); >+ >+ if (currentIndex === -1) return; >+ >+ const newIndex = >+ params.direction === "up" >+ ? currentIndex - 1 >+ : currentIndex + 1; >+ >+ if (newIndex < 0 || newIndex >= list.length) return; // Out of bounds >+ >+ if (params.currentColumn === "left") { >+ selectedWidgetsLeft.value = (() => { >+ const arr = [...selectedWidgetsLeft.value]; >+ const [item] = arr.splice(currentIndex, 1); >+ arr.splice(newIndex, 0, item); >+ return arr; >+ })(); >+ } else if (params.currentColumn === "right") { >+ selectedWidgetsRight.value = (() => { >+ const arr = [...selectedWidgetsRight.value]; >+ const [item] = arr.splice(currentIndex, 1); >+ arr.splice(newIndex, 0, item); >+ return arr; >+ })(); >+ } > } > } > >diff --git a/koha-tmpl/intranet-tmpl/prog/js/vue/components/ModuleDashboard/WidgetDashboardWrapper.vue b/koha-tmpl/intranet-tmpl/prog/js/vue/components/ModuleDashboard/WidgetDashboardWrapper.vue >index 539f507172c..35d1be52f00 100644 >--- a/koha-tmpl/intranet-tmpl/prog/js/vue/components/ModuleDashboard/WidgetDashboardWrapper.vue >+++ b/koha-tmpl/intranet-tmpl/prog/js/vue/components/ModuleDashboard/WidgetDashboardWrapper.vue >@@ -36,6 +36,16 @@ > {{ $__("Settings") }} > </button> > </li> >+ <li v-if="!dashboardTopRow"> >+ <button >+ class="dropdown-item move-up" >+ @mousedown="moveWidget('up')" >+ :title="$__('Move up')" >+ > >+ <font-awesome-icon icon="arrow-up" /> >+ {{ $__("Move up") }} >+ </button> >+ </li> > <li v-if="dashboardColumn === 'left'"> > <button > class="dropdown-item move-right" >@@ -56,6 +66,16 @@ > {{ $__("Move to left") }} > </button> > </li> >+ <li v-if="dashboardTopRow"> >+ <button >+ class="dropdown-item move-down" >+ @mousedown="moveWidget('down')" >+ :title="$__('Move down')" >+ > >+ <font-awesome-icon icon="arrow-down" /> >+ {{ $__("Move down") }} >+ </button> >+ </li> > <li> > <button > class="dropdown-item remove-widget" >@@ -140,6 +160,10 @@ export default { > type: String, > required: false, > }, >+ dashboardTopRow: { >+ type: Boolean, >+ required: true, >+ }, > }, > setup(props, { emit }) { > const showSettings = ref(false); >@@ -148,8 +172,8 @@ export default { > emit("removed", props); > }; > >- const moveWidget = column => { >- emit("moveWidget"); >+ const moveWidget = direction => { >+ emit("moveWidget", direction); > }; > > function toggleSettings() { >diff --git a/koha-tmpl/intranet-tmpl/prog/js/vue/components/ModuleDashboard/WidgetWrapper.vue b/koha-tmpl/intranet-tmpl/prog/js/vue/components/ModuleDashboard/WidgetWrapper.vue >index a873ce6a276..577dccbf2c7 100644 >--- a/koha-tmpl/intranet-tmpl/prog/js/vue/components/ModuleDashboard/WidgetWrapper.vue >+++ b/koha-tmpl/intranet-tmpl/prog/js/vue/components/ModuleDashboard/WidgetWrapper.vue >@@ -21,6 +21,7 @@ > :settings_definitions="settings_definitions" > :loading="loading" > :dashboardColumn="dashboardColumn" >+ :dashboardTopRow="dashboardTopRow" > :name="name" > :icon="icon" > > >@@ -52,6 +53,9 @@ export default { > dashboardColumn: { > type: String, > }, >+ dashboardTopRow: { >+ type: Boolean, >+ }, > id: { > type: String, > required: true, >@@ -83,6 +87,7 @@ export default { > display, > alreadyAdded, > dashboardColumn, >+ dashboardTopRow, > id, > name, > icon, >@@ -104,14 +109,15 @@ export default { > if (removeWidget) removeWidget(); > }; > >- const handleMoveWidget = () => { >- if (moveWidget) moveWidget(); >+ const handleMoveWidget = direction => { >+ if (moveWidget) moveWidget(direction); > }; > > return { > display, > alreadyAdded, > dashboardColumn, >+ dashboardTopRow, > id, > name, > icon, >diff --git a/koha-tmpl/intranet-tmpl/prog/js/vue/components/ModuleDashboard/Widgets/ERMCounts.vue b/koha-tmpl/intranet-tmpl/prog/js/vue/components/ModuleDashboard/Widgets/ERMCounts.vue >index 651c080c5bf..92ae98024ca 100644 >--- a/koha-tmpl/intranet-tmpl/prog/js/vue/components/ModuleDashboard/Widgets/ERMCounts.vue >+++ b/koha-tmpl/intranet-tmpl/prog/js/vue/components/ModuleDashboard/Widgets/ERMCounts.vue >@@ -49,6 +49,7 @@ export default { > components: { WidgetWrapper }, > props: { > display: String, >+ dashboardColumn: String, > }, > emits: ["removed", "added", "moveWidget"], > setup(props, { emit }) { >diff --git a/koha-tmpl/intranet-tmpl/prog/js/vue/components/ModuleDashboard/Widgets/ERMLatestSUSHIJobs.vue b/koha-tmpl/intranet-tmpl/prog/js/vue/components/ModuleDashboard/Widgets/ERMLatestSUSHIJobs.vue >index 5b6c7e08147..e1d2f99f900 100644 >--- a/koha-tmpl/intranet-tmpl/prog/js/vue/components/ModuleDashboard/Widgets/ERMLatestSUSHIJobs.vue >+++ b/koha-tmpl/intranet-tmpl/prog/js/vue/components/ModuleDashboard/Widgets/ERMLatestSUSHIJobs.vue >@@ -23,6 +23,7 @@ export default { > components: { WidgetWrapper, KohaTable }, > props: { > display: String, >+ dashboardColumn: String, > }, > emits: ["removed", "added", "moveWidget"], > setup(props, { emit }) { >diff --git a/koha-tmpl/intranet-tmpl/prog/js/vue/components/ModuleDashboard/Widgets/ERMLicensesNeedingAction.vue b/koha-tmpl/intranet-tmpl/prog/js/vue/components/ModuleDashboard/Widgets/ERMLicensesNeedingAction.vue >index af520cc76bd..4304247c62a 100644 >--- a/koha-tmpl/intranet-tmpl/prog/js/vue/components/ModuleDashboard/Widgets/ERMLicensesNeedingAction.vue >+++ b/koha-tmpl/intranet-tmpl/prog/js/vue/components/ModuleDashboard/Widgets/ERMLicensesNeedingAction.vue >@@ -23,6 +23,7 @@ export default { > components: { WidgetWrapper, KohaTable }, > props: { > display: String, >+ dashboardColumn: String, > }, > emits: ["removed", "added", "moveWidget"], > setup(props, { emit }) { >diff --git a/koha-tmpl/intranet-tmpl/prog/js/vue/components/ModuleDashboard/Widgets/ERMRunUsageReport.vue b/koha-tmpl/intranet-tmpl/prog/js/vue/components/ModuleDashboard/Widgets/ERMRunUsageReport.vue >index 0ae20b5c377..8ff50838df0 100644 >--- a/koha-tmpl/intranet-tmpl/prog/js/vue/components/ModuleDashboard/Widgets/ERMRunUsageReport.vue >+++ b/koha-tmpl/intranet-tmpl/prog/js/vue/components/ModuleDashboard/Widgets/ERMRunUsageReport.vue >@@ -49,6 +49,7 @@ export default { > components: { WidgetWrapper }, > props: { > display: String, >+ dashboardColumn: String, > }, > emits: ["removed", "added", "moveWidget"], > setup(props, { emit }) { >diff --git a/koha-tmpl/intranet-tmpl/prog/js/vue/composables/base-widget.js b/koha-tmpl/intranet-tmpl/prog/js/vue/composables/base-widget.js >index 4b52776d5ca..102bb9e9e80 100644 >--- a/koha-tmpl/intranet-tmpl/prog/js/vue/composables/base-widget.js >+++ b/koha-tmpl/intranet-tmpl/prog/js/vue/composables/base-widget.js >@@ -10,10 +10,11 @@ export function useBaseWidget(widgetConfig, emit) { > const settings_definitions = ref(widgetConfig.settings_definitions || []); > const removeWidget = () => emit("removed", widgetConfig); > const addWidget = () => emit("added", widgetConfig); >- const moveWidget = () => { >+ const moveWidget = direction => { > emit("moveWidget", { >- componentName: widgetConfig.id, >+ widgetComponentName: widgetConfig.id, > currentColumn: widgetConfig.dashboardColumn, >+ direction: direction, > }); > }; > >@@ -26,6 +27,7 @@ export function useBaseWidget(widgetConfig, emit) { > display: widgetConfig.display, > alreadyAdded: widgetConfig.alreadyAdded, > dashboardColumn: widgetConfig.dashboardColumn, >+ dashboardTopRow: widgetConfig.dashboardTopRow, > name: widgetConfig.name, > icon: widgetConfig.icon, > loading: loading.value, >diff --git a/koha-tmpl/intranet-tmpl/prog/js/vue/modules/erm.ts b/koha-tmpl/intranet-tmpl/prog/js/vue/modules/erm.ts >index bf22b7a0abc..614f0dc7249 100644 >--- a/koha-tmpl/intranet-tmpl/prog/js/vue/modules/erm.ts >+++ b/koha-tmpl/intranet-tmpl/prog/js/vue/modules/erm.ts >@@ -15,6 +15,8 @@ import { > faEllipsisVertical, > faArrowRight, > faArrowLeft, >+ faArrowUp, >+ faArrowDown, > } from "@fortawesome/free-solid-svg-icons"; > import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome"; > import vSelect from "vue-select"; >@@ -30,7 +32,9 @@ library.add( > faEye, > faEllipsisVertical, > faArrowRight, >- faArrowLeft >+ faArrowLeft, >+ faArrowUp, >+ faArrowDown > ); > > import App from "../components/ERM/Main.vue"; >diff --git a/t/cypress/integration/ERM/ModuleDashboard_spec.ts b/t/cypress/integration/ERM/ModuleDashboard_spec.ts >index 4dd95de3b12..91d6e9ca53c 100644 >--- a/t/cypress/integration/ERM/ModuleDashboard_spec.ts >+++ b/t/cypress/integration/ERM/ModuleDashboard_spec.ts >@@ -32,7 +32,7 @@ describe("ERM Module Dashboard", () => { > "There are 1 agreement, 5 licenses, 0 documents, 0 local packages, 0 local titles, 1 usage data provider." > ); > >- //Move >+ //Move to the right > cy.get( > ".dashboard-left-col .widget#ERMCounts .widget-header #dropdownMenuButton" > ).click(); >@@ -45,6 +45,40 @@ describe("ERM Module Dashboard", () => { > .first() > .should("have.id", "ERMCounts"); > >+ //Move down >+ cy.get(".dashboard-right-col .dragArea") >+ .children() >+ .first() >+ .should("have.id", "ERMCounts"); >+ cy.get( >+ ".dashboard-right-col .widget#ERMCounts .widget-header #dropdownMenuButton" >+ ).click(); >+ cy.get( >+ ".dashboard-right-col .widget#ERMCounts .widget-header .move-down" >+ ).click(); >+ //ERMCounts is now index 1, position 2 >+ cy.get(".dashboard-right-col .dragArea") >+ .children() >+ .eq(1) >+ .should("have.id", "ERMCounts"); >+ >+ //Move up >+ cy.get(".dashboard-right-col .dragArea") >+ .children() >+ .eq(1) >+ .should("have.id", "ERMCounts"); >+ cy.get( >+ ".dashboard-right-col .widget#ERMCounts .widget-header #dropdownMenuButton" >+ ).click(); >+ cy.get( >+ ".dashboard-right-col .widget#ERMCounts .widget-header .move-up" >+ ).click(); >+ //ERMCounts is now index 1, position 2 >+ cy.get(".dashboard-right-col .dragArea") >+ .children() >+ .first() >+ .should("have.id", "ERMCounts"); >+ > //Remove > cy.get( > ".dashboard-right-col .widget#ERMCounts .widget-header #dropdownMenuButton" >-- >2.39.5
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 39320
:
187513
|
187514
|
187515
|
187516
|
187517
|
187518
|
187519
|
187520
|
187521
|
187522
|
187563
|
187568
|
187635
|
187636
|
187637
|
187638
|
187639
|
187640
|
187641
|
187642
|
187643
|
187644
|
187645
|
188094
|
188095
|
188096
|
188097
|
188098
|
188099
|
188100
|
188101
|
188102
|
188103
|
188104
|
188151
|
188279
|
188280
|
188281
|
188282
|
188283
|
188284
|
188285
|
188312
|
188315
|
188372
|
188375
|
188376
|
188637
|
188638
|
188639
|
188640
|
188641
|
188830
|
188831
|
188832
|
188833
|
188834
|
188835
|
188836
|
188837
|
188838
|
188839
|
188840
|
188841
|
188842
|
188843
|
188844
|
188845
|
188846
|
188847
|
188848
|
188849
|
188850
|
188851
|
188852
|
188853
|
188854
|
188855
|
188856
|
188857
|
188858
|
188859
|
188860
|
188861
|
188862
|
188863
|
188864