diff --git a/packages/cli/src/config/webpack.config.common.js b/packages/cli/src/config/webpack.config.common.js index 26b773d53..ee3a0fda0 100644 --- a/packages/cli/src/config/webpack.config.common.js +++ b/packages/cli/src/config/webpack.config.common.js @@ -84,7 +84,8 @@ module.exports = ({ config, context }) => { resolve: { extensions: ['.js', '.json', '.gql', '.graphql'], alias: { - '@greenwood/cli/data': context.dataDir + '@greenwood/cli/data': context.dataDir, + '@greenwood/cli/templates/app-template': path.join(context.scratchDir, 'app', 'app-template.js') } }, diff --git a/packages/cli/src/lifecycles/scaffold.js b/packages/cli/src/lifecycles/scaffold.js index f2145e4d6..b185038d4 100644 --- a/packages/cli/src/lifecycles/scaffold.js +++ b/packages/cli/src/lifecycles/scaffold.js @@ -89,7 +89,7 @@ const writeRoutes = async(compilation) => { const appDir = path.join(compilation.context.scratchDir, 'app'); await fs.ensureDir(appDir); - await fs.writeFile(path.join(appDir, './app.js'), result); + await fs.writeFile(path.join(appDir, './app-template.js'), result); resolve(); } catch (err) { @@ -98,6 +98,21 @@ const writeRoutes = async(compilation) => { }); }; +const writeBaseAppTemplate = async({ context }) => { + return new Promise(async (resolve, reject) => { + try { + let data = await fs.readFile(path.join(__dirname, '../templates/', 'base-template.js'), 'utf8'); + const appDir = path.join(context.scratchDir, 'app'); + + await fs.ensureDir(appDir); + await fs.writeFile(path.join(appDir, './app.js'), data); + resolve(); + } catch (err) { + reject(err); + } + }); +}; + const setupIndex = async({ context }) => { return new Promise(async (resolve, reject) => { try { @@ -125,6 +140,9 @@ module.exports = generateScaffolding = async (compilation) => { console.log('Writing Lit routes...'); await writeRoutes(compilation); + console.log('Write Base App Template...'); + await writeBaseAppTemplate(compilation); + console.log('setup index page and html'); await setupIndex(compilation); diff --git a/packages/cli/src/templates/app-template.js b/packages/cli/src/templates/app-template.js index 1016c49aa..60b8d5fb6 100644 --- a/packages/cli/src/templates/app-template.js +++ b/packages/cli/src/templates/app-template.js @@ -1,101 +1,13 @@ import { html, LitElement } from 'lit-element'; -import { connectRouter } from 'lit-redux-router'; -import { applyMiddleware, createStore, compose as origCompose, combineReducers } from 'redux'; -import { lazyReducerEnhancer } from 'pwa-helpers/lazy-reducer-enhancer.js'; -import thunk from 'redux-thunk'; -import client from '@greenwood/cli/data/client'; -import ConfigQuery from '@greenwood/cli/data/queries/config'; -import GraphQuery from '@greenwood/cli/data/queries/graph'; - -// eslint-disable-next-line no-underscore-dangle -const compose = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || origCompose; - -const store = createStore((state) => state, - compose(lazyReducerEnhancer(combineReducers), applyMiddleware(thunk)) -); - -import '../index/index'; - -connectRouter(store); class AppComponent extends LitElement { - async connectedCallback() { - super.connectedCallback(); - const route = window.location.pathname; - const response = await Promise.all([ - await client.query({ - query: ConfigQuery - }), - await client.query({ - query: GraphQuery - }) - ]); - const { config } = response[0].data; - const currentPage = response[1].data.graph.filter((page) => { - return route === page.link; - })[0]; - - const currentPageTitleSuffix = !currentPage || currentPage.link === '/' - ? '' - : ` - ${currentPage.title}`; - const fullTitle = `${config.title}${currentPageTitleSuffix}`; - - this.setDocumentTitle(fullTitle); - this.setMeta(config.meta, currentPage); - } - - setDocumentTitle(title = '') { - const head = document.head; - const titleElement = head.getElementsByTagName('title')[0]; - - titleElement.innerHTML = title; - } - - setMeta(meta = [], currentPage = {}) { - let header = document.head; - - meta.forEach(metaItem => { - const metaType = metaItem.rel // type of meta - ? 'rel' - : metaItem.name - ? 'name' - : 'property'; - const metaTypeValue = metaItem[metaType]; // value of the meta - let meta = document.createElement('meta'); - - if (metaType === 'rel') { - // change to a tag instead - meta = document.createElement('link'); - - meta.setAttribute('rel', metaTypeValue); - meta.setAttribute('href', metaItem.href); - } else { - const metaContent = metaItem.property === 'og:url' - ? `${metaItem.content}${currentPage.link}` - : metaItem.content; - - meta.setAttribute(metaType, metaItem[metaType]); - meta.setAttribute('content', metaContent); - } - - const oldmeta = header.querySelector(`[${metaType}="${metaTypeValue}"]`); - - // rehydration - if (oldmeta) { - header.replaceChild(meta, oldmeta); - } else { - header.appendChild(meta); - } - }); - } - render() { return html` - MYROUTES -

404 Not found

+ MYROUTES +

404 Not found

`; } } -customElements.define('eve-app', AppComponent); \ No newline at end of file +customElements.define('eve-app', AppComponent); diff --git a/packages/cli/src/templates/base-template.js b/packages/cli/src/templates/base-template.js new file mode 100644 index 000000000..2028a48a0 --- /dev/null +++ b/packages/cli/src/templates/base-template.js @@ -0,0 +1,104 @@ +import { html, LitElement } from 'lit-element'; +import { connectRouter } from 'lit-redux-router'; +import { applyMiddleware, createStore, compose as origCompose, combineReducers } from 'redux'; +import { lazyReducerEnhancer } from 'pwa-helpers/lazy-reducer-enhancer.js'; +import thunk from 'redux-thunk'; +import client from '@greenwood/cli/data/client'; +import ConfigQuery from '@greenwood/cli/data/queries/config'; +import GraphQuery from '@greenwood/cli/data/queries/graph'; +import '@greenwood/cli/templates/app-template'; +// eslint-disable-next-line no-underscore-dangle +const compose = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || origCompose; + +const store = createStore((state) => state, + compose(lazyReducerEnhancer(combineReducers), applyMiddleware(thunk)) +); + +import '../index/index'; + +connectRouter(store); + +class BaseAppComponent extends LitElement { + + async connectedCallback() { + super.connectedCallback(); + const route = window.location.pathname; + const response = await Promise.all([ + await client.query({ + query: ConfigQuery + }), + await client.query({ + query: GraphQuery + }) + ]); + const { config } = response[0].data; + const currentPage = response[1].data.graph.filter((page) => { + return route === page.link; + })[0]; + + const currentPageTitleSuffix = !currentPage || currentPage.link === '/' + ? '' + : ` - ${currentPage.title}`; + const fullTitle = `${config.title}${currentPageTitleSuffix}`; + + this.setDocumentTitle(fullTitle); + this.setMeta(config.meta, currentPage); + } + + setDocumentTitle(title = 'test') { + const head = document.head; + const titleElement = head.getElementsByTagName('title')[0]; + + titleElement.innerHTML = title; + } + + setMeta(meta = [], currentPage = {}) { + let header = document.head; + + meta.forEach(metaItem => { + const metaType = metaItem.rel // type of meta + ? 'rel' + : metaItem.name + ? 'name' + : 'property'; + const metaTypeValue = metaItem[metaType]; // value of the meta + let meta = document.createElement('meta'); + + if (metaType === 'rel') { + // change to a tag instead + meta = document.createElement('link'); + + meta.setAttribute('rel', metaTypeValue); + meta.setAttribute('href', metaItem.href); + } else { + const metaContent = metaItem.property === 'og:url' + ? `${metaItem.content}${currentPage.link}` + : metaItem.content; + + meta.setAttribute(metaType, metaItem[metaType]); + meta.setAttribute('content', metaContent); + } + + const oldmeta = header.querySelector(`[${metaType}="${metaTypeValue}"]`); + + // rehydration + if (oldmeta) { + header.replaceChild(meta, oldmeta); + } else { + header.appendChild(meta); + } + }); + } + + createRenderRoot() { + return this; + } + + render() { + return html` + + `; + } +} + +customElements.define('app-root', BaseAppComponent); \ No newline at end of file diff --git a/packages/cli/src/templates/index.html b/packages/cli/src/templates/index.html index fc7ca20f1..ac454b28e 100644 --- a/packages/cli/src/templates/index.html +++ b/packages/cli/src/templates/index.html @@ -19,7 +19,7 @@ - + diff --git a/packages/cli/test/cases/build.config.babel/build.config.babel.spec.js b/packages/cli/test/cases/build.config.babel/build.config.babel.spec.js index 8b6d0b1e7..21c3301c0 100644 --- a/packages/cli/test/cases/build.config.babel/build.config.babel.spec.js +++ b/packages/cli/test/cases/build.config.babel/build.config.babel.spec.js @@ -42,9 +42,9 @@ describe('Build Greenwood With: ', function() { dom = await JSDOM.fromFile(path.resolve(this.context.publicDir, './index.html')); }); - it('should not contain any components within eve-app', function() { + it('should not contain any components within app-root', function() { // prove that our custom broken babel config is being used - const outlet = dom.window.document.querySelector('body > eve-app').innerHTML; + const outlet = dom.window.document.querySelector('body > app-root').innerHTML; expect(outlet).to.equal(''); }); diff --git a/packages/cli/test/cases/build.default.webpack/webpack.config.common.js b/packages/cli/test/cases/build.default.webpack/webpack.config.common.js index 7b2efbe6d..7d51c1b57 100644 --- a/packages/cli/test/cases/build.default.webpack/webpack.config.common.js +++ b/packages/cli/test/cases/build.default.webpack/webpack.config.common.js @@ -85,7 +85,8 @@ module.exports = ({ config, context }) => { resolve: { extensions: ['.js', '.json', '.gql', '.graphql'], alias: { - '@greenwood/cli/data': path.join(__dirname, '../../..', './src', './data') + '@greenwood/cli/data': path.join(__dirname, '../../..', './src', './data'), + '@greenwood/cli/templates/app-template': path.join(context.scratchDir, 'app', 'app-template.js') } }, diff --git a/packages/cli/test/cases/build.default.workspace-template-app/build.default.workspace-template-app.spec.js b/packages/cli/test/cases/build.default.workspace-template-app/build.default.workspace-template-app.spec.js index 215e45bd5..41c5c0f8f 100644 --- a/packages/cli/test/cases/build.default.workspace-template-app/build.default.workspace-template-app.spec.js +++ b/packages/cli/test/cases/build.default.workspace-template-app/build.default.workspace-template-app.spec.js @@ -69,7 +69,7 @@ describe('Build Greenwood With: ', function() { }); it('should have a router outlet tag in the ', function() { - const outlet = dom.window.document.querySelectorAll('body eve-app'); + const outlet = dom.window.document.querySelectorAll('body app-root'); expect(outlet.length).to.be.equal(1); }); diff --git a/packages/cli/test/cases/build.default.workspace-template-app/src/templates/app-template.js b/packages/cli/test/cases/build.default.workspace-template-app/src/templates/app-template.js index ce3d2d4be..7e866dcc4 100644 --- a/packages/cli/test/cases/build.default.workspace-template-app/src/templates/app-template.js +++ b/packages/cli/test/cases/build.default.workspace-template-app/src/templates/app-template.js @@ -1,47 +1,11 @@ import { html, LitElement } from 'lit-element'; -import { connectRouter } from 'lit-redux-router'; -import { applyMiddleware, createStore, compose as origCompose, combineReducers } from 'redux'; -import { lazyReducerEnhancer } from 'pwa-helpers/lazy-reducer-enhancer.js'; -import thunk from 'redux-thunk'; -import client from '@greenwood/cli/data/client'; -import ConfigQuery from '@greenwood/cli/data/queries/config'; - -// eslint-disable-next-line no-underscore-dangle -const compose = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || origCompose; - -// eslint-disable-next-line -const store = createStore( - (state, action) => state, // eslint-disable-line - compose(lazyReducerEnhancer(combineReducers), applyMiddleware(thunk))); - -import '../index/index'; - -connectRouter(store); class AppComponent extends LitElement { - async connectedCallback() { - super.connectedCallback(); - - const response = await client.query({ - query: ConfigQuery - }); - const { config } = response.data; - - this.setDocoumentTitle(config.title); - } - - setDocoumentTitle(title) { - const head = document.head; - const titleElement = head.getElementsByTagName('title')[0]; - - titleElement.innerHTML = title; - } - render() { return html` - MYROUTES -

My Custom App Template

+ MYROUTES +

My Custom App Template

`; } } diff --git a/test/smoke-test.js b/test/smoke-test.js index 6e4dc513a..b7ee61857 100644 --- a/test/smoke-test.js +++ b/test/smoke-test.js @@ -89,7 +89,7 @@ function defaultIndex(label) { }); it('should have one