1
0
Fork 0
mirror of https://github.com/codex-team/codex.docs.git synced 2025-08-06 14:05:22 +02:00

Added navigation on page

This commit is contained in:
slaveeks 2022-07-01 21:30:28 +03:00
parent 8c0211d7bc
commit 587062d4d1
9 changed files with 231 additions and 7 deletions

View file

@ -1,4 +1,5 @@
import database from '../utils/database/index';
import Pages from '../controllers/pages';
const db = database['pagesOrder'];
@ -86,6 +87,105 @@ class PageOrder {
return new PageOrder(docs);
}
/**
* Returns previous page for navigation
*
* @param {string} pageId - page's id
* @returns {Promise<string | null>} - previous page id
*/
public static async getPreviousNavigationPage(pageId: string): Promise<string | null> {
const page = await Pages.get(pageId);
const pageParent = await page.getParent();
let previousPageId = null;
// Check if page has a parent
if (pageParent._id) {
// Get order by parent
const order = await this.get(pageParent._id);
// Get previous page
previousPageId = order.getSubPageBefore(pageId);
// Check if previous page consists in parent order
if (!previousPageId) {
previousPageId = pageParent._id;
}
return previousPageId;
}
// Get order, which includes getting page, because it has no parent
const order = await this.getRootPageOrder();
// Get parent page before page, which was gotten
const parentPageBefore = order.getSubPageBefore(pageId);
if (parentPageBefore) {
// Get previous parent page order
const newOrder = await this.get(parentPageBefore);
// Check if order is empty
if (!newOrder._order || newOrder._order.length == 0) {
return parentPageBefore;
}
previousPageId = newOrder._order[newOrder._order.length - 1];
}
return previousPageId;
}
/**
* Returns next page for navigation
*
* @param {string} pageId - page's id
* @returns {Promise<string | null>} - next page id
*/
public static async getNextNavigationPage(pageId: string): Promise<string | null> {
const page = await Pages.get(pageId);
const pageParent = await page.getParent();
let nextPageId;
// Check if page has a parent
if (pageParent._id) {
let order = await this.get(pageParent._id);
// Get next page by parent order
nextPageId = order.getSubPageAfter(pageId);
// Check if next page consists in parent order
if (nextPageId) {
return nextPageId;
}
// Get order, which includes parent
order = await this.getRootPageOrder();
nextPageId = order.getSubPageAfter(pageParent._id);
return nextPageId;
}
// Get order by page id
const childOrder = await this.get(pageId);
// Check if order is empty
if (childOrder._order && childOrder._order.length > 0) {
nextPageId = childOrder._order[0];
return nextPageId;
}
// Get order, which includes getting page, because it has no parent
const order = await this.getRootPageOrder();
nextPageId = order.getSubPageAfter(pageId);
return nextPageId;
}
/**
* Returns only child page's order
*
@ -182,7 +282,7 @@ class PageOrder {
*
* @param {string} pageId - identity of page
*/
public getPageBefore(pageId: string): string | null {
public getSubPageBefore(pageId: string): string | null {
if (this.order === undefined) {
return null;
}
@ -204,7 +304,7 @@ class PageOrder {
*
* @param pageId - identity of page
*/
public getPageAfter(pageId: string): string | null {
public getSubPageAfter(pageId: string): string | null {
if (this.order === undefined) {
return null;
}

View file

@ -3,6 +3,8 @@ import Aliases from '../controllers/aliases';
import Pages from '../controllers/pages';
import Alias from '../models/alias';
import verifyToken from './middlewares/token';
import PageOrder from '../models/pageOrder';
import Page from '../models/page';
const router = express.Router();
@ -32,9 +34,27 @@ router.get('*', verifyToken, async (req: Request, res: Response) => {
const pageParent = await page.getParent();
let previousPage;
let nextPage;
const previousPageId = await PageOrder.getPreviousNavigationPage(alias.id);
const nextPageId = await PageOrder.getNextNavigationPage(alias.id);
if (previousPageId){
previousPage = await Page.get(previousPageId);
}
if (nextPageId) {
nextPage = await Page.get(nextPageId);
}
res.render('pages/page', {
page,
pageParent,
previousPage,
nextPage,
config: req.app.locals.config,
});
}

View file

@ -158,8 +158,8 @@ router.delete('/page/:id', async (req: Request, res: Response) => {
}
const parentPageOrder = await PagesOrder.get(page._parent);
const pageBeforeId = parentPageOrder.getPageBefore(page._id);
const pageAfterId = parentPageOrder.getPageAfter(page._id);
const pageBeforeId = parentPageOrder.getSubPageBefore(page._id);
const pageAfterId = parentPageOrder.getSubPageAfter(page._id);
let pageToRedirect;

View file

@ -3,6 +3,8 @@ import Pages from '../controllers/pages';
import PagesOrder from '../controllers/pagesOrder';
import verifyToken from './middlewares/token';
import allowEdit from './middlewares/locals';
import PageOrder from '../models/pageOrder';
import Page from '../models/page';
const router = express.Router();
@ -62,10 +64,28 @@ router.get('/page/:id', verifyToken, async (req: Request, res: Response, next: N
const pageParent = await page.parent;
let previousPage;
let nextPage;
const previousPageId = await PageOrder.getPreviousNavigationPage(pageId);
const nextPageId = await PageOrder.getNextNavigationPage(pageId);
if (previousPageId) {
previousPage = await Page.get(previousPageId);
}
if (nextPageId) {
nextPage = await Page.get(nextPageId);
}
res.render('pages/page', {
page,
pageParent,
config: req.app.locals.config,
previousPage,
nextPage,
});
} catch (error) {
res.status(404);

View file

@ -0,0 +1,21 @@
{% set mainClass = 'navigator' %}
{% set tag = 'div' %}
{% if url is not empty %}
{% set tag = 'a' %}
{% endif %}
<{{tag}}
{{ name is not empty ? 'name="' ~ name ~ '"': '' }}
class="{{ mainClass }} {{ mainClass }}--{{ direction|default('previous') }} {{ class ?? '' }}"
{{ url is not empty ? 'href="' ~ url ~ '"' : '' }}
>
<div class="{{mainClass}}__direction">
{{ direction }}
</div>
<div class="{{mainClass}}__label">
{{ label }}
</div>
</{{tag}}>

View file

@ -23,6 +23,9 @@
{% include 'components/button.twig' with {label: 'Edit', icon: 'pencil', size: 'small', url: '/page/edit/' ~ page._id, class: 'page__header-button'} %}
{% endif %}
</header>
<script>
console.log({{prev.uri}})
</script>
<h1 class="page__title">
{{ page.title }}
</h1>
@ -39,7 +42,17 @@
{% endif %}
{% endfor %}
</section>
<footer>
<footer class="page_footer">
<div class="navigator_wrapper">
{% if previousPage %}
{% include 'components/navigator.twig' with {label: previousPage.title, direction: 'previous', url: '/' ~ previousPage.uri} %}
{% endif %}
</div>
<div class="navigator_wrapper">
{% if nextPage %}
{% include 'components/navigator.twig' with {label: nextPage.title, direction: 'next', url: '/' ~ nextPage.uri} %}
{% endif %}
</div>
</footer>
</article>

View file

@ -0,0 +1,46 @@
.navigator {
cursor: pointer;
-webkit-user-select: none;
display: flex;
flex-direction: column;
justify-content: space-between;
background-color: var(--color-bg-navigation);
border-radius: 10px;
padding: 12px 16px 12px 16px;
color: black;
width: max-content;
font-weight: 500;
font-size: 14px;
&--previous {
align-items: flex-start;
}
&--next {
align-items: flex-end;
}
&__direction {
text-transform: capitalize;
color: var(--color-direction-navigation);
font-size: 12px;
font-weight: 400;
}
&__label {
width: 100%;
}
}
.navigator_wrapper {
max-width: 100%;
margin: 0;
padding: 0;
}
.page_footer {
display: flex;
flex-direction: row;
justify-content: space-between;
width: 100%;
}

View file

@ -9,6 +9,7 @@
@import './components/auth.pcss';
@import './components/button.pcss';
@import './components/sidebar.pcss';
@import './components/navigator.pcss';
body {
font-family: system-ui, Helvetica, Arial, Verdana;

View file

@ -1,6 +1,7 @@
:root {
--color-text-main: #313649;
--color-text-second: #5d6068;
--color-direction-navigation: #717682;
--color-line-gray: #E8E8EB;
--color-link-active: #2071cc;
--color-link-hover: #F3F6F8;
@ -19,6 +20,8 @@
--color-button-warning-hover: #D65151;
--color-button-warning-active: #BD4848;
--color-bg-navigation: #F3F6F8;
/**
* Site layout sizes
@ -79,7 +82,7 @@
--squircle {
border-radius: 8px;
@supports(-webkit-mask-box-image: url('')){
border-radius: 0;
-webkit-mask-box-image: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M0 10.3872C0 1.83334 1.83334 0 10.3872 0H13.6128C22.1667 0 24 1.83334 24 10.3872V13.6128C24 22.1667 22.1667 24 13.6128 24H10.3872C1.83334 24 0 22.1667 0 13.6128V10.3872Z' fill='black'/%3E%3C/svg%3E%0A") 48% 41% 37.9% 53.3%;;
@ -95,4 +98,4 @@
@custom-media --tablet all and (min-width: 980px) and (max-width: 1050px);
@custom-media --mobile all and (max-width: 980px);
@custom-media --retina all and (-webkit-min-device-pixel-ratio: 1.5);
@custom-media --can-hover all and (hover:hover)
@custom-media --can-hover all and (hover:hover)