diff --git a/lib/plugin.js b/lib/plugin.js index ff2d69a8..e1373681 100644 --- a/lib/plugin.js +++ b/lib/plugin.js @@ -16,6 +16,7 @@ class DrupalCe { */ this.$currentPage = Vue.observable({ title: null, + statusCode: null, metadata: { meta: [], link: [] @@ -26,13 +27,6 @@ class DrupalCe { localTasks: null, settings: {}, }) - - /** - * Returns an object for rendering as Vue component. - */ - this.$currentPage.contentComponent = () => { - return { name: 'DrupalContent', template: this.$currentPage.content } - } } /** @@ -54,23 +48,49 @@ class DrupalCe { if (this.options.addRequestContentFormat) { config.params._content_format = config.params._content_format ?? this.options.addRequestContentFormat } - const data = await this.$axios.get(path, config).then(res => res.data) + const { data, status } = await this.$axios.get(path, config) if (!data.title || !data.content) { return this.context.error({ statusCode: 422, message: 'Malformed API response. Please make sure to install Custom Elements renderer: https://www.drupal.org/project/lupus_ce_renderer'}) } - this.$currentPage.title = data.title - this.$currentPage.metatags = this.processMetatags(data.metatags) - this.$currentPage.content = data.content - this.$currentPage.breadcrumbs = Array.isArray(data.breadcrumbs) ? data.breadcrumbs : [], - this.$currentPage.messages = this.processMessages(data.messages) - this.$currentPage.localTasks = data.local_tasks - this.$currentPage.settings = data.settings + this.processPageResponse(data, status) return this.$currentPage - } catch (err) { - this.context.error(err) - return err + } catch (error) { + if (error.response) { + // Request made and server responded. If we get a proper Drupal error + // page, apply it and propagate the error code. + if (error.response.data && error.response.data.title && error.response.data.content) { + this.processPageResponse(error.response.data, error.response.status) + } else { + this.context.error({ statusCode: error.response.status, message: error.message }) + } + } else if (error.request) { + // The request was made but no response was received. Usually this + // means a network error. + this.context.error({ statusCode: 503, message: error.message }) + } else { + // Some other error happened, so be verbose about it. + this.context.error({ statusCode: 400, message: error.message }) + } + } + } + + /** + * Updates $currentpage based upon response data. + */ + processPageResponse(data, status) { + this.$currentPage.statusCode = status + this.$currentPage.title = data.title + this.$currentPage.metatags = this.processMetatags(data.metatags) + this.$currentPage.content = data.content + this.$currentPage.breadcrumbs = Array.isArray(data.breadcrumbs) ? data.breadcrumbs : [], + this.$currentPage.messages = this.processMessages(data.messages) + this.$currentPage.localTasks = data.local_tasks + this.$currentPage.settings = data.settings + // When possible, propagate status code (only in server mode). + if (this.context.res) { + this.context.res.statusCode = status } } @@ -133,10 +153,17 @@ export default async function (context, inject) { const drupal = new DrupalCe($axiosDrupal, context, options) - const { nuxtState = {} } = context || {} + if (process.server) { + context.beforeNuxtRender(({ nuxtState }) => { + // Prepare data for client-side hydration. + nuxtState.drupal = drupal.$currentPage + }) + } - if (process.client && !nuxtState.drupal) { - await drupal.fetchPage(context.route.path) + const { nuxtState = {} } = context || {} + // Client-side hydration + if (process.client && nuxtState.drupal) { + drupal.$currentPage = Vue.observable(nuxtState.drupal) } inject('drupal', drupal) diff --git a/scaffold/pages/_.vue b/scaffold/pages/_.vue index d3c0f2b5..fc968bf4 100644 --- a/scaffold/pages/_.vue +++ b/scaffold/pages/_.vue @@ -9,7 +9,8 @@ export default { async asyncData ({ route, $drupal }) { - return { page: await $drupal.fetchPage(route.path) } + // Do not return the data here to avoid hydrating data twice. The drupal-ce module is taking care of it already. + await $drupal.fetchPage(route.path) }, head () { return { @@ -17,6 +18,11 @@ export default { meta: this.page.metatags.meta, link: this.page.metatags.link } + }, + computed: { + page () { + return this.$drupal.$currentPage + } } }