mirror of
https://github.com/codex-team/codex.docs.git
synced 2025-07-19 13:19:42 +02:00
Page showing, page edit, move API to /api/ (#10)
This commit is contained in:
parent
ff09f695d0
commit
730eff7995
18 changed files with 316 additions and 133 deletions
2
public/dist/editor.bundle.js
vendored
2
public/dist/editor.bundle.js
vendored
File diff suppressed because one or more lines are too long
2
public/dist/main.bundle.js
vendored
2
public/dist/main.bundle.js
vendored
File diff suppressed because one or more lines are too long
2
public/dist/main.css
vendored
2
public/dist/main.css
vendored
File diff suppressed because one or more lines are too long
|
@ -7,8 +7,9 @@ import Header from 'codex.editor.header';
|
||||||
export default class Editor {
|
export default class Editor {
|
||||||
/**
|
/**
|
||||||
* Creates Editor instance
|
* Creates Editor instance
|
||||||
|
* @property {object} initialData - data to start with
|
||||||
*/
|
*/
|
||||||
constructor() {
|
constructor({initialData}) {
|
||||||
this.editor = new CodeXEditor({
|
this.editor = new CodeXEditor({
|
||||||
tools: {
|
tools: {
|
||||||
header: {
|
header: {
|
||||||
|
@ -18,7 +19,7 @@ export default class Editor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data: {
|
data: initialData || {
|
||||||
blocks: [
|
blocks: [
|
||||||
{
|
{
|
||||||
type: 'header',
|
type: 'header',
|
||||||
|
|
|
@ -7,6 +7,12 @@
|
||||||
* @property {string} version - used Editor version
|
* @property {string} version - used Editor version
|
||||||
* @property {number} time - saving time
|
* @property {number} time - saving time
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {object} writingSettings
|
||||||
|
* @property {{_id, _parent, title, body: editorData}} [page] - page data for editing
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @class Writing
|
* @class Writing
|
||||||
* @classdesc Class for create/edit pages
|
* @classdesc Class for create/edit pages
|
||||||
|
@ -17,6 +23,7 @@ export default class Writing {
|
||||||
*/
|
*/
|
||||||
constructor() {
|
constructor() {
|
||||||
this.editor = null;
|
this.editor = null;
|
||||||
|
this.page = null; // stores Page on editing
|
||||||
this.nodes = {
|
this.nodes = {
|
||||||
editorWrapper: null,
|
editorWrapper: null,
|
||||||
saveButton: null,
|
saveButton: null,
|
||||||
|
@ -26,10 +33,10 @@ export default class Writing {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called by ModuleDispatcher to initialize module from DOM
|
* Called by ModuleDispatcher to initialize module from DOM
|
||||||
* @param {object} settings - module settings
|
* @param {writingSettings} settings - module settings
|
||||||
* @param {HTMLElement} moduleEl - module element
|
* @param {HTMLElement} moduleEl - module element
|
||||||
*/
|
*/
|
||||||
init(settings, moduleEl) {
|
init(settings = {}, moduleEl) {
|
||||||
/**
|
/**
|
||||||
* Create Editor
|
* Create Editor
|
||||||
*/
|
*/
|
||||||
|
@ -38,6 +45,10 @@ export default class Writing {
|
||||||
|
|
||||||
moduleEl.appendChild(this.nodes.editorWrapper);
|
moduleEl.appendChild(this.nodes.editorWrapper);
|
||||||
|
|
||||||
|
if (settings.page){
|
||||||
|
this.page = settings.page;
|
||||||
|
}
|
||||||
|
|
||||||
this.loadEditor().then((editor) => {
|
this.loadEditor().then((editor) => {
|
||||||
this.editor = editor;
|
this.editor = editor;
|
||||||
});
|
});
|
||||||
|
@ -59,7 +70,9 @@ export default class Writing {
|
||||||
async loadEditor() {
|
async loadEditor() {
|
||||||
const {default: Editor} = await import(/* webpackChunkName: "editor" */ './../classes/editor');
|
const {default: Editor} = await import(/* webpackChunkName: "editor" */ './../classes/editor');
|
||||||
|
|
||||||
return new Editor();
|
return new Editor({
|
||||||
|
initialData: this.page ? this.page.body : null
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -88,10 +101,11 @@ export default class Writing {
|
||||||
async saveButtonClicked() {
|
async saveButtonClicked() {
|
||||||
try {
|
try {
|
||||||
const writingData = await this.getData();
|
const writingData = await this.getData();
|
||||||
|
const endpoint = this.page ? '/api/page/' + this.page._id : '/api/page';
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let response = await fetch('/page', {
|
let response = await fetch(endpoint, {
|
||||||
method: 'PUT',
|
method: this.page ? 'POST' : 'PUT',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json; charset=utf-8'
|
'Content-Type': 'application/json; charset=utf-8'
|
||||||
},
|
},
|
||||||
|
|
57
src/frontend/styles/components/page.pcss
Normal file
57
src/frontend/styles/components/page.pcss
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
.page {
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 1.6;
|
||||||
|
|
||||||
|
&__header {
|
||||||
|
display: flex;
|
||||||
|
color: var(--color-text-second);
|
||||||
|
|
||||||
|
&-nav {
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: none;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: var(--color-link-active);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(:last-of-type) {
|
||||||
|
&::after {
|
||||||
|
content: '»';
|
||||||
|
margin: 0 0.7em 0 0.45em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-time {
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-button {
|
||||||
|
@apply --button;
|
||||||
|
padding: 5px 10px;
|
||||||
|
font-size: 13px;
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__title {
|
||||||
|
font-size: 26px;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: -0.04px;
|
||||||
|
margin-bottom: -0.2em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.block-header {
|
||||||
|
margin: 1.5em 0 0.5em;
|
||||||
|
|
||||||
|
&--2 {
|
||||||
|
font-size: 22px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--3 {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,6 +4,7 @@
|
||||||
@import url('components/header.pcss');
|
@import url('components/header.pcss');
|
||||||
@import url('components/aside.pcss');
|
@import url('components/aside.pcss');
|
||||||
@import url('components/writing.pcss');
|
@import url('components/writing.pcss');
|
||||||
|
@import url('components/page.pcss');
|
||||||
|
|
||||||
body {
|
body {
|
||||||
font-family: system-ui, Helvetica, Arial, Verdana;
|
font-family: system-ui, Helvetica, Arial, Verdana;
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
*/
|
*/
|
||||||
--layout-padding-horisontal: 40px;
|
--layout-padding-horisontal: 40px;
|
||||||
--layout-padding-vertical: 40px;
|
--layout-padding-vertical: 40px;
|
||||||
--layout-width-aside: 250px;
|
--layout-width-aside: 200px;
|
||||||
--layout-width-main-col: 650px;
|
--layout-width-main-col: 650px;
|
||||||
|
|
||||||
--button {
|
--button {
|
||||||
|
@ -20,6 +20,7 @@
|
||||||
padding: 9px 15px;
|
padding: 9px 15px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
line-height: 1em;
|
line-height: 1em;
|
||||||
|
text-decoration: none;
|
||||||
|
|
||||||
svg {
|
svg {
|
||||||
margin: 0 0.3em 0 -0.05em;
|
margin: 0 0.3em 0 -0.05em;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
const {pages} = require('../utils/database/index');
|
const {pages: db} = require('../utils/database/index');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {Object} PageData
|
* @typedef {Object} PageData
|
||||||
|
@ -25,7 +25,7 @@ class Page {
|
||||||
* @returns {Promise<Page>}
|
* @returns {Promise<Page>}
|
||||||
*/
|
*/
|
||||||
static async get(_id) {
|
static async get(_id) {
|
||||||
const data = await pages.findOne({_id});
|
const data = await db.findOne({_id});
|
||||||
|
|
||||||
return new Page(data);
|
return new Page(data);
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ class Page {
|
||||||
* @returns {Promise<Page[]>}
|
* @returns {Promise<Page[]>}
|
||||||
*/
|
*/
|
||||||
static async getAll(query = {}) {
|
static async getAll(query = {}) {
|
||||||
const docs = await pages.find(query);
|
const docs = await db.find(query);
|
||||||
|
|
||||||
return Promise.all(docs.map(doc => new Page(doc)));
|
return Promise.all(docs.map(doc => new Page(doc)));
|
||||||
}
|
}
|
||||||
|
@ -52,8 +52,6 @@ class Page {
|
||||||
data = {};
|
data = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
this.db = pages;
|
|
||||||
|
|
||||||
if (data._id) {
|
if (data._id) {
|
||||||
this._id = data._id;
|
this._id = data._id;
|
||||||
}
|
}
|
||||||
|
@ -113,7 +111,7 @@ class Page {
|
||||||
* @returns {Promise<Page>}
|
* @returns {Promise<Page>}
|
||||||
*/
|
*/
|
||||||
get parent() {
|
get parent() {
|
||||||
return this.db.findOne({_id: this._parent})
|
return db.findOne({_id: this._parent})
|
||||||
.then(data => new Page(data));
|
.then(data => new Page(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,7 +121,7 @@ class Page {
|
||||||
* @returns {Promise<Page[]>}
|
* @returns {Promise<Page[]>}
|
||||||
*/
|
*/
|
||||||
get children() {
|
get children() {
|
||||||
return this.db.find({parent: this._id})
|
return db.find({parent: this._id})
|
||||||
.then(data => data.map(page => new Page(page)));
|
.then(data => data.map(page => new Page(page)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,11 +132,11 @@ class Page {
|
||||||
*/
|
*/
|
||||||
async save() {
|
async save() {
|
||||||
if (!this._id) {
|
if (!this._id) {
|
||||||
const insertedRow = await this.db.insert(this.data);
|
const insertedRow = await db.insert(this.data);
|
||||||
|
|
||||||
this._id = insertedRow._id;
|
this._id = insertedRow._id;
|
||||||
} else {
|
} else {
|
||||||
await this.db.update({_id: this._id}, this.data);
|
await db.update({_id: this._id}, this.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
|
@ -150,7 +148,7 @@ class Page {
|
||||||
* @returns {Promise<Page>}
|
* @returns {Promise<Page>}
|
||||||
*/
|
*/
|
||||||
async destroy() {
|
async destroy() {
|
||||||
await this.db.remove({_id: this._id});
|
await db.remove({_id: this._id});
|
||||||
|
|
||||||
delete this._id;
|
delete this._id;
|
||||||
|
|
||||||
|
|
8
src/routes/api/index.js
Normal file
8
src/routes/api/index.js
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
const express = require('express');
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
const pagesAPI = require('./pages');
|
||||||
|
|
||||||
|
router.use('/', pagesAPI);
|
||||||
|
|
||||||
|
module.exports = router;
|
115
src/routes/api/pages.js
Normal file
115
src/routes/api/pages.js
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
const express = require('express');
|
||||||
|
const router = express.Router();
|
||||||
|
const multer = require('multer')();
|
||||||
|
const Pages = require('../../controllers/pages');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GET /page/:id
|
||||||
|
*
|
||||||
|
* Return PageData of page with given id
|
||||||
|
*/
|
||||||
|
router.get('/page/:id', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const page = await Pages.get(req.params.id);
|
||||||
|
|
||||||
|
res.json({
|
||||||
|
success: true,
|
||||||
|
result: page.data
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
res.status(400).json({
|
||||||
|
success: false,
|
||||||
|
error: err.message
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GET /pages
|
||||||
|
*
|
||||||
|
* Return PageData for all pages
|
||||||
|
*/
|
||||||
|
router.get('/pages', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const pages = await Pages.getAll();
|
||||||
|
|
||||||
|
res.json({
|
||||||
|
success: true,
|
||||||
|
result: pages
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
res.status(400).json({
|
||||||
|
success: false,
|
||||||
|
error: err.message
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PUT /page
|
||||||
|
*
|
||||||
|
* Create new page in the database
|
||||||
|
*/
|
||||||
|
router.put('/page', multer.any(), async (req, res) => {
|
||||||
|
try {
|
||||||
|
const {title, body, parent} = req.body;
|
||||||
|
const page = await Pages.insert({title, body, parent});
|
||||||
|
|
||||||
|
res.json({
|
||||||
|
success: true,
|
||||||
|
result: page
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
res.status(400).json({
|
||||||
|
success: false,
|
||||||
|
error: err.message
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POST /page/:id
|
||||||
|
*
|
||||||
|
* Update page data in the database
|
||||||
|
*/
|
||||||
|
router.post('/page/:id', multer.any(), async (req, res) => {
|
||||||
|
const {id} = req.params;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const {title, body, parent} = req.body;
|
||||||
|
const page = await Pages.update(id, {title, body, parent});
|
||||||
|
|
||||||
|
res.json({
|
||||||
|
success: true,
|
||||||
|
result: page
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
res.status(400).json({
|
||||||
|
success: false,
|
||||||
|
error: err.message
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DELETE /page/:id
|
||||||
|
*
|
||||||
|
* Remove page from the database
|
||||||
|
*/
|
||||||
|
router.delete('/page/:id', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const page = await Pages.remove(req.params.id);
|
||||||
|
|
||||||
|
res.json({
|
||||||
|
success: true,
|
||||||
|
result: page
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
res.status(400).json({
|
||||||
|
success: false,
|
||||||
|
error: err.message
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = router;
|
|
@ -3,8 +3,10 @@ const router = express.Router();
|
||||||
|
|
||||||
const home = require('./home');
|
const home = require('./home');
|
||||||
const pages = require('./pages');
|
const pages = require('./pages');
|
||||||
|
const api = require('./api');
|
||||||
|
|
||||||
router.use('/', home);
|
router.use('/', home);
|
||||||
router.use('/', pages);
|
router.use('/', pages);
|
||||||
|
router.use('/api', api);
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
const express = require('express');
|
const express = require('express');
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
const multer = require('multer')();
|
|
||||||
const Pages = require('../controllers/pages');
|
const Pages = require('../controllers/pages');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -10,116 +9,46 @@ router.get('/page/new', async (req, res) => {
|
||||||
let pagesAvailable = await Pages.getAll();
|
let pagesAvailable = await Pages.getAll();
|
||||||
|
|
||||||
res.render('pages/form', {
|
res.render('pages/form', {
|
||||||
pagesAvailable
|
pagesAvailable,
|
||||||
|
page: null
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GET /page/:id
|
* Edit page form
|
||||||
*
|
|
||||||
* Return PageData of page with given id
|
|
||||||
*/
|
*/
|
||||||
router.get('/page/:id', async (req, res) => {
|
router.get('/page/edit/:id', async (req, res, next) => {
|
||||||
try {
|
const pageId = req.params.id;
|
||||||
const page = await Pages.get(req.params.id);
|
|
||||||
|
|
||||||
res.json({
|
try {
|
||||||
success: true,
|
let page = await Pages.get(pageId);
|
||||||
result: page.data
|
let pagesAvailable = await Pages.getAll();
|
||||||
});
|
|
||||||
} catch (err) {
|
res.render('pages/form', {
|
||||||
res.status(400).json({
|
pagesAvailable,
|
||||||
success: false,
|
page
|
||||||
error: err.message
|
|
||||||
});
|
});
|
||||||
|
} catch (error) {
|
||||||
|
res.status(404);
|
||||||
|
next(error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GET /pages
|
* View page
|
||||||
*
|
|
||||||
* Return PageData for all pages
|
|
||||||
*/
|
*/
|
||||||
router.get('/pages', async (req, res) => {
|
router.get('/page/:id', async (req, res, next) => {
|
||||||
try {
|
const pageId = req.params.id;
|
||||||
const pages = await Pages.getAll();
|
|
||||||
|
|
||||||
res.json({
|
|
||||||
success: true,
|
|
||||||
result: pages
|
|
||||||
});
|
|
||||||
} catch (err) {
|
|
||||||
res.status(400).json({
|
|
||||||
success: false,
|
|
||||||
error: err.message
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PUT /page
|
|
||||||
*
|
|
||||||
* Create new page in the database
|
|
||||||
*/
|
|
||||||
router.put('/page', multer.any(), async (req, res) => {
|
|
||||||
try {
|
|
||||||
const {title, body, parent} = req.body;
|
|
||||||
const page = await Pages.insert({title, body, parent});
|
|
||||||
|
|
||||||
res.json({
|
|
||||||
success: true,
|
|
||||||
result: page
|
|
||||||
});
|
|
||||||
} catch (err) {
|
|
||||||
res.status(400).json({
|
|
||||||
success: false,
|
|
||||||
error: err.message
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* POST /page/:id
|
|
||||||
*
|
|
||||||
* Update page data in the database
|
|
||||||
*/
|
|
||||||
router.post('/page/:id', multer.any(), async (req, res) => {
|
|
||||||
const {id} = req.params;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const {title, body, parent} = req.body;
|
let page = await Pages.get(pageId);
|
||||||
const page = await Pages.update(id, {title, body, parent});
|
|
||||||
|
|
||||||
res.json({
|
res.render('pages/page', {
|
||||||
success: true,
|
page
|
||||||
result: page
|
|
||||||
});
|
|
||||||
} catch (err) {
|
|
||||||
res.status(400).json({
|
|
||||||
success: false,
|
|
||||||
error: err.message
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DELETE /page/:id
|
|
||||||
*
|
|
||||||
* Remove page from the database
|
|
||||||
*/
|
|
||||||
router.delete('/page/:id', async (req, res) => {
|
|
||||||
try {
|
|
||||||
const page = await Pages.remove(req.params.id);
|
|
||||||
|
|
||||||
res.json({
|
|
||||||
success: true,
|
|
||||||
result: page
|
|
||||||
});
|
|
||||||
} catch (err) {
|
|
||||||
res.status(400).json({
|
|
||||||
success: false,
|
|
||||||
error: err.message
|
|
||||||
});
|
});
|
||||||
|
} catch (error) {
|
||||||
|
res.status(404);
|
||||||
|
next(error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
3
src/views/pages/blocks/header.twig
Normal file
3
src/views/pages/blocks/header.twig
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<h{{ level }} class="block-header block-header--{{ level }}">
|
||||||
|
{{ text }}
|
||||||
|
</h{{ level }}>
|
3
src/views/pages/blocks/paragraph.twig
Normal file
3
src/views/pages/blocks/paragraph.twig
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<p class="block-paragraph">
|
||||||
|
{{ text }}
|
||||||
|
</p>
|
|
@ -7,15 +7,28 @@
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<section data-module="writing">
|
<section data-module="writing">
|
||||||
|
<module-settings hidden>
|
||||||
|
{
|
||||||
|
"page": {{ page | json_encode }}
|
||||||
|
}
|
||||||
|
</module-settings>
|
||||||
<header class="writing-header">
|
<header class="writing-header">
|
||||||
<span class="writing-header__left">
|
<span class="writing-header__left">
|
||||||
New Page at the
|
New Page at the
|
||||||
<select name="parent">
|
{% set currentPageId = 0 %}
|
||||||
<option value="0">Root</option>
|
{% if page is not empty %}
|
||||||
{% for page in pagesAvailable %}
|
{% set currentPageId = page._id %}
|
||||||
<option value="{{ page._id }}">{{ page.title }}</option>
|
{% endif %}
|
||||||
{% endfor %}
|
<select name="parent">
|
||||||
</select>
|
<option value="0">Root</option>
|
||||||
|
{% for _page in pagesAvailable %}
|
||||||
|
{% if _page._id != currentPageId %}
|
||||||
|
<option value="{{ _page._id }}" {{ page is not empty and page._parent == _page._id ? 'selected' : ''}}>
|
||||||
|
{{ _page.title }}
|
||||||
|
</option>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
</span>
|
</span>
|
||||||
<span class="writing-header__save" name="js-submit">
|
<span class="writing-header__save" name="js-submit">
|
||||||
Save
|
Save
|
||||||
|
|
38
src/views/pages/page.twig
Normal file
38
src/views/pages/page.twig
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
{% extends 'layout.twig' %}
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
<article class="page">
|
||||||
|
<header class="page__header">
|
||||||
|
<a href="/" class="page__header-nav">
|
||||||
|
Documentation
|
||||||
|
</a>
|
||||||
|
{% if page._parent %}
|
||||||
|
<a href="/page/{{ page._parent }}" class="page__header-nav">
|
||||||
|
Parent {{ page._parent }}
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
|
<time class="page__header-time">
|
||||||
|
Last edit {{ (page.body.time / 1000) | date("M d Y") }}
|
||||||
|
<a href="/page/edit/{{ page._id }}" class="page__header-button">
|
||||||
|
Edit
|
||||||
|
</a>
|
||||||
|
</time>
|
||||||
|
</header>
|
||||||
|
<h1 class="page__title">
|
||||||
|
{{ page.title }}
|
||||||
|
</h1>
|
||||||
|
<section class="page__content">
|
||||||
|
{% for block in page.body.blocks %}
|
||||||
|
{# Skip first header, because it is already showed as a Title #}
|
||||||
|
{% if not (loop.first and block.type == 'header') %}
|
||||||
|
{% if block.type in ['paragraph', 'header'] %}
|
||||||
|
{% include './blocks/' ~ block.type ~ '.twig' with block.data %}
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</section>
|
||||||
|
<footer>
|
||||||
|
</footer>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
{% endblock %}
|
|
@ -38,7 +38,7 @@ describe('Pages REST: ', () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const res = await agent
|
const res = await agent
|
||||||
.put('/page')
|
.put('/api/page')
|
||||||
.send({body});
|
.send({body});
|
||||||
|
|
||||||
expect(res).to.have.status(200);
|
expect(res).to.have.status(200);
|
||||||
|
@ -63,7 +63,7 @@ describe('Pages REST: ', () => {
|
||||||
|
|
||||||
it('Page data validation on create', async () => {
|
it('Page data validation on create', async () => {
|
||||||
const res = await agent
|
const res = await agent
|
||||||
.put('/page')
|
.put('/api/page')
|
||||||
.send({someField: 'Some text'});
|
.send({someField: 'Some text'});
|
||||||
|
|
||||||
expect(res).to.have.status(400);
|
expect(res).to.have.status(400);
|
||||||
|
@ -88,7 +88,7 @@ describe('Pages REST: ', () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const put = await agent
|
const put = await agent
|
||||||
.put('/page')
|
.put('/api/page')
|
||||||
.send({body});
|
.send({body});
|
||||||
|
|
||||||
expect(put).to.have.status(200);
|
expect(put).to.have.status(200);
|
||||||
|
@ -96,7 +96,7 @@ describe('Pages REST: ', () => {
|
||||||
|
|
||||||
const {result: {_id}} = put.body;
|
const {result: {_id}} = put.body;
|
||||||
|
|
||||||
const get = await agent.get(`/page/${_id}`);
|
const get = await agent.get(`/api/page/${_id}`);
|
||||||
|
|
||||||
expect(get).to.have.status(200);
|
expect(get).to.have.status(200);
|
||||||
expect(get).to.be.json;
|
expect(get).to.be.json;
|
||||||
|
@ -115,7 +115,7 @@ describe('Pages REST: ', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Finding page with not existing id', async () => {
|
it('Finding page with not existing id', async () => {
|
||||||
const res = await agent.get('/page/not-existing-id');
|
const res = await agent.get('/api/page/not-existing-id');
|
||||||
|
|
||||||
expect(res).to.have.status(400);
|
expect(res).to.have.status(400);
|
||||||
expect(res).to.be.json;
|
expect(res).to.be.json;
|
||||||
|
@ -139,7 +139,7 @@ describe('Pages REST: ', () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
let res = await agent
|
let res = await agent
|
||||||
.put('/page')
|
.put('/api/page')
|
||||||
.send({body});
|
.send({body});
|
||||||
|
|
||||||
expect(res).to.have.status(200);
|
expect(res).to.have.status(200);
|
||||||
|
@ -159,7 +159,7 @@ describe('Pages REST: ', () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
res = await agent
|
res = await agent
|
||||||
.post(`/page/${_id}`)
|
.post(`/api/page/${_id}`)
|
||||||
.send({body: updatedBody});
|
.send({body: updatedBody});
|
||||||
|
|
||||||
expect(res).to.have.status(200);
|
expect(res).to.have.status(200);
|
||||||
|
@ -187,7 +187,7 @@ describe('Pages REST: ', () => {
|
||||||
|
|
||||||
it('Updating page with not existing id', async () => {
|
it('Updating page with not existing id', async () => {
|
||||||
const res = await agent
|
const res = await agent
|
||||||
.post('/page/not-existing-id')
|
.post('/api/page/not-existing-id')
|
||||||
.send({body: {
|
.send({body: {
|
||||||
blocks: [
|
blocks: [
|
||||||
{
|
{
|
||||||
|
@ -221,7 +221,7 @@ describe('Pages REST: ', () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
let res = await agent
|
let res = await agent
|
||||||
.put('/page')
|
.put('/api/page')
|
||||||
.send({body});
|
.send({body});
|
||||||
|
|
||||||
expect(res).to.have.status(200);
|
expect(res).to.have.status(200);
|
||||||
|
@ -230,7 +230,7 @@ describe('Pages REST: ', () => {
|
||||||
const {result: {_id}} = res.body;
|
const {result: {_id}} = res.body;
|
||||||
|
|
||||||
res = await agent
|
res = await agent
|
||||||
.delete(`/page/${_id}`);
|
.delete(`/api/page/${_id}`);
|
||||||
|
|
||||||
expect(res).to.have.status(200);
|
expect(res).to.have.status(200);
|
||||||
expect(res).to.be.json;
|
expect(res).to.be.json;
|
||||||
|
@ -249,7 +249,7 @@ describe('Pages REST: ', () => {
|
||||||
|
|
||||||
it('Removing page with not existing id', async () => {
|
it('Removing page with not existing id', async () => {
|
||||||
const res = await agent
|
const res = await agent
|
||||||
.delete('/page/not-existing-id');
|
.delete('/api/page/not-existing-id');
|
||||||
|
|
||||||
expect(res).to.have.status(400);
|
expect(res).to.have.status(400);
|
||||||
expect(res).to.be.json;
|
expect(res).to.be.json;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue