diff --git a/docs/introduction/getting-started.md b/docs/introduction/getting-started.md index d6fcefd..16656dc 100644 --- a/docs/introduction/getting-started.md +++ b/docs/introduction/getting-started.md @@ -47,12 +47,13 @@ app.use(harnessPlugin, { pinia, pages, router }) app.use(router); app.mount("#app"); ``` + ## Automagic Page Stores One of the goals of Harness-Vue is the ability to write components that are widely reusable across pages, charts and filters - having an API of helper functions that provide contextualized actions on each page is a convenience feature that allows for more robust and reusable components. In order to assist in that process, Harness-Vue exports a global mixin for the options API and a composable for the composition API that detect what page your component is currently referring to using the following logic: * first by checking if the route name (if vue-router is used) matches the name of an installed page definition * second by checking if there is only one page and no vue-router installed and using that by default - * third by checking for a `harness-waypoint` prop that matches a page definition key + * third by checking for a provided `waypoint` rop that matches a page definition key ### Options API mixin diff --git a/docs/introduction/page-definitions.md b/docs/introduction/page-definitions.md index 76253ee..c99c34e 100644 --- a/docs/introduction/page-definitions.md +++ b/docs/introduction/page-definitions.md @@ -1,4 +1,4 @@ -# Page definitions +# Page Definitions The core unit of the Harness-Vue plugin is the page definition. The page definition is an expected format for developers to provide to the plugin to be translated into Harness Vue pinia stores. @@ -146,10 +146,28 @@ export default class ExamplePage { } } ``` +### Before and After loadData +Similar to the `beforeSet` and `afterSet` functionality in the charts and filters, page definitions can include `beforeLoadData` and `afterLoadData` functions to be run before and after `loadData`, respectively. +## Routing +If a router was provided, a [named route](https://router.vuejs.org/guide/essentials/named-routes.html) will be created for your page definition. This route will be defined using defaults, all of which can be overridden by providing your page definition with select attributes. -## Other -Similar to the `beforeSet` and `afterSet` functionality in the charts and filters, page definitions can include `beforeLoadData` and `afterLoadData` functions to be run before and after `loadData`, respectively. +* The `path` of the route will default to the page key, but can be overridden by providing a `routePath` attribute. Note that this will have a prepended slash automatically. +* The `name` of the route will default to the page key, but can be overridden by providing a `routeName` attribute. +* The route will be provided with a [navigation guard](https://router.vuejs.org/guide/advanced/navigation-guards.html#Per-Route-Guard) using the `beforeEnter` syntax. By default, this will run `clearData()` on route exit and `loadData()` on route enter. This can be overridden by providing your own `routeBeforeEnter(to, from, next, store)` function, which takes the `to`/`from`/`next` arguments from `beforeEnter` and additionally provides the page store. + +```javascript +export default class ExamplePage { + // ... // + routePath = 'dashboards/examplePage' + routeName = 'Example Page' + routeBeforeEnter(to, from, next, store){ + console.log(`Came from ${from.name}`) + store.initializeDefaults() + store.loadData() + } +} +``` ## Full Example diff --git a/package-lock.json b/package-lock.json index 6557be8..a72448f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@rtidatascience/harness-vue", - "version": "1.6.0", + "version": "1.7.0-0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@rtidatascience/harness-vue", - "version": "1.6.0", + "version": "1.7.0-0", "license": "MIT", "dependencies": { "file-saver": "^2.0.5", diff --git a/package.json b/package.json index 3e10dbc..3c4d106 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "@rtidatascience/harness-vue", "author": "RTI CDS ", "private": false, - "version": "1.6.0", + "version": "1.7.0-0", "type": "module", "repository": { "type": "git", diff --git a/src/composable/composable.js b/src/composable/composable.js index 5d9b142..21d88c5 100644 --- a/src/composable/composable.js +++ b/src/composable/composable.js @@ -1,38 +1,38 @@ // https://stackoverflow.com/questions/72209080/vue-3-is-getcurrentinstance-deprecated -import { getCurrentInstance } from "vue"; import { useHarnessStore } from "../harness.js"; -export default function useHarnessComposable() { +/** + * Returns the current harness page store + * If a waypoint is provided, that store is returned + * If the route is provided and the route name matches a harness store key, that store is returned + * If there is no router and only a single harness page exists, that store is returned + * @param {any} waypoint=false a string matching a harness page store key + * @returns {Object} a pinia store representing a harness page + */ +export default function useHarnessComposable(waypoint = false) { const harnessMetadata = useHarnessStore(); - const vueInstance = getCurrentInstance(); + if (waypoint === false) { + let currentRoute = + harnessMetadata.optionsProvided?.router?.currentRoute?.name; - let waypoint = false; + // check for a vue-router route + if (currentRoute && harnessMetadata.getPages.includes(currentRoute)) { + waypoint = currentRoute; + } - // check for a vue-router route - if ( - vueInstance.appContext.config.globalProperties.$route?.name && - harnessMetadata.getPages.includes( - vueInstance.appContext.config.globalProperties.$route.name, - ) - ) { - waypoint = vueInstance.appContext.config.globalProperties.$route.name; + // if router is not installed and only a single harness page exists, use it as waypoint + if (harnessMetadata.getPages.length === 1 && !currentRoute) { + waypoint = harnessMetadata.pages[0]; + } } - // if router is not installed and only a single harness page exists, use it as waypoint if ( - (harnessMetadata.getPages.length === 1) & - !vueInstance.appContext.config.globalProperties.$route + waypoint && + Object.keys(harnessMetadata.getPageStores).includes(waypoint) ) { - waypoint = harnessMetadata.pages[0]; - } - - // // if a waypoint override was specified, use that - if (vueInstance.attrs["harness-waypoint"]) { - waypoint = vueInstance.attrs["harness-waypoint"]; - } - - if (waypoint) { return harnessMetadata.getPageStores[waypoint](); } - return waypoint; + console.error( + `The detected waypoint ${waypoint} is not a valid harness page.`, + ); } diff --git a/src/harness.js b/src/harness.js index c47d75c..c7adca9 100644 --- a/src/harness.js +++ b/src/harness.js @@ -8,7 +8,7 @@ const harnessPlugin = { install: (app, options) => { // create harness metadata store in pinia const harness = useHarnessStore(options.pinia); - + harness.optionsProvided = options; // validate page files const validatedPages = pages(options.pages); diff --git a/src/router/route.js b/src/router/route.js index 63f3382..2d18c0f 100644 --- a/src/router/route.js +++ b/src/router/route.js @@ -1,19 +1,21 @@ export default function createHarnessRoute(store, pageDefinition) { return { - path: "/" + pageDefinition.key, - name: pageDefinition.key, + path: `/${pageDefinition?.routePath || pageDefinition.key}`, + name: pageDefinition?.routeName || pageDefinition.key, component: pageDefinition.pageComponent, - props: pageDefinition.pageProps ? pageDefinition.pageProps : false, - beforeEnter: pageDefinition.loadData - ? (to, from, next) => { - if (from.name) { - store.clearData(); - } - if (to.name) { - store.loadData(); - } - next(); + props: pageDefinition?.pageProps, + beforeEnter: (to, from, next) => { + if (pageDefinition?.routeBeforeEnter) { + pageDefinition.routeBeforeEnter(to, from, next, store); + } else { + if (from.name) { + store.clearData(); } - : null, + if (to.name) { + store.loadData(); + } + next(); + } + }, }; } diff --git a/src/store/harnessStore.js b/src/store/harnessStore.js index 9ee6331..b784fe8 100644 --- a/src/store/harnessStore.js +++ b/src/store/harnessStore.js @@ -1,7 +1,12 @@ import { defineStore } from "pinia"; export default defineStore("harnessVue", { - state: () => ({ pages: [], pageDefinitions: {}, pageStores: {} }), + state: () => ({ + pages: [], + pageDefinitions: {}, + pageStores: {}, + optionsProvided: {}, + }), getters: { getPages() { return this.pages; @@ -12,6 +17,9 @@ export default defineStore("harnessVue", { getPageStores() { return this.pageStores; }, + getOptionsProvided() { + return this.optionsProvided; + }, }, actions: { addStore(key, definition, store) {