From 2742d5dcc9da8cf5a61c838bdf35f2f4803fc220 Mon Sep 17 00:00:00 2001 From: formfcw Date: Mon, 13 Apr 2026 13:55:15 +0200 Subject: [PATCH 1/4] update private-view slots and theme example for twelve-ui changes --- .../3.app-extensions/5.modules.md | 28 ++++++++-------- .../3.app-extensions/6.themes.md | 33 ++++++++++--------- 2 files changed, 30 insertions(+), 31 deletions(-) diff --git a/content/guides/09.extensions/3.app-extensions/5.modules.md b/content/guides/09.extensions/3.app-extensions/5.modules.md index 8675d273..071d7a27 100644 --- a/content/guides/09.extensions/3.app-extensions/5.modules.md +++ b/content/guides/09.extensions/3.app-extensions/5.modules.md @@ -23,19 +23,19 @@ The `index.js` or `index.ts` file exports an object that is read by Directus. It ## Entrypoint Example ```js -import { defineInterface } from '@directus/extensions-sdk' -import ModuleComponent from './module.vue'; +import { defineInterface } from "@directus/extensions-sdk"; +import ModuleComponent from "./module.vue"; export default defineInterface({ - id: 'custom', - name: 'Custom', - icon: 'box', - routes: [ - { - path: '', - component: ModuleComponent, - }, - ], + id: "custom", + name: "Custom", + icon: "box", + routes: [ + { + path: "", + component: ModuleComponent, + }, + ], }); ``` @@ -62,7 +62,6 @@ The route object uses the same syntax as Vue Router, defining each route as an o | `path` | The route path without the leading slash. | | `component` | A Vue component to be rendered for this route. | - The `routes` array should contain a root route with an empty path, which will load at the module's base route (the value of the module's `id`). Dynamic portions of the path can be defined using the `:param` syntax. ### Route Component @@ -71,7 +70,7 @@ The module route component will be rendered in the Data Studio when the route is ```vue @@ -357,19 +335,19 @@ To start using the new component in `module.vue`, add it to the `export default` ```js export default { - components: { // [!code ++] - PageNavigation, // [!code ++] - }, // [!code ++] - props: { - } -} + components: { + // [!code ++] + PageNavigation, // [!code ++] + }, // [!code ++] + props: {}, +}; ``` -Now this can be used in the template. After the `breadcrumbs`, add the following code: +Now this can be used in the template. Inside the `private-view`, add the following code: ```vue ``` @@ -394,11 +372,16 @@ In the template, create the HTML structure after the navigation and some new var ```html
- +
-
- +
+ {{ card.label }}
@@ -424,10 +407,10 @@ Add a new function to change the page called `change_page`. Import the `vue-rout import: ```js -import { ref, watch } from 'vue'; -import { useApi } from '@directus/extensions-sdk'; -import { useRouter } from 'vue-router'; // [!code ++] -import PageNavigation from './components/navigation.vue'; +import { ref, watch } from "vue"; +import { useApi } from "@directus/extensions-sdk"; +import { useRouter } from "vue-router"; // [!code ++] +import PageNavigation from "./components/navigation.vue"; ``` Assign the router to a variable: @@ -446,38 +429,48 @@ Create the function before the return and add the three new variables and the ne items. This will allow them to be used in the template. ```js -function change_page(to){ +function change_page(to) { const next = router.resolve(`${to}`); router.push(next); } -return { page_title, page_banner, page_cards, page_body, breadcrumb, all_pages, change_page }; +return { + page_title, + page_banner, + page_cards, + page_body, + all_pages, + change_page, +}; ``` Inside the render_page function, start adding content to these new variables. Here is an example using static content. ```js -switch(page) { - case 'home': - page_title.value = 'Home'; - page_banner.value = '/assets/83BD365C-C3CE-4015-B2AD-63EDA9E52A69?width=2000&height=563&fit=cover'; +switch (page) { + case "home": + page_title.value = "Home"; + page_banner.value = + "/assets/83BD365C-C3CE-4015-B2AD-63EDA9E52A69?width=2000&height=563&fit=cover"; page_cards.value = all_pages.value; - page_body.value = '

Lorem ipsum dolor sit amet

'; + page_body.value = "

Lorem ipsum dolor sit amet

"; break; - case 'hello-world': - page_title.value = 'Hello World'; - page_banner.value = '/assets/853B243D-A1BF-6051-B1BF-23EDA8E32A09?width=2000&height=563&fit=cover'; + case "hello-world": + page_title.value = "Hello World"; + page_banner.value = + "/assets/853B243D-A1BF-6051-B1BF-23EDA8E32A09?width=2000&height=563&fit=cover"; page_cards.value = all_pages.value; - page_body.value = '

Lorem ipsum dolor sit amet

'; + page_body.value = "

Lorem ipsum dolor sit amet

"; break; - case 'contact': - page_title.value = 'Contact Us'; - page_banner.value = '/assets/91CE173D-A1AD-4104-A1EC-74FCB8F41B58?width=2000&height=563&fit=cover'; + case "contact": + page_title.value = "Contact Us"; + page_banner.value = + "/assets/91CE173D-A1AD-4104-A1EC-74FCB8F41B58?width=2000&height=563&fit=cover"; page_cards.value = []; - page_body.value = '

Lorem ipsum dolor sit amet

'; + page_body.value = "

Lorem ipsum dolor sit amet

"; break; default: - page_title.value = '404: Not Found'; + page_title.value = "404: Not Found"; } ``` @@ -485,19 +478,22 @@ Or from the internal API providing you have a table with the fields `title`, `ba (WYSIWYG field): ```js -api.get(`/items/pages?fields=title,banner,content&filter[uri][_eq]=${page}`).then((rsp) => { - if(rsp.data.data){ - rsp.data.data.forEach(item => { - page_title.value = item.title; - page_banner.value = `/assets/${item.banner}?width=2000&height=563&fit=cover`; - page_body.value = item.content; - }); - } else { - page_title.value = "404: Not Found"; - } -}).catch((error) => { - console.log(error); -}); +api + .get(`/items/pages?fields=title,banner,content&filter[uri][_eq]=${page}`) + .then((rsp) => { + if (rsp.data.data) { + rsp.data.data.forEach((item) => { + page_title.value = item.title; + page_banner.value = `/assets/${item.banner}?width=2000&height=563&fit=cover`; + page_body.value = item.content; + }); + } else { + page_title.value = "404: Not Found"; + } + }) + .catch((error) => { + console.log(error); + }); ``` ### Work With Images @@ -528,13 +524,15 @@ export default function useDirectusToken(directusApi) { queryParams.push(`${key}=${value}`); } - return path.includes('?') ? `${path}&${queryParams.join('&')}` : `${path}?${queryParams.join('&')}`; + return path.includes("?") + ? `${path}&${queryParams.join("&")}` + : `${path}?${queryParams.join("&")}`; } function getToken() { return ( - directusApi.defaults?.headers?.['Authorization']?.split(' ')[1] || - directusApi.defaults?.headers?.common?.['Authorization']?.split(' ')[1] || + directusApi.defaults?.headers?.["Authorization"]?.split(" ")[1] || + directusApi.defaults?.headers?.common?.["Authorization"]?.split(" ")[1] || null ); } @@ -546,7 +544,7 @@ export default function useDirectusToken(directusApi) { access_token: accessToken, }); } -}; +} ``` This will use the access token of the current user to render the images. Alternatively, you can enable Read permissions @@ -555,7 +553,7 @@ on the Public role for the image ID or images with a specific folder ID to remov Import the function into the `module.vue` file to make it available in your script: ```js -import useDirectusToken from './use-directus-token'; +import useDirectusToken from "./use-directus-token"; ``` Include the function `AddTokenToURL` as a variable from the new script. @@ -573,7 +571,9 @@ setup(props) { Then wrap any internal images with this function: ```js -page_banner.value = addTokenToURL(`/assets/${item.banner}?width=2000&height=563&fit=cover`); +page_banner.value = addTokenToURL( + `/assets/${item.banner}?width=2000&height=563&fit=cover`, +); ``` ::callout{icon="material-symbols:info-outline} @@ -597,7 +597,7 @@ the following SCSS: width: 100%; max-width: 1024px; - &> div { + & > div { margin-bottom: var(--content-padding); } } @@ -694,22 +694,22 @@ images from within Directus to surface on the page. From here you can create con of the Directus platform. ```js [index.js] -import ModuleComponent from './module.vue'; +import ModuleComponent from "./module.vue"; export default { - id: 'landing-page', - name: 'Landing Page', - icon: 'rocket_launch', + id: "landing-page", + name: "Landing Page", + icon: "rocket_launch", routes: [ { - name: 'home', - path: '', + name: "home", + path: "", props: true, component: ModuleComponent, }, { - name: 'page', - path: ':page', + name: "page", + path: ":page", props: true, component: ModuleComponent, }, @@ -720,21 +720,23 @@ export default { ```vue [module.vue] ``` ```vue [components/navigation.vue]