diff --git a/packages/api/src/context/createApiContext.js b/packages/api/src/context/createApiContext.js index b116ba2fa..c9c9a3f53 100644 --- a/packages/api/src/context/createApiContext.js +++ b/packages/api/src/context/createApiContext.js @@ -19,6 +19,7 @@ import createReadConfigFile from './readConfigFile.js'; async function createApiContext({ buildDirectory }) { const readConfigFile = createReadConfigFile({ buildDirectory }); return { + authenticated: false, authorize: () => true, readConfigFile, }; diff --git a/packages/api/src/index.js b/packages/api/src/index.js index 2454b483a..a1b1110ab 100644 --- a/packages/api/src/index.js +++ b/packages/api/src/index.js @@ -18,11 +18,8 @@ import createApiContext from './context/createApiContext.js'; import createContext from './context/createContext.js'; import getHomePageId from './routes/rootConfig/getHomePageId.js'; import getPageConfig from './routes/page/getPageConfig.js'; -import openIdAuthorizationUrl from './routes/auth/openIdAuthorizationUrl.js'; -import openIdCallback from './routes/auth/openIdCallback.js'; -import openIdLogoutUrl from './routes/auth/openIdLogoutUrl.js'; +import getRootConfig from './routes/rootConfig/getRootConfig.js'; import request from './routes/request/request.js'; -import rootConfig from './routes/rootConfig/rootConfig.js'; import { AuthenticationError, @@ -37,11 +34,8 @@ export { createContext, getHomePageId, getPageConfig, - openIdAuthorizationUrl, - openIdCallback, - openIdLogoutUrl, + getRootConfig, request, - rootConfig, AuthenticationError, ConfigurationError, RequestError, diff --git a/packages/api/src/routes/rootConfig/rootConfig.js b/packages/api/src/routes/rootConfig/getRootConfig.js similarity index 93% rename from packages/api/src/routes/rootConfig/rootConfig.js rename to packages/api/src/routes/rootConfig/getRootConfig.js index 2880ae210..9f3e9e322 100644 --- a/packages/api/src/routes/rootConfig/rootConfig.js +++ b/packages/api/src/routes/rootConfig/getRootConfig.js @@ -18,7 +18,7 @@ import findHomePageId from './findHomePageId.js'; import getLowdefyGlobal from './getLowdefyGlobal.js'; import getMenus from './menus/getMenus.js'; -async function rootConfig(context) { +async function getRootConfig(context) { const [lowdefyGlobal, menus] = await Promise.all([getLowdefyGlobal(context), getMenus(context)]); return { authenticated: context.authenticated, @@ -28,4 +28,4 @@ async function rootConfig(context) { }; } -export default rootConfig; +export default getRootConfig; diff --git a/packages/engine/src/actions/Link.js b/packages/engine/src/actions/Link.js index afb7d81f7..56d8292c4 100644 --- a/packages/engine/src/actions/Link.js +++ b/packages/engine/src/actions/Link.js @@ -19,8 +19,9 @@ import { type } from '@lowdefy/helpers'; async function Link({ context, params }) { const linkParams = type.isString(params) ? { pageId: params } : params; try { - context.lowdefy.link(linkParams); + context._internal.lowdefy._internal.link(linkParams); } catch (error) { + console.log(error); throw new Error(`Invalid Link, check action params. Received "${JSON.stringify(params)}".`); } } diff --git a/packages/server/next.config.js b/packages/server/next.config.js index 0bec413c4..ca85c45f2 100644 --- a/packages/server/next.config.js +++ b/packages/server/next.config.js @@ -23,6 +23,7 @@ module.exports = withLess({ } return config; }, + poweredByHeader: false, // productionBrowserSourceMaps: true // experimental: { // concurrentFeatures: true, diff --git a/packages/server/src/components/Context.js b/packages/server/src/components/Context.js index aea330777..8d4377cfd 100644 --- a/packages/server/src/components/Context.js +++ b/packages/server/src/components/Context.js @@ -22,21 +22,16 @@ const LoadingBlock = () =>
Loading...
; const Context = ({ children, lowdefy, config }) => { const [context, setContext] = useState({}); - const [error, setError] = useState(null); useEffect(() => { let mounted = true; const mount = async () => { - try { - const ctx = await getContext({ - config, - lowdefy, - }); - if (mounted) { - setContext(ctx); - } - } catch (err) { - setError(err); + const ctx = await getContext({ + config, + lowdefy, + }); + if (mounted) { + setContext(ctx); } }; mount(); @@ -45,7 +40,6 @@ const Context = ({ children, lowdefy, config }) => { }; }, [config, lowdefy]); - if (error) throw error; if (context.id !== config.id) return ; return children(context); diff --git a/packages/server/src/components/Head.js b/packages/server/src/components/Head.js index 2f6bc2c12..d04b2a22e 100644 --- a/packages/server/src/components/Head.js +++ b/packages/server/src/components/Head.js @@ -18,7 +18,6 @@ import React from 'react'; import Head from 'next/head'; const BindHead = ({ properties }) => { - console.log(properties); return ( {properties.title} diff --git a/packages/server/src/components/LowdefyContext.js b/packages/server/src/components/LowdefyContext.js index 77c9639af..ab01c7aac 100644 --- a/packages/server/src/components/LowdefyContext.js +++ b/packages/server/src/components/LowdefyContext.js @@ -17,14 +17,16 @@ import React from 'react'; import blockComponents from '../plugins/blocks.js'; +import components from './components.js'; const LowdefyContext = ({ children }) => { const lowdefy = { _internal: { blockComponents, + components, updaters: {}, displayMessage: (message) => { - console.log(message); + alert(message); return () => undefined; }, link: () => undefined, diff --git a/packages/server/src/components/Page.js b/packages/server/src/components/Page.js index c199f09cb..63ce77e9a 100644 --- a/packages/server/src/components/Page.js +++ b/packages/server/src/components/Page.js @@ -16,25 +16,45 @@ import React from 'react'; +import { useRouter } from 'next/router'; + import Context from './Context.js'; import Head from './Head.js'; import Block from './block/Block.js'; +import Root from './Root.js'; +import setupLink from '../utils/setupLink.js'; -const Page = ({ lowdefy, pageConfig }) => { +const Page = ({ lowdefy, pageConfig, rootConfig }) => { + const router = useRouter(); + lowdefy._internal.basePath = router.basePath; + lowdefy._internal.pathname = router.pathname; + lowdefy._internal.query = router.query; + lowdefy._internal.router = router; + lowdefy._internal.link = setupLink({ lowdefy }); return ( - - {(context) => ( - <> - - - - )} - + + {(loaded) => + !loaded ? ( +
Loading
+ ) : ( + + {(context) => ( + <> + + + + )} + + ) + } +
); }; diff --git a/packages/server/src/components/Root.js b/packages/server/src/components/Root.js new file mode 100644 index 000000000..ae5ff3368 --- /dev/null +++ b/packages/server/src/components/Root.js @@ -0,0 +1,36 @@ +/* + Copyright 2020-2021 Lowdefy, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +import React, { useEffect, useState } from 'react'; + +const Root = ({ children, lowdefy, rootConfig }) => { + const [loading, setLoading] = useState(true); + + useEffect(() => { + lowdefy.document = document; + lowdefy.window = window; + setLoading(false); + }, [lowdefy]); + + lowdefy.homePageId = rootConfig.homePageId; + lowdefy.lowdefyGlobal = rootConfig.lowdefyGlobal; + lowdefy.menus = rootConfig.menus; + + if (loading) return
Loading...
; + + return <>{children(true)}; +}; + +export default Root; diff --git a/packages/server/src/components/components.js b/packages/server/src/components/components.js new file mode 100644 index 000000000..007c3a246 --- /dev/null +++ b/packages/server/src/components/components.js @@ -0,0 +1,21 @@ +/* + Copyright 2020-2021 Lowdefy, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +import Link from 'next/link'; + +export default { + Link, +}; diff --git a/packages/server/src/pages/[pageId].js b/packages/server/src/pages/[pageId].js index 24e4a2496..bdcfd1793 100644 --- a/packages/server/src/pages/[pageId].js +++ b/packages/server/src/pages/[pageId].js @@ -16,13 +16,20 @@ import createApiContext from '@lowdefy/api/context/createApiContext'; import getPageConfig from '@lowdefy/api/routes/page/getPageConfig'; +import getRootConfig from '@lowdefy/api/routes/rootConfig/getRootConfig'; import Page from '../components/Page.js'; export async function getServerSideProps(context) { const { pageId } = context.params; const apiContext = await createApiContext({ buildDirectory: './.lowdefy/build' }); - const pageConfig = await getPageConfig(apiContext, { pageId }); + + // TODO: Maybe we can only get rootConfig once? + // We can't do getServerSideProps on _app :( + const [rootConfig, pageConfig] = await Promise.all([ + getRootConfig(apiContext), + getPageConfig(apiContext, { pageId }), + ]); if (!pageConfig) { return { @@ -36,6 +43,7 @@ export async function getServerSideProps(context) { return { props: { pageConfig, + rootConfig, }, }; } diff --git a/packages/server/src/utils/setupLink.js b/packages/server/src/utils/setupLink.js new file mode 100644 index 000000000..34077d516 --- /dev/null +++ b/packages/server/src/utils/setupLink.js @@ -0,0 +1,44 @@ +/* + Copyright 2020-2021 Lowdefy, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +import { createLink } from '@lowdefy/engine'; + +function setupLink({ lowdefy }) { + const { router, window } = lowdefy._internal; + const sameOriginLink = (path, newTab) => { + if (newTab) { + return window.open(`${window.location.origin}${lowdefy.basePath}${path}`, '_blank').focus(); + } else { + // Next handles the basePath here. + return router.push({ + pathname: path, + // TODO: Do we handle urlQuery as a param here? + // query: {}, + }); + } + }; + const newOriginLink = (path, newTab) => { + if (newTab) { + return window.open(path, '_blank').focus(); + } else { + return (window.location.href = path); + } + }; + const backLink = () => window.history.back(); + return createLink({ backLink, lowdefy, newOriginLink, sameOriginLink }); +} + +export default setupLink;