From 6035aa62fd47b44349a2ea79fb3363a6c2faade7 Mon Sep 17 00:00:00 2001 From: The4thLaw Date: Wed, 27 Mar 2024 22:37:50 +0100 Subject: [PATCH] Migrated to vue unhead. Refs #156 --- source/demyo-vue-frontend/package-lock.json | 80 +++++++++++++++++++ source/demyo-vue-frontend/package.json | 1 + source/demyo-vue-frontend/src/App.vue | 8 +- .../src/components/SectionCard.vue | 1 - .../src/composables/model-index.js | 9 ++- source/demyo-vue-frontend/src/i18n.js | 3 +- .../src/layouts/DefaultLayout.vue | 28 ++++--- source/demyo-vue-frontend/src/main.js | 4 + .../src/mixins/model-edit.js | 21 +++-- .../src/pages/AboutDemyo.vue | 7 +- source/demyo-vue-frontend/src/pages/Home.vue | 8 +- .../src/pages/albums/AlbumIndex.vue | 6 ++ .../src/pages/albums/AlbumView.vue | 12 +-- .../src/pages/authors/AuthorEdit.vue | 4 + .../src/pages/authors/AuthorIndex.vue | 2 +- .../src/pages/authors/AuthorView.vue | 12 +-- .../src/pages/bindings/BindingEdit.vue | 4 + .../src/pages/bindings/BindingIndex.vue | 2 +- .../src/pages/bindings/BindingView.vue | 14 ++-- .../src/pages/collections/CollectionEdit.vue | 8 ++ .../src/pages/collections/CollectionView.vue | 17 ++-- .../DerivativeSourceEdit.vue | 4 + .../DerivativeSourceIndex.vue | 2 +- .../DerivativeSourceView.vue | 12 +-- .../derivativeTypes/DerivativeTypeEdit.vue | 4 + .../derivativeTypes/DerivativeTypeIndex.vue | 2 +- .../derivativeTypes/DerivativeTypeView.vue | 12 +-- .../src/pages/derivatives/DerivativeEdit.vue | 4 + .../src/pages/derivatives/DerivativeIndex.vue | 6 ++ .../pages/derivatives/DerivativeStickers.vue | 10 +-- .../src/pages/derivatives/DerivativeView.vue | 12 +-- .../src/pages/images/ImageDetect.vue | 12 +-- .../src/pages/images/ImageEdit.vue | 4 + .../src/pages/images/ImageIndex.vue | 2 +- .../src/pages/images/ImageView.vue | 12 +-- .../src/pages/manage/ManageExport.vue | 12 +-- .../src/pages/manage/ManageImport.vue | 10 +-- .../src/pages/publishers/PublisherEdit.vue | 4 + .../src/pages/publishers/PublisherIndex.vue | 2 +- .../src/pages/publishers/PublisherView.vue | 12 +-- .../src/pages/readers/ReaderConfig.vue | 5 ++ .../src/pages/readers/ReaderEdit.vue | 4 + .../src/pages/readers/ReaderFavourites.vue | 8 +- .../src/pages/readers/ReaderView.vue | 12 +-- .../src/pages/readers/ReadingList.vue | 8 +- .../src/pages/series/SeriesEdit.vue | 4 + .../src/pages/series/SeriesIndex.vue | 2 +- .../src/pages/series/SeriesView.vue | 12 +-- .../src/pages/tags/TagEdit.vue | 4 + .../src/pages/tags/TagIndex.vue | 8 +- .../src/pages/tags/TagView.vue | 12 +-- source/demyo-vue-frontend/src/router/index.js | 2 - 52 files changed, 318 insertions(+), 152 deletions(-) diff --git a/source/demyo-vue-frontend/package-lock.json b/source/demyo-vue-frontend/package-lock.json index cd8f0f2b..793b2192 100644 --- a/source/demyo-vue-frontend/package-lock.json +++ b/source/demyo-vue-frontend/package-lock.json @@ -9,6 +9,7 @@ "version": "3.1.0-SNAPSHOT", "dependencies": { "@mdi/font": "^5.9.55", + "@unhead/vue": "^1.9.1", "autoprefixer": "^10.4.18", "axios": "^1.3.1", "currency-symbol-map": "^5.0.1", @@ -1663,6 +1664,58 @@ "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", "dev": true }, + "node_modules/@unhead/dom": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@unhead/dom/-/dom-1.9.1.tgz", + "integrity": "sha512-5YVT8pyg7Mw8niWwklP8nFKK9WLIvaK4O3tXvqpW9OxSAexJG576bh6FR0hEtSDLBkJh+pI8mMMMIuzSdK/whA==", + "dependencies": { + "@unhead/schema": "1.9.1", + "@unhead/shared": "1.9.1" + }, + "funding": { + "url": "https://github.com/sponsors/harlan-zw" + } + }, + "node_modules/@unhead/schema": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@unhead/schema/-/schema-1.9.1.tgz", + "integrity": "sha512-wCJKNx4l837NEVMWP3MnUfkgsnMyuXwYs7+5VvbYzAWbnZSvQt/K10xDV0N7ft9RSlPfgukVVG+gtARm1kGVHQ==", + "dependencies": { + "hookable": "^5.5.3", + "zhead": "^2.2.4" + }, + "funding": { + "url": "https://github.com/sponsors/harlan-zw" + } + }, + "node_modules/@unhead/shared": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@unhead/shared/-/shared-1.9.1.tgz", + "integrity": "sha512-rZgzXzOeF4vu2bJJAkHJckgPgWGfpDA3/vesPhJIZGs2NkGYi9lDwMUeJ90HKCMJv1+JRAcPOokjRi6vRlnQpg==", + "dependencies": { + "@unhead/schema": "1.9.1" + }, + "funding": { + "url": "https://github.com/sponsors/harlan-zw" + } + }, + "node_modules/@unhead/vue": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@unhead/vue/-/vue-1.9.1.tgz", + "integrity": "sha512-clSKIkwtw26Lx5tR7ecJ/zvyFJkghvJU+jt2liQ4XYQb/Qaveh8L7gqsI1RKUuKaXAjlo2Z4Jpp1v9nHxA0heg==", + "dependencies": { + "@unhead/schema": "1.9.1", + "@unhead/shared": "1.9.1", + "hookable": "^5.5.3", + "unhead": "1.9.1" + }, + "funding": { + "url": "https://github.com/sponsors/harlan-zw" + }, + "peerDependencies": { + "vue": ">=2.7 || >=3" + } + }, "node_modules/@vitejs/plugin-vue": { "version": "5.0.4", "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.0.4.tgz", @@ -5763,6 +5816,11 @@ "minimalistic-crypto-utils": "^1.0.1" } }, + "node_modules/hookable": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz", + "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==" + }, "node_modules/html-tags": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", @@ -9703,6 +9761,20 @@ "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", "devOptional": true }, + "node_modules/unhead": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/unhead/-/unhead-1.9.1.tgz", + "integrity": "sha512-qTyA0V6xjUrIJp6KWs0CqAayw4K2DE7rh0GO0vmcC2YuF0HITO/3zkVtG7zhJUd5VeGgGCO/82zatDOOhMyneA==", + "dependencies": { + "@unhead/dom": "1.9.1", + "@unhead/schema": "1.9.1", + "@unhead/shared": "1.9.1", + "hookable": "^5.5.3" + }, + "funding": { + "url": "https://github.com/sponsors/harlan-zw" + } + }, "node_modules/unimport": { "version": "3.7.1", "resolved": "https://registry.npmjs.org/unimport/-/unimport-3.7.1.tgz", @@ -10822,6 +10894,14 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/zhead": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/zhead/-/zhead-2.2.4.tgz", + "integrity": "sha512-8F0OI5dpWIA5IGG5NHUg9staDwz/ZPxZtvGVf01j7vHqSyZ0raHY+78atOVxRqb73AotX22uV1pXt3gYSstGag==", + "funding": { + "url": "https://github.com/sponsors/harlan-zw" + } } } } diff --git a/source/demyo-vue-frontend/package.json b/source/demyo-vue-frontend/package.json index 111f6cbb..82b3610f 100644 --- a/source/demyo-vue-frontend/package.json +++ b/source/demyo-vue-frontend/package.json @@ -17,6 +17,7 @@ }, "dependencies": { "@mdi/font": "^5.9.55", + "@unhead/vue": "^1.9.1", "autoprefixer": "^10.4.18", "axios": "^1.3.1", "currency-symbol-map": "^5.0.1", diff --git a/source/demyo-vue-frontend/src/App.vue b/source/demyo-vue-frontend/src/App.vue index 0ea671f0..44524bc2 100644 --- a/source/demyo-vue-frontend/src/App.vue +++ b/source/demyo-vue-frontend/src/App.vue @@ -11,15 +11,13 @@ import { contextRoot } from '@/myenv' export default { name: 'DemyoApp', - metaInfo() { - const self = this + head() { return { - title: null, - titleTemplate: '%s — Demyo', + titleTemplate: (title) => !title ? 'Demyo' : `${title} – Demyo`, link: [ { rel: 'manifest', - href: `${contextRoot}manifest.json?lang=${self.$i18n.locale.replace(/-/, '_')}` + href: `${contextRoot}manifest.json?lang=${this.$i18n.locale.replace(/-/, '_')}` } ] } diff --git a/source/demyo-vue-frontend/src/components/SectionCard.vue b/source/demyo-vue-frontend/src/components/SectionCard.vue index 88e3813d..9d9a53d2 100644 --- a/source/demyo-vue-frontend/src/components/SectionCard.vue +++ b/source/demyo-vue-frontend/src/components/SectionCard.vue @@ -107,7 +107,6 @@ export default { padding-bottom: 0; > :last-child { - padding-bottom: 0; margin-bottom: 0; } } diff --git a/source/demyo-vue-frontend/src/composables/model-index.js b/source/demyo-vue-frontend/src/composables/model-index.js index 1d8f623f..dddf2aee 100644 --- a/source/demyo-vue-frontend/src/composables/model-index.js +++ b/source/demyo-vue-frontend/src/composables/model-index.js @@ -1,10 +1,17 @@ import { useUiStore } from '@/stores/ui' +import { useHead } from '@unhead/vue' +import { useI18n } from 'vue-i18n' /** * Composable for simple model indexes loading data from the service. * @param {AbstractModelService} serviceInstance The service to use to fetch the data. + * @param {string} titleKey the page title key */ -export function useSimpleIndex(serviceInstance) { +export function useSimpleIndex(serviceInstance, titleKey) { + useHead({ + title: useI18n().t(titleKey) + }) + const uiStore = useUiStore() const modelList = ref([]) diff --git a/source/demyo-vue-frontend/src/i18n.js b/source/demyo-vue-frontend/src/i18n.js index 23b41a96..b79c17fa 100644 --- a/source/demyo-vue-frontend/src/i18n.js +++ b/source/demyo-vue-frontend/src/i18n.js @@ -47,7 +47,8 @@ const i18n = createI18n({ locale: simpleLocale, fallbackLocale: fallbackLanguage, messages: loadLocaleMessages(), - datetimeFormats + datetimeFormats, + legacy: false }) setHtmlLang(selectedLocale) console.log(`Initialized i18n with '${selectedLocale}' as default language and '${fallbackLanguage}' as fallback`) diff --git a/source/demyo-vue-frontend/src/layouts/DefaultLayout.vue b/source/demyo-vue-frontend/src/layouts/DefaultLayout.vue index b084462c..c3260ff6 100644 --- a/source/demyo-vue-frontend/src/layouts/DefaultLayout.vue +++ b/source/demyo-vue-frontend/src/layouts/DefaultLayout.vue @@ -146,21 +146,12 @@ export default { mixins: [quicksearch], - metaInfo() { - const self = this - - return { - changed(newInfo, addedTags, removedTags) { - self.pageTitle = newInfo.titleChunk - } - } - }, - data() { return { uiStore: useUiStore(), pageTitle: 'Demyo', + pageTitleObserver: null, demyoCodename: demyoCodename, mainMenu: false, @@ -189,6 +180,23 @@ export default { } }, + mounted() { + // Monitor the page title for changes. unhead doesn't seem to have an event for this + this.pageTitleObserver = new MutationObserver((mutations) => { + const pageTitle = mutations[0].target.text.replace(/ – Demyo$/, '') + this.pageTitle = pageTitle + }) + this.pageTitleObserver.observe( + document.querySelector('title'), + { subtree: true, characterData: true, childList: true } + ) + }, + + unmounted() { + this.pageTitleObserver.disconnect() + this.pageTitleObserver = null + }, + methods: { enterSearch() { this.$refs.menuSearch.blur() diff --git a/source/demyo-vue-frontend/src/main.js b/source/demyo-vue-frontend/src/main.js index 75707b5b..d486ebbd 100644 --- a/source/demyo-vue-frontend/src/main.js +++ b/source/demyo-vue-frontend/src/main.js @@ -2,6 +2,7 @@ import '@mdi/font/css/materialdesignicons.css' import 'roboto-fontface/css/roboto/roboto-fontface.css' import { createApp } from 'vue' // From https://gitlab.com/totol.toolsuite/vue-3-fullscreen-image +import { VueHeadMixin, createHead } from '@unhead/vue' import { fullscreenImagePlugin } from 'vue-3-fullscreen-image-directive-plugin' import 'vue-3-fullscreen-image-directive-plugin/style.css' import App from './App.vue' @@ -29,6 +30,9 @@ app.use(i18n) app.use(vuetify) app.use(fullscreenImagePlugin) +app.use(createHead()) +app.mixin(VueHeadMixin) + // Add the ID to the body element to ease style overrides document.getElementsByTagName('body')[0].id = 'demyo' diff --git a/source/demyo-vue-frontend/src/mixins/model-edit.js b/source/demyo-vue-frontend/src/mixins/model-edit.js index f3e6c443..d224d9c2 100644 --- a/source/demyo-vue-frontend/src/mixins/model-edit.js +++ b/source/demyo-vue-frontend/src/mixins/model-edit.js @@ -1,16 +1,6 @@ import { useUiStore } from '@/stores/ui' export default { - metaInfo() { - return { - title: this.initialized - ? (this.parsedId - ? this.$t(this.mixinConfig.modelEdit.titleKeys.edit) - : this.$t(this.mixinConfig.modelEdit.titleKeys.add)) - : '' - } - }, - data() { return { initialized: false, @@ -18,6 +8,16 @@ export default { } }, + computed: { + pageTitle() { + return this.initialized + ? (this.parsedId + ? this.$t(this.mixinConfig.modelEdit.titleKeys.edit) + : this.$t(this.mixinConfig.modelEdit.titleKeys.add)) + : null + } + }, + watch: { $route: 'fetchDataInternal' }, @@ -106,6 +106,5 @@ export default { this.fetchDataInternal() } } - } } diff --git a/source/demyo-vue-frontend/src/pages/AboutDemyo.vue b/source/demyo-vue-frontend/src/pages/AboutDemyo.vue index 3f97b521..91ad437b 100644 --- a/source/demyo-vue-frontend/src/pages/AboutDemyo.vue +++ b/source/demyo-vue-frontend/src/pages/AboutDemyo.vue @@ -159,10 +159,15 @@ diff --git a/source/demyo-vue-frontend/src/pages/authors/AuthorView.vue b/source/demyo-vue-frontend/src/pages/authors/AuthorView.vue index ae470a4c..4b6836d5 100644 --- a/source/demyo-vue-frontend/src/pages/authors/AuthorView.vue +++ b/source/demyo-vue-frontend/src/pages/authors/AuthorView.vue @@ -89,12 +89,6 @@ export default { mixins: [modelViewMixin], - metaInfo() { - return { - title: this.author.identifyingName - } - }, - data() { return { mainLoading: true, @@ -107,6 +101,12 @@ export default { } }, + head() { + return { + title: this.author.identifyingName + } + }, + computed: { albums() { return this.authorAlbums.albums || [] diff --git a/source/demyo-vue-frontend/src/pages/bindings/BindingEdit.vue b/source/demyo-vue-frontend/src/pages/bindings/BindingEdit.vue index f62ca691..304b44cc 100644 --- a/source/demyo-vue-frontend/src/pages/bindings/BindingEdit.vue +++ b/source/demyo-vue-frontend/src/pages/bindings/BindingEdit.vue @@ -55,6 +55,10 @@ export default { } }, + head() { + return { title: this.pageTitle } + }, + methods: { async fetchData() { if (this.parsedId) { diff --git a/source/demyo-vue-frontend/src/pages/bindings/BindingIndex.vue b/source/demyo-vue-frontend/src/pages/bindings/BindingIndex.vue index 1570130c..c8285a8d 100644 --- a/source/demyo-vue-frontend/src/pages/bindings/BindingIndex.vue +++ b/source/demyo-vue-frontend/src/pages/bindings/BindingIndex.vue @@ -15,5 +15,5 @@ import { useSimpleIndex } from '@/composables/model-index' import bindingService from '@/services/binding-service' -const { modelList } = useSimpleIndex(bindingService) +const { modelList } = useSimpleIndex(bindingService, 'title.index.binding') diff --git a/source/demyo-vue-frontend/src/pages/bindings/BindingView.vue b/source/demyo-vue-frontend/src/pages/bindings/BindingView.vue index 2bd68fdb..4bf8fae8 100644 --- a/source/demyo-vue-frontend/src/pages/bindings/BindingView.vue +++ b/source/demyo-vue-frontend/src/pages/bindings/BindingView.vue @@ -42,7 +42,7 @@ import { deleteStub } from '@/helpers/actions' import modelViewMixin from '@/mixins/model-view' import bindingService from '@/services/binding-service' -// TODO: Vue 3: Try to extract such simple views in a composable (after the appTasks are migrated to teleport) +// TODO: Vue 3: Try to extract such simple views in a composable export default { name: 'BindingView', @@ -54,12 +54,6 @@ export default { mixins: [modelViewMixin], - metaInfo() { - return { - title: this.binding.identifyingName - } - }, - data() { return { binding: {}, @@ -68,6 +62,12 @@ export default { } }, + head() { + return { + title: this.binding.identifyingName + } + }, + methods: { async fetchData() { const bindingP = bindingService.findById(this.parsedId) diff --git a/source/demyo-vue-frontend/src/pages/collections/CollectionEdit.vue b/source/demyo-vue-frontend/src/pages/collections/CollectionEdit.vue index 882cc8c0..15fba9c6 100644 --- a/source/demyo-vue-frontend/src/pages/collections/CollectionEdit.vue +++ b/source/demyo-vue-frontend/src/pages/collections/CollectionEdit.vue @@ -23,10 +23,13 @@ + @@ -105,8 +108,13 @@ export default { } }, + head() { + return { title: this.pageTitle } + }, + methods: { async fetchData() { + console.log('XXX', this.head2) if (this.parsedId) { this.collection = await collectionService.findById(this.parsedId) } diff --git a/source/demyo-vue-frontend/src/pages/collections/CollectionView.vue b/source/demyo-vue-frontend/src/pages/collections/CollectionView.vue index 07c0bbcd..3d6f61d7 100644 --- a/source/demyo-vue-frontend/src/pages/collections/CollectionView.vue +++ b/source/demyo-vue-frontend/src/pages/collections/CollectionView.vue @@ -76,12 +76,6 @@ export default { mixins: [modelViewMixin], - metaInfo() { - return { - title: this.collection.identifyingName - } - }, - data() { return { collection: {}, @@ -90,6 +84,13 @@ export default { } }, + head() { + return { + title: this.collection + ? `${this.collection.identifyingName} – ${this.collection.publisher?.identifyingName}` : null + } + }, + methods: { async fetchData() { const collectionP = collectionService.findById(this.parsedId) @@ -98,8 +99,8 @@ export default { }, deleteCollection() { - deleteStub(this, - () => collectionService.deleteModel(this.collection.id), + void deleteStub(this, + async () => collectionService.deleteModel(this.collection.id), 'quickTasks.delete.collection.confirm.done', 'PublisherIndex') } diff --git a/source/demyo-vue-frontend/src/pages/derivativeSources/DerivativeSourceEdit.vue b/source/demyo-vue-frontend/src/pages/derivativeSources/DerivativeSourceEdit.vue index d25f6ef6..6f218995 100644 --- a/source/demyo-vue-frontend/src/pages/derivativeSources/DerivativeSourceEdit.vue +++ b/source/demyo-vue-frontend/src/pages/derivativeSources/DerivativeSourceEdit.vue @@ -105,6 +105,10 @@ export default { } }, + head() { + return { title: this.pageTitle } + }, + methods: { async fetchData() { if (this.parsedId) { diff --git a/source/demyo-vue-frontend/src/pages/derivativeSources/DerivativeSourceIndex.vue b/source/demyo-vue-frontend/src/pages/derivativeSources/DerivativeSourceIndex.vue index ad8f6230..3af23cd4 100644 --- a/source/demyo-vue-frontend/src/pages/derivativeSources/DerivativeSourceIndex.vue +++ b/source/demyo-vue-frontend/src/pages/derivativeSources/DerivativeSourceIndex.vue @@ -17,5 +17,5 @@ import { useSimpleIndex } from '@/composables/model-index' import sourceService from '@/services/derivative-source-service' -const { modelList } = useSimpleIndex(sourceService) +const { modelList } = useSimpleIndex(sourceService, 'title.index.derivativeSource') diff --git a/source/demyo-vue-frontend/src/pages/derivativeSources/DerivativeSourceView.vue b/source/demyo-vue-frontend/src/pages/derivativeSources/DerivativeSourceView.vue index d35fe86f..47b44dda 100644 --- a/source/demyo-vue-frontend/src/pages/derivativeSources/DerivativeSourceView.vue +++ b/source/demyo-vue-frontend/src/pages/derivativeSources/DerivativeSourceView.vue @@ -96,12 +96,6 @@ export default { mixins: [modelViewMixin], - metaInfo() { - return { - title: this.source.identifyingName - } - }, - data() { return { source: {}, @@ -110,6 +104,12 @@ export default { } }, + head() { + return { + title: this.source.identifyingName + } + }, + computed: { phoneLink() { if (!this.source.phoneNumber) { diff --git a/source/demyo-vue-frontend/src/pages/derivativeTypes/DerivativeTypeEdit.vue b/source/demyo-vue-frontend/src/pages/derivativeTypes/DerivativeTypeEdit.vue index 393539f1..65c7a4d0 100644 --- a/source/demyo-vue-frontend/src/pages/derivativeTypes/DerivativeTypeEdit.vue +++ b/source/demyo-vue-frontend/src/pages/derivativeTypes/DerivativeTypeEdit.vue @@ -55,6 +55,10 @@ export default { } }, + head() { + return { title: this.pageTitle } + }, + methods: { async fetchData() { if (this.parsedId) { diff --git a/source/demyo-vue-frontend/src/pages/derivativeTypes/DerivativeTypeIndex.vue b/source/demyo-vue-frontend/src/pages/derivativeTypes/DerivativeTypeIndex.vue index 5129ba19..af5a523f 100644 --- a/source/demyo-vue-frontend/src/pages/derivativeTypes/DerivativeTypeIndex.vue +++ b/source/demyo-vue-frontend/src/pages/derivativeTypes/DerivativeTypeIndex.vue @@ -15,5 +15,5 @@ import { useSimpleIndex } from '@/composables/model-index' import typeService from '@/services/derivative-type-service' -const { modelList } = useSimpleIndex(typeService) +const { modelList } = useSimpleIndex(typeService, 'title.index.derivativeType') diff --git a/source/demyo-vue-frontend/src/pages/derivativeTypes/DerivativeTypeView.vue b/source/demyo-vue-frontend/src/pages/derivativeTypes/DerivativeTypeView.vue index e2337f8e..f7f0d984 100644 --- a/source/demyo-vue-frontend/src/pages/derivativeTypes/DerivativeTypeView.vue +++ b/source/demyo-vue-frontend/src/pages/derivativeTypes/DerivativeTypeView.vue @@ -53,12 +53,6 @@ export default { mixins: [modelViewMixin], - metaInfo() { - return { - title: this.type.identifyingName - } - }, - data() { return { type: {}, @@ -67,6 +61,12 @@ export default { } }, + head() { + return { + title: this.type.identifyingName + } + }, + methods: { async fetchData() { const typeP = typeService.findById(this.parsedId) diff --git a/source/demyo-vue-frontend/src/pages/derivatives/DerivativeEdit.vue b/source/demyo-vue-frontend/src/pages/derivatives/DerivativeEdit.vue index d748e7e1..a4b470c5 100644 --- a/source/demyo-vue-frontend/src/pages/derivatives/DerivativeEdit.vue +++ b/source/demyo-vue-frontend/src/pages/derivatives/DerivativeEdit.vue @@ -191,6 +191,10 @@ export default { } }, + head() { + return { title: this.pageTitle } + }, + methods: { oneNotNull() { // In addition to this rule, an @input handler forces full form validation when one of the relevant diff --git a/source/demyo-vue-frontend/src/pages/derivatives/DerivativeIndex.vue b/source/demyo-vue-frontend/src/pages/derivatives/DerivativeIndex.vue index 1cad3024..ef42fca0 100644 --- a/source/demyo-vue-frontend/src/pages/derivatives/DerivativeIndex.vue +++ b/source/demyo-vue-frontend/src/pages/derivatives/DerivativeIndex.vue @@ -26,8 +26,14 @@ import { retrieveFilter } from '@/helpers/filter' import derivativeService from '@/services/derivative-service' import { useUiStore } from '@/stores/ui' +import { useHead } from '@unhead/vue' +import { useI18n } from 'vue-i18n' import { useRoute } from 'vue-router' +useHead({ + title: useI18n().t('title.index.derivative') +}) + const uiStore = useUiStore() const route = useRoute() diff --git a/source/demyo-vue-frontend/src/pages/derivatives/DerivativeStickers.vue b/source/demyo-vue-frontend/src/pages/derivatives/DerivativeStickers.vue index fbaef8e1..022a67f2 100644 --- a/source/demyo-vue-frontend/src/pages/derivatives/DerivativeStickers.vue +++ b/source/demyo-vue-frontend/src/pages/derivatives/DerivativeStickers.vue @@ -47,16 +47,16 @@ import derivativeService from '@/services/derivative-service' export default { name: 'DerivativeStickers', - metaInfo() { + data() { return { - title: this.$t('title.index.derivative.stickers') + initialized: false, + derivatives: [] } }, - data() { + head() { return { - initialized: false, - derivatives: [] + title: this.$t('title.index.derivative.stickers') } }, diff --git a/source/demyo-vue-frontend/src/pages/derivatives/DerivativeView.vue b/source/demyo-vue-frontend/src/pages/derivatives/DerivativeView.vue index 714e6db6..773fe98b 100644 --- a/source/demyo-vue-frontend/src/pages/derivatives/DerivativeView.vue +++ b/source/demyo-vue-frontend/src/pages/derivatives/DerivativeView.vue @@ -198,12 +198,6 @@ export default { mixins: [i18nMixin, modelViewMixin], - metaInfo() { - return { - title: this.derivative.identifyingName - } - }, - data() { return { uiStore: useUiStore(), @@ -219,6 +213,12 @@ export default { } }, + head() { + return { + title: this.derivative.identifyingName + } + }, + computed: { hasPrices() { return this.derivative.prices && this.derivative.prices.length > 0 diff --git a/source/demyo-vue-frontend/src/pages/images/ImageDetect.vue b/source/demyo-vue-frontend/src/pages/images/ImageDetect.vue index 5431bfad..f3270f20 100644 --- a/source/demyo-vue-frontend/src/pages/images/ImageDetect.vue +++ b/source/demyo-vue-frontend/src/pages/images/ImageDetect.vue @@ -46,12 +46,6 @@ export default { SectionCard }, - metaInfo() { - return { - title: this.$t('title.add.image') - } - }, - data() { return { uiStore: useUiStore(), @@ -65,6 +59,12 @@ export default { } }, + head() { + return { + title: this.$t('title.add.image') + } + }, + created() { this.fetchData() }, diff --git a/source/demyo-vue-frontend/src/pages/images/ImageEdit.vue b/source/demyo-vue-frontend/src/pages/images/ImageEdit.vue index 0fc8849c..e87503ac 100644 --- a/source/demyo-vue-frontend/src/pages/images/ImageEdit.vue +++ b/source/demyo-vue-frontend/src/pages/images/ImageEdit.vue @@ -56,6 +56,10 @@ export default { } }, + head() { + return { title: this.pageTitle } + }, + methods: { async fetchData() { this.image = await imageService.findById(this.parsedId) diff --git a/source/demyo-vue-frontend/src/pages/images/ImageIndex.vue b/source/demyo-vue-frontend/src/pages/images/ImageIndex.vue index 974846e7..ce8728b2 100644 --- a/source/demyo-vue-frontend/src/pages/images/ImageIndex.vue +++ b/source/demyo-vue-frontend/src/pages/images/ImageIndex.vue @@ -15,5 +15,5 @@ import { useSimpleIndex } from '@/composables/model-index' import imageService from '@/services/image-service' -const { modelList } = useSimpleIndex(imageService) +const { modelList } = useSimpleIndex(imageService, 'title.index.image') diff --git a/source/demyo-vue-frontend/src/pages/images/ImageView.vue b/source/demyo-vue-frontend/src/pages/images/ImageView.vue index dc6b227f..6718b887 100644 --- a/source/demyo-vue-frontend/src/pages/images/ImageView.vue +++ b/source/demyo-vue-frontend/src/pages/images/ImageView.vue @@ -73,12 +73,6 @@ export default { mixins: [modelViewMixin], - metaInfo() { - return { - title: this.image.identifyingName - } - }, - data() { return { mainLoading: true, @@ -89,6 +83,12 @@ export default { } }, + head() { + return { + title: this.image.identifyingName + } + }, + computed: { imageUrl() { return getBaseImageUrl(this.image) diff --git a/source/demyo-vue-frontend/src/pages/manage/ManageExport.vue b/source/demyo-vue-frontend/src/pages/manage/ManageExport.vue index 16f97012..3ba5f22e 100644 --- a/source/demyo-vue-frontend/src/pages/manage/ManageExport.vue +++ b/source/demyo-vue-frontend/src/pages/manage/ManageExport.vue @@ -30,12 +30,6 @@ export default { SectionCard }, - metaInfo() { - return { - title: this.$t('title.manage.export.select') - } - }, - data() { return { format: 'XML', @@ -49,6 +43,12 @@ export default { } }, + head() { + return { + title: this.$t('title.manage.export.select') + } + }, + computed: { postUrl() { return apiRoot + 'manage/export' diff --git a/source/demyo-vue-frontend/src/pages/manage/ManageImport.vue b/source/demyo-vue-frontend/src/pages/manage/ManageImport.vue index fb4e2a96..9a5e283b 100644 --- a/source/demyo-vue-frontend/src/pages/manage/ManageImport.vue +++ b/source/demyo-vue-frontend/src/pages/manage/ManageImport.vue @@ -26,16 +26,16 @@ export default { SectionCard }, - metaInfo() { + data() { return { - title: this.$t('title.manage.import.select') + uiStore: useUiStore(), + file: null } }, - data() { + head() { return { - uiStore: useUiStore(), - file: null + title: this.$t('title.manage.import.select') } }, diff --git a/source/demyo-vue-frontend/src/pages/publishers/PublisherEdit.vue b/source/demyo-vue-frontend/src/pages/publishers/PublisherEdit.vue index ccfd4d44..a5224712 100644 --- a/source/demyo-vue-frontend/src/pages/publishers/PublisherEdit.vue +++ b/source/demyo-vue-frontend/src/pages/publishers/PublisherEdit.vue @@ -91,6 +91,10 @@ export default { } }, + head() { + return { title: this.pageTitle } + }, + methods: { async fetchData() { if (this.parsedId) { diff --git a/source/demyo-vue-frontend/src/pages/publishers/PublisherIndex.vue b/source/demyo-vue-frontend/src/pages/publishers/PublisherIndex.vue index a4cfbd6b..30f994e4 100644 --- a/source/demyo-vue-frontend/src/pages/publishers/PublisherIndex.vue +++ b/source/demyo-vue-frontend/src/pages/publishers/PublisherIndex.vue @@ -18,5 +18,5 @@ import PublisherCard from '@/components/PublisherCard.vue' import { useSimpleIndex } from '@/composables/model-index' import publisherService from '@/services/publisher-service' -const { modelList } = useSimpleIndex(publisherService) +const { modelList } = useSimpleIndex(publisherService, 'title.index.publisher') diff --git a/source/demyo-vue-frontend/src/pages/publishers/PublisherView.vue b/source/demyo-vue-frontend/src/pages/publishers/PublisherView.vue index 9d483bcb..e8d742a3 100644 --- a/source/demyo-vue-frontend/src/pages/publishers/PublisherView.vue +++ b/source/demyo-vue-frontend/src/pages/publishers/PublisherView.vue @@ -92,12 +92,6 @@ export default { mixins: [modelViewMixin], - metaInfo() { - return { - title: this.publisher.identifyingName - } - }, - data() { return { publisher: {}, @@ -106,6 +100,12 @@ export default { } }, + head() { + return { + title: this.publisher.identifyingName + } + }, + computed: { collectionCount() { if (!this.publisher?.collections) { diff --git a/source/demyo-vue-frontend/src/pages/readers/ReaderConfig.vue b/source/demyo-vue-frontend/src/pages/readers/ReaderConfig.vue index 91d3fdf5..682ecb34 100644 --- a/source/demyo-vue-frontend/src/pages/readers/ReaderConfig.vue +++ b/source/demyo-vue-frontend/src/pages/readers/ReaderConfig.vue @@ -85,6 +85,11 @@ export default { } } }, + + head() { + return { title: this.pageTitle } + }, + methods: { async fetchData() { this.reader = await readerService.findById(this.parsedId) diff --git a/source/demyo-vue-frontend/src/pages/readers/ReaderEdit.vue b/source/demyo-vue-frontend/src/pages/readers/ReaderEdit.vue index 9e55e0ea..5bd1e30b 100644 --- a/source/demyo-vue-frontend/src/pages/readers/ReaderEdit.vue +++ b/source/demyo-vue-frontend/src/pages/readers/ReaderEdit.vue @@ -63,6 +63,10 @@ export default { } }, + head() { + return { title: this.pageTitle } + }, + methods: { async fetchData() { if (this.parsedId) { diff --git a/source/demyo-vue-frontend/src/pages/readers/ReaderFavourites.vue b/source/demyo-vue-frontend/src/pages/readers/ReaderFavourites.vue index c6055aae..66900e3c 100644 --- a/source/demyo-vue-frontend/src/pages/readers/ReaderFavourites.vue +++ b/source/demyo-vue-frontend/src/pages/readers/ReaderFavourites.vue @@ -19,15 +19,15 @@ export default { // We can reuse the 'view' mixin even though it's not really a view : it is generic enough mixins: [modelViewMixin], - metaInfo() { + data() { return { - title: this.$t('title.reader.favourites') + albums: [] } }, - data() { + head() { return { - albums: [] + title: this.$t('title.reader.favourites') } }, diff --git a/source/demyo-vue-frontend/src/pages/readers/ReaderView.vue b/source/demyo-vue-frontend/src/pages/readers/ReaderView.vue index ef00e7d1..1dd75d95 100644 --- a/source/demyo-vue-frontend/src/pages/readers/ReaderView.vue +++ b/source/demyo-vue-frontend/src/pages/readers/ReaderView.vue @@ -63,12 +63,6 @@ export default { mixins: [modelViewMixin], - metaInfo() { - return { - title: this.reader.identifyingName - } - }, - data() { return { reader: {}, @@ -77,6 +71,12 @@ export default { } }, + head() { + return { + title: this.reader.identifyingName + } + }, + computed: { letter() { return this.reader.name?.charAt(0) diff --git a/source/demyo-vue-frontend/src/pages/readers/ReadingList.vue b/source/demyo-vue-frontend/src/pages/readers/ReadingList.vue index e467ddee..bb714d8b 100644 --- a/source/demyo-vue-frontend/src/pages/readers/ReadingList.vue +++ b/source/demyo-vue-frontend/src/pages/readers/ReadingList.vue @@ -19,15 +19,15 @@ export default { // We can reuse the 'view' mixin even though it's not really a view : it is generic enough mixins: [modelViewMixin], - metaInfo() { + data() { return { - title: this.$t('title.reader.readingList') + albums: [] } }, - data() { + head() { return { - albums: [] + title: this.$t('title.reader.readingList') } }, diff --git a/source/demyo-vue-frontend/src/pages/series/SeriesEdit.vue b/source/demyo-vue-frontend/src/pages/series/SeriesEdit.vue index 4f8ff5a3..35c15789 100644 --- a/source/demyo-vue-frontend/src/pages/series/SeriesEdit.vue +++ b/source/demyo-vue-frontend/src/pages/series/SeriesEdit.vue @@ -103,6 +103,10 @@ export default { } }, + head() { + return { title: this.pageTitle } + }, + methods: { async fetchData() { const allSeriesP = seriesService.findForList() diff --git a/source/demyo-vue-frontend/src/pages/series/SeriesIndex.vue b/source/demyo-vue-frontend/src/pages/series/SeriesIndex.vue index c35e3d69..a6b43618 100644 --- a/source/demyo-vue-frontend/src/pages/series/SeriesIndex.vue +++ b/source/demyo-vue-frontend/src/pages/series/SeriesIndex.vue @@ -18,5 +18,5 @@ import { useSimpleIndex } from '@/composables/model-index' import seriesService from '@/services/series-service' -const { modelList } = useSimpleIndex(seriesService) +const { modelList } = useSimpleIndex(seriesService, 'title.index.series') diff --git a/source/demyo-vue-frontend/src/pages/series/SeriesView.vue b/source/demyo-vue-frontend/src/pages/series/SeriesView.vue index 9b50cf76..445b2387 100644 --- a/source/demyo-vue-frontend/src/pages/series/SeriesView.vue +++ b/source/demyo-vue-frontend/src/pages/series/SeriesView.vue @@ -195,12 +195,6 @@ export default { mixins: [modelViewMixin], - metaInfo() { - return { - title: this.series.identifyingName - } - }, - data() { return { series: {}, @@ -214,6 +208,12 @@ export default { } }, + head() { + return { + title: this.series.identifyingName + } + }, + computed: { ownedIds() { if (!this.series.albumIds) { diff --git a/source/demyo-vue-frontend/src/pages/tags/TagEdit.vue b/source/demyo-vue-frontend/src/pages/tags/TagEdit.vue index 1a791159..9a1f8b02 100644 --- a/source/demyo-vue-frontend/src/pages/tags/TagEdit.vue +++ b/source/demyo-vue-frontend/src/pages/tags/TagEdit.vue @@ -97,6 +97,10 @@ export default { } }, + head() { + return { title: this.pageTitle } + }, + computed: { style() { const style = {} diff --git a/source/demyo-vue-frontend/src/pages/tags/TagIndex.vue b/source/demyo-vue-frontend/src/pages/tags/TagIndex.vue index 5ad6cbfb..00076243 100644 --- a/source/demyo-vue-frontend/src/pages/tags/TagIndex.vue +++ b/source/demyo-vue-frontend/src/pages/tags/TagIndex.vue @@ -16,15 +16,15 @@ import { useUiStore } from '@/stores/ui' export default { name: 'TagIndex', - metaInfo() { + data() { return { - title: this.$t('title.index.tag') + tags: [] } }, - data() { + head() { return { - tags: [] + title: this.$t('title.index.tag') } }, diff --git a/source/demyo-vue-frontend/src/pages/tags/TagView.vue b/source/demyo-vue-frontend/src/pages/tags/TagView.vue index aca41a32..0388cf90 100644 --- a/source/demyo-vue-frontend/src/pages/tags/TagView.vue +++ b/source/demyo-vue-frontend/src/pages/tags/TagView.vue @@ -64,12 +64,6 @@ export default { mixins: [modelViewMixin], - metaInfo() { - return { - title: this.tag.identifyingName - } - }, - data() { return { tag: {}, @@ -78,6 +72,12 @@ export default { } }, + head() { + return { + title: this.tag.identifyingName + } + }, + computed: { style() { const style = {} diff --git a/source/demyo-vue-frontend/src/router/index.js b/source/demyo-vue-frontend/src/router/index.js index b4af7766..b5ebecfe 100644 --- a/source/demyo-vue-frontend/src/router/index.js +++ b/source/demyo-vue-frontend/src/router/index.js @@ -16,8 +16,6 @@ import readerRoutes from './readers' import seriesRoutes from './series' import tagRoutes from './tags' -// TODO: Vue 3: restore equivalent to vue-meta - const routes = [ { path: '/',