From e7b12feffb0fe976365e91776778a0b45d7d1237 Mon Sep 17 00:00:00 2001 From: Pedro Amorim Date: Tue, 25 Feb 2025 16:05:26 +0000 Subject: [PATCH] Bug 39320: Preparation: Add base and wrapper components As well as wrapper support components base-widget.js composable --- .../ModuleDashboard/ModuleDashboard.vue | 222 +++++++++++++++++ .../WidgetDashboardWrapper.vue | 231 ++++++++++++++++++ .../ModuleDashboard/WidgetPicker.vue | 59 +++++ .../ModuleDashboard/WidgetPickerWrapper.vue | 97 ++++++++ .../ModuleDashboard/WidgetWrapper.vue | 136 +++++++++++ .../prog/js/vue/composables/base-widget.js | 97 ++++++++ 6 files changed, 842 insertions(+) create mode 100644 koha-tmpl/intranet-tmpl/prog/js/vue/components/ModuleDashboard/ModuleDashboard.vue create mode 100644 koha-tmpl/intranet-tmpl/prog/js/vue/components/ModuleDashboard/WidgetDashboardWrapper.vue create mode 100644 koha-tmpl/intranet-tmpl/prog/js/vue/components/ModuleDashboard/WidgetPicker.vue create mode 100644 koha-tmpl/intranet-tmpl/prog/js/vue/components/ModuleDashboard/WidgetPickerWrapper.vue create mode 100644 koha-tmpl/intranet-tmpl/prog/js/vue/components/ModuleDashboard/WidgetWrapper.vue create mode 100644 koha-tmpl/intranet-tmpl/prog/js/vue/composables/base-widget.js 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 new file mode 100644 index 00000000000..0ec96c92ffe --- /dev/null +++ b/koha-tmpl/intranet-tmpl/prog/js/vue/components/ModuleDashboard/ModuleDashboard.vue @@ -0,0 +1,222 @@ + + + + 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 new file mode 100644 index 00000000000..539f507172c --- /dev/null +++ b/koha-tmpl/intranet-tmpl/prog/js/vue/components/ModuleDashboard/WidgetDashboardWrapper.vue @@ -0,0 +1,231 @@ + + + + + diff --git a/koha-tmpl/intranet-tmpl/prog/js/vue/components/ModuleDashboard/WidgetPicker.vue b/koha-tmpl/intranet-tmpl/prog/js/vue/components/ModuleDashboard/WidgetPicker.vue new file mode 100644 index 00000000000..1f5994faf41 --- /dev/null +++ b/koha-tmpl/intranet-tmpl/prog/js/vue/components/ModuleDashboard/WidgetPicker.vue @@ -0,0 +1,59 @@ + + + diff --git a/koha-tmpl/intranet-tmpl/prog/js/vue/components/ModuleDashboard/WidgetPickerWrapper.vue b/koha-tmpl/intranet-tmpl/prog/js/vue/components/ModuleDashboard/WidgetPickerWrapper.vue new file mode 100644 index 00000000000..8affc61bdcf --- /dev/null +++ b/koha-tmpl/intranet-tmpl/prog/js/vue/components/ModuleDashboard/WidgetPickerWrapper.vue @@ -0,0 +1,97 @@ + + + + + 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 new file mode 100644 index 00000000000..9d8ff424b24 --- /dev/null +++ b/koha-tmpl/intranet-tmpl/prog/js/vue/components/ModuleDashboard/WidgetWrapper.vue @@ -0,0 +1,136 @@ + + + + + + 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 new file mode 100644 index 00000000000..4b52776d5ca --- /dev/null +++ b/koha-tmpl/intranet-tmpl/prog/js/vue/composables/base-widget.js @@ -0,0 +1,97 @@ +// composables/useBaseWidget.js +import { ref, computed, watch, provide, onMounted, onBeforeMount } from "vue"; +import VueCookies from "vue-cookies"; + +export function useBaseWidget(widgetConfig, emit) { + const loading = ref( + widgetConfig.loading !== undefined ? widgetConfig.loading : true + ); + const settings = ref(widgetConfig.settings || {}); + const settings_definitions = ref(widgetConfig.settings_definitions || []); + const removeWidget = () => emit("removed", widgetConfig); + const addWidget = () => emit("added", widgetConfig); + const moveWidget = () => { + emit("moveWidget", { + componentName: widgetConfig.id, + currentColumn: widgetConfig.dashboardColumn, + }); + }; + + provide("removeWidget", removeWidget); + provide("addWidget", addWidget); + provide("moveWidget", moveWidget); + + const widgetWrapperProps = computed(() => ({ + id: widgetConfig.id, + display: widgetConfig.display, + alreadyAdded: widgetConfig.alreadyAdded, + dashboardColumn: widgetConfig.dashboardColumn, + name: widgetConfig.name, + icon: widgetConfig.icon, + loading: loading.value, + description: widgetConfig.description, + settings: settings.value, + settings_definitions: settings_definitions.value, + })); + + const getWidgetSavedSettings = () => { + const cookie = VueCookies.get( + "widget-" + widgetConfig.id + "-settings" + ); + return cookie || null; + }; + + onBeforeMount(() => { + if (widgetConfig.display === "dashboard") { + const cookie = getWidgetSavedSettings(); + if (cookie) { + settings.value = cookie; + } + } + }); + + /** + * Lifecycle method that runs when the widget is mounted on the dashboard. + * Use this to e.g. fetch data + * + * Sample usage from ERMCounts.vue: + * + * baseWidget.onDashboardMounted(() => { + * getCounts(); + * }); + */ + function onDashboardMounted(callback) { + onMounted(() => { + if (widgetConfig.display === "dashboard") { + callback?.(); + } + }); + } + + watch( + settings, + newSettings => { + if (widgetConfig.display === "dashboard" && newSettings !== null) { + VueCookies.set( + "widget-" + widgetConfig.id + "-settings", + JSON.stringify(newSettings), + "30d" + ); + } + }, + { deep: true } + ); + + return { + ...widgetConfig, + loading, + display: widgetConfig.display, + settings, + settings_definitions, + widgetWrapperProps, + removeWidget, + addWidget, + moveWidget, + onDashboardMounted, + }; +} -- 2.39.5