diff --git a/apps/app/src/server/routes/cms.ts b/apps/app/src/server/routes/cms.ts index fb120f6a2c..f8dc0abf80 100644 --- a/apps/app/src/server/routes/cms.ts +++ b/apps/app/src/server/routes/cms.ts @@ -3,6 +3,8 @@ import emoji from 'markdown-it-emoji'; import loggerFactory from '~/utils/logger'; +const ApiResponse = require('../util/apiResponse'); + const logger = loggerFactory('growi:routes:cms:pages'); module.exports = function(crowi) { @@ -13,16 +15,53 @@ module.exports = function(crowi) { actions.api = api; - /** - * @api {get} /pages.get get pages - * @apiName get - * @apiGroup Page - * - * @apiParam {String} id - */ + api.list = async function(req, res) { + // const nameSpace = req.params.nameSpace; + const limit = parseInt(req.query.limit) || 50; + const offset = parseInt(req.query.offset) || 0; + + const queryOptions = { offset, limit: limit + 1 }; + + // if (nameSpace == null) { + // return res.json(ApiResponse.error('Parameter nameSpace is required.')); + // } + + let pages; + + try { + // TODO: namespace を考慮する + const result = await Page.findListByStartWith('', undefined, queryOptions); + + // TODO: latestRevisionData が付いている pages を、1つずつではなくまとめて取得する + pages = await Promise.all(result.pages.map(async(page) => { + const reGetPage = await Page.findByIdAndViewer(page._id); + reGetPage.initLatestRevisionField(undefined); + return reGetPage.populateDataToShowRevision(); + })); + } + catch (err) { + logger.error('get-pages-failed', err); + return res.json(ApiResponse.error(err)); + } + + if (pages.length > limit) { + pages.pop(); + } + + const pagesWithHTMLString = pages.map((page) => { + return { page, htmlString: md({ html: true, linkify: true }).use(emoji).render(page.revision.body) }; + }); + + return res.json(ApiResponse.success(pagesWithHTMLString)); + }; + api.get = async function(req, res) { const pageId = req.params.pageId; + if (pageId == null) { + return res.json(ApiResponse.error('Parameter pageId is required.')); + } + let page; try { @@ -30,11 +69,11 @@ module.exports = function(crowi) { } catch (err) { logger.error('get-page-failed', err); - return res.apiv3Err(err, 500); + return res.json(ApiResponse.error(err)); } if (page == null) { - return res.apiv3Err('Page is not found', 404); + return res.json(ApiResponse.error(`Page('${pageId}' is not found or forbidden`)); } if (page != null) { @@ -46,13 +85,13 @@ module.exports = function(crowi) { } catch (err) { logger.error('populate-page-failed', err); - return res.apiv3Err(err, 500); + return res.json(ApiResponse.error('Populate page failed')); } } - const htmlString = md({ html: true }).use(emoji).render(page.revision.body); + const htmlString = md({ html: true, linkify: true }).use(emoji).render(page.revision.body); - return res.apiv3({ ...page, htmlString }); + return res.json(ApiResponse.success({ page, htmlString })); }; return actions; diff --git a/apps/app/src/server/routes/index.js b/apps/app/src/server/routes/index.js index e52935ee47..6d4506c787 100644 --- a/apps/app/src/server/routes/index.js +++ b/apps/app/src/server/routes/index.js @@ -187,6 +187,7 @@ module.exports = function(crowi, app) { app.use('/ogp', express.Router().get('/:pageId([0-9a-z]{0,})', loginRequired, ogp.pageIdRequired, ogp.ogpValidator, ogp.renderOgp)); + app.get('/_cms/list.json', cms.api.list); app.get('/_cms/:pageId.json', cms.api.get); app.get('/_cms/tags', tag.api.list); diff --git a/apps/mobliz-clone/.env.development b/apps/mobliz-clone/.env.development new file mode 100644 index 0000000000..a3c6ed1218 --- /dev/null +++ b/apps/mobliz-clone/.env.development @@ -0,0 +1 @@ +NEXT_PUBLIC_APP_SITE_URL=http://localhost:3000 diff --git a/apps/mobliz-clone/src/pages/[pageId].tsx b/apps/mobliz-clone/src/pages/[pageId].tsx index f03b4348d1..f21480cb97 100644 --- a/apps/mobliz-clone/src/pages/[pageId].tsx +++ b/apps/mobliz-clone/src/pages/[pageId].tsx @@ -17,7 +17,7 @@ const DetailPage: NextPage = (props: Props) => { const [error, setError] = useState(); useEffect(() => { - axios.get(`http://localhost:3000/_cms/${pageId}.json`) + axios.get(`${process.env.NEXT_PUBLIC_APP_SITE_URL}/_cms/${pageId}.json`) .then((response) => { setHTMLString(response.data.htmlString); }) diff --git a/apps/mobliz-clone/src/pages/index.tsx b/apps/mobliz-clone/src/pages/index.tsx index fbe14eb3ed..b4562d0761 100644 --- a/apps/mobliz-clone/src/pages/index.tsx +++ b/apps/mobliz-clone/src/pages/index.tsx @@ -1,20 +1,56 @@ -import React, { useState } from 'react'; +import React, { useState, useEffect } from 'react'; +import parse from 'html-react-parser'; import { NextPage } from 'next'; import axios from '~/utils/axios'; -const Top: NextPage = () => { - const [body, setBody] = useState(); - axios.get('http://localhost:3000/_api/v3/page?pageId=6522505d8eddc4a6c69499b0').then((data) => { - setBody(data.data.page.revision.body); - }); +const TopPage: NextPage = () => { + const [data, setData] = useState(); + const [error, setError] = useState(); + + useEffect(() => { + axios.get(`${process.env.NEXT_PUBLIC_APP_SITE_URL}/_cms/list.json`) + .then((response) => { + setData(response.data); + }) + .catch((error) => { + setError(`データの取得に失敗しました。\n${JSON.stringify(error)}`); + }); + }, []); return ( -
-
{body}
-
+ <> + {error == null ? ( + <> + {data == null ? ( +
+ Loading... +
+ ) : ( + <> + {data.map((pageData, index) => { + return ( +
+
+ {parse(pageData.htmlString)} +
+ + 続きを読む + +
+ ); + })} + + )} + + ) : ( +
+

{error}

+
+ )} + ); }; -export default Top; +export default TopPage; diff --git a/apps/mobliz-clone/src/styles/globals.scss b/apps/mobliz-clone/src/styles/globals.scss index a96e4cc3b0..2d3a319710 100644 --- a/apps/mobliz-clone/src/styles/globals.scss +++ b/apps/mobliz-clone/src/styles/globals.scss @@ -28,3 +28,11 @@ a { text-decoration: underline; } } + +img { + max-width: 100%; +} + +.index-preview { + max-height: 500px; +}