feat(server-dev): Fetch Lowdefy config client-side using swr.

This commit is contained in:
Sam Tolmay 2021-11-30 17:18:48 +02:00
parent e76b40e839
commit ce126df437
No known key found for this signature in database
GPG Key ID: D004126FCD1A6DF0
11 changed files with 238 additions and 107 deletions

View File

@ -0,0 +1,60 @@
/*
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 from 'react';
import { useRouter } from 'next/router';
import Context from './Context.js';
import Head from './Head.js';
import Block from './block/Block.js';
import setupLink from '../utils/setupLink.js';
const LoadingBlock = () => <div>Loading...</div>;
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 });
lowdefy.home = rootConfig.home;
lowdefy.lowdefyGlobal = rootConfig.lowdefyGlobal;
lowdefy.menus = rootConfig.menus;
return (
<Context config={pageConfig} lowdefy={lowdefy}>
{(context, loading) => {
if (loading) {
return <LoadingBlock />;
}
return (
<>
<Head properties={context._internal.RootBlocks.map[pageConfig.id].eval.properties} />
<Block
block={context._internal.RootBlocks.map[pageConfig.id]}
Blocks={context._internal.RootBlocks}
context={context}
lowdefy={lowdefy}
/>
</>
);
}}
</Context>
);
};
export default Page;

View File

@ -43,6 +43,7 @@ const LowdefyContext = ({ children }) => {
};
lowdefy._internal.updateBlock = (blockId) =>
lowdefy._internal.updaters[blockId] && lowdefy._internal.updaters[blockId]();
return <>{children(lowdefy)}</>;
};

View File

@ -21,39 +21,48 @@ import { useRouter } from 'next/router';
import Context from './Context.js';
import Head from './Head.js';
import Block from './block/Block.js';
import PageConfig from './PageConfig.js';
import setupLink from '../utils/setupLink.js';
const LoadingBlock = () => <div>Loading...</div>;
const Page = ({ lowdefy, pageConfig, rootConfig }) => {
const Page = ({ lowdefy }) => {
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 });
lowdefy.home = rootConfig.home;
lowdefy.lowdefyGlobal = rootConfig.lowdefyGlobal;
lowdefy.menus = rootConfig.menus;
if (!lowdefy._internal.query.pageId) return <LoadingBlock />;
return (
<Context config={pageConfig} lowdefy={lowdefy}>
{(context, loading) => {
if (loading) {
return <LoadingBlock />;
}
<PageConfig lowdefy={lowdefy}>
{(pageConfig) => {
return (
<>
<Head properties={context._internal.RootBlocks.map[pageConfig.id].eval.properties} />
<Block
block={context._internal.RootBlocks.map[pageConfig.id]}
Blocks={context._internal.RootBlocks}
context={context}
lowdefy={lowdefy}
/>
</>
<Context config={pageConfig} lowdefy={lowdefy}>
{(context, loading) => {
if (loading) {
return <LoadingBlock />;
}
return (
<>
<Head
properties={context._internal.RootBlocks.map[pageConfig.id].eval.properties}
/>
<Block
block={context._internal.RootBlocks.map[pageConfig.id]}
Blocks={context._internal.RootBlocks}
context={context}
lowdefy={lowdefy}
/>
</>
);
}}
</Context>
);
}}
</Context>
</PageConfig>
);
};

View File

@ -0,0 +1,35 @@
/*
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 from 'react';
import usePageConfig from '../utils/usePageConfig.js';
import useRootConfig from '../utils/useRootConfig.js';
const PageConfig = ({ lowdefy, children }) => {
const { pageId } = lowdefy._internal.query;
const { data: pageConfig } = usePageConfig(pageId);
const { data: rootConfig } = useRootConfig();
lowdefy.home = rootConfig.home;
lowdefy.lowdefyGlobal = rootConfig.lowdefyGlobal;
lowdefy.menus = rootConfig.menus;
window.lowdefy = lowdefy;
return <>{children(pageConfig)}</>;
};
export default PageConfig;

View File

@ -14,25 +14,6 @@
limitations under the License.
*/
import { createApiContext, getPageConfig, getRootConfig } from '@lowdefy/api';
import Page from '../components/Page.js';
export async function getStaticProps() {
// TODO: get the right api context options
const apiContext = await createApiContext({ buildDirectory: './build' });
const [rootConfig, pageConfig] = await Promise.all([
getRootConfig(apiContext),
getPageConfig(apiContext, { pageId: '404' }),
]);
return {
props: {
pageConfig,
rootConfig,
},
};
}
export default Page;

View File

@ -14,37 +14,6 @@
limitations under the License.
*/
import { createApiContext, getPageConfig, getRootConfig } from '@lowdefy/api';
import Page from '../components/Page.js';
export async function getServerSideProps(context) {
const { pageId } = context.params;
// TODO: get the right api context options
const apiContext = await createApiContext({ buildDirectory: './build' });
// 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 {
redirect: {
destination: '/404',
permanent: false,
},
};
}
return {
props: {
pageConfig,
rootConfig,
},
};
}
export default Page;

View File

@ -0,0 +1,26 @@
/*
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 { createApiContext, getPageConfig } from '@lowdefy/api';
export default async function handler(req, res) {
const { pageId } = req.query;
// TODO: get the right api context options
const apiContext = await createApiContext({ buildDirectory: './build' });
const pageConfig = await getPageConfig(apiContext, { pageId });
res.status(200).json(pageConfig);
}

View File

@ -0,0 +1,25 @@
/*
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 { createApiContext, getRootConfig } from '@lowdefy/api';
export default async function handler(req, res) {
// TODO: get the right api context options
const apiContext = await createApiContext({ buildDirectory: './build' });
const rootConfig = await getRootConfig(apiContext);
res.status(200).json(rootConfig);
}

View File

@ -14,42 +14,6 @@
limitations under the License.
*/
import { createApiContext, getHome, getPageConfig, getRootConfig } from '@lowdefy/api';
import Home from '../components/Home.js';
import Page from '../components/Page.js';
export async function getServerSideProps() {
const apiContext = await createApiContext({ buildDirectory: './build' });
const home = await getHome(apiContext);
if (home.configured === false) {
return {
redirect: {
destination: `/${home.pageId}`,
permanent: false,
},
};
}
const [rootConfig, pageConfig] = await Promise.all([
getRootConfig(apiContext),
getPageConfig(apiContext, { pageId: home.pageId }),
]);
if (!pageConfig) {
return {
redirect: {
destination: '/404',
permanent: false,
},
};
}
return {
props: {
pageConfig,
rootConfig,
},
};
}
export default Page;
export default Home;

View File

@ -0,0 +1,32 @@
/*
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 useSWR from 'swr';
import request from './request.js';
// TODO: Handle TokenExpiredError
function fetchPageConfig(pageId) {
return request({ url: `/api/page/${pageId}` });
}
function usePageConfig(pageId) {
if (!pageId) {
pageId = 'NULL';
}
const { data } = useSWR(pageId, fetchPageConfig, { suspense: true });
return { data };
}
export default usePageConfig;

View File

@ -0,0 +1,29 @@
/*
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 useSWR from 'swr';
import request from './request.js';
// TODO: Handle TokenExpiredError
function fetchRootConfig() {
return request({ url: '/api/root' });
}
function useRootConfig() {
const { data } = useSWR('root', fetchRootConfig, { suspense: true });
return { data };
}
export default useRootConfig;