menu moved to config and context

This commit is contained in:
tmshv committed 2020-02-22 04:53:22 +03:00
1 parent e8fb2e817b
commit 1dbbe04d59
20 files changed
+62 -249

No files matched your search

-4
View File
@@ -2,8 +2,6 @@ import Head from 'next/head'
import { App } from 'src/components/App'
import { tail } from 'lodash'
import { Page } from 'src/components/Page'
import menuModel from 'src/models/menu'
import { buildMenu } from 'src/lib/menu'
import { Meta } from 'src/components/Meta'
import { meta } from 'src/lib/meta'
import { createApiUrl, requestGet, wrapInitialProps, IResponseItems } from 'src/next-lib'
@@ -16,7 +14,6 @@ function array<T>(value: T | T[]) {
const Index = props => (
<App
menu={buildMenu(props.pageUrl, menuModel)}
showAuthor={true}
contentStyle={{
marginTop: 'var(--size-l)'
@@ -51,7 +48,6 @@ export const unstable_getStaticProps = async (ctx: any) => {
return {
props: {
content: page.data,
pageUrl: slug,
title: page.title,
meta: meta({
title: page.title,
-6
View File
@@ -2,13 +2,10 @@ import Head from 'next/head'
import { App } from 'src/components/App'
import { Article } from 'src/components/Article'
import { Html } from 'src/components/Html'
import menuModel from 'src/models/menu'
import { buildMenu } from 'src/lib/menu'
import { createApiUrl, requestGet, IResponseItems } from 'src/next-lib'
import { NextPage } from 'next'
type Props = {
pageUrl: string
data: any //(album)
}
@@ -21,7 +18,6 @@ const Page: NextPage<Props> = props => {
return (
<App
menu={buildMenu(props.pageUrl, menuModel)}
showAuthor={true}
>
<Head>
@@ -43,7 +39,6 @@ const Page: NextPage<Props> = props => {
}
export const unstable_getStaticProps = async (ctx: any) => {
const pageUrl = '/gallery'
// const id = ctx.query.slug
const id = ctx.params.slug
const data = await requestGet(createApiUrl(`/api/albums/${id}`), null)
@@ -55,7 +50,6 @@ export const unstable_getStaticProps = async (ctx: any) => {
return {
props: {
data,
pageUrl,
}
}
}
-5
View File
@@ -3,8 +3,6 @@ import { get } from 'lodash'
import { App } from 'src/components/App'
import { Article } from 'src/components/Article'
import { Html } from 'src/components/Html'
import menuModel from 'src/models/menu'
import { buildMenu } from 'src/lib/menu'
import { Meta } from 'src/components/Meta'
import { meta } from 'src/lib/meta'
import { createApiUrl, requestGet, IResponseItems } from 'src/next-lib'
@@ -12,7 +10,6 @@ import { NextPage } from 'next'
import { IArticle } from 'src/types'
type Props = {
pageUrl: string
meta: any
data: IArticle
}
@@ -25,7 +22,6 @@ const Page: NextPage<Props> = props => {
return (
<App
menu={buildMenu(props.pageUrl, menuModel)}
showAuthor={true}
>
<Head>
@@ -59,7 +55,6 @@ export const unstable_getStaticProps = async (ctx: any) => {
return {
props: {
data,
pageUrl,
meta: meta({
title: data.title,
image: image.src,
-6
View File
@@ -2,8 +2,6 @@ import Head from 'next/head'
import { range } from 'lodash'
import { App } from 'src/components/App'
import { ArticleGrid } from 'src/components/ArticleGrid'
import menuModel from 'src/models/menu'
import { buildMenu } from 'src/lib/menu'
import { meta } from 'src/lib/meta'
import { Meta } from 'src/components/Meta'
import { createApiUrl, requestGet, IResponseItems } from 'src/next-lib'
@@ -12,7 +10,6 @@ import { NextPage } from 'next'
const pageSize = Number(process.env.APP_ARTICLES_PAGE_SIZE)
type Props = {
pageUrl: string
meta: any
title: string
data: any //(list of article)
@@ -28,7 +25,6 @@ const Page: NextPage<Props> = props => {
return (
<App
menu={buildMenu(props.pageUrl, menuModel)}
showAuthor={true}
wide={true}
>
@@ -46,7 +42,6 @@ const Page: NextPage<Props> = props => {
}
export const unstable_getStaticProps = async (ctx: any) => {
const pageUrl = '/'
// const page = parseInt(ctx.query.page)
const page = parseInt(ctx.params.slug)
const res = await requestGet<IResponseItems<any[]>>(
@@ -67,7 +62,6 @@ export const unstable_getStaticProps = async (ctx: any) => {
data,
nextPage,
prevPage,
pageUrl,
title,
meta: meta({
title,
-7
View File
@@ -3,8 +3,6 @@ import { get } from 'lodash'
import { App } from 'src/components/App'
import { Meta } from 'src/components/Meta'
import { CollectiveImage } from 'src/components/CollectiveImage'
import menuModel from 'src/models/menu'
import { buildMenu } from 'src/lib/menu'
import { meta } from 'src/lib/meta'
import { IMeta, IImage } from 'src/types'
import { createApiUrl, requestGet, IResponseItems } from 'src/next-lib'
@@ -20,7 +18,6 @@ interface IPerson {
}
type Props = {
pageUrl: string
title: string
image: string
meta: IMeta
@@ -35,7 +32,6 @@ const Page: NextPage<Props> = props => {
return (
<App
menu={buildMenu(props.pageUrl, menuModel)}
showAuthor={true}
wide={true}
>
@@ -83,7 +79,6 @@ const Page: NextPage<Props> = props => {
export const unstable_getStaticProps = async (ctx: NextPageContext) => {
// const pageUrl = ctx.req.url
const pageUrl = '/collective'
const res = await requestGet<IResponseItems<IPerson>>(createApiUrl('/api/persons'), null)
const data = res?.items || []
@@ -96,11 +91,9 @@ export const unstable_getStaticProps = async (ctx: NextPageContext) => {
props: {
data,
image,
pageUrl,
title,
meta: meta({
title,
url: pageUrl,
description: 'Преподаватели Шлиссельбургской ДХШ',
})
}
-6
View File
@@ -3,8 +3,6 @@ import Head from 'next/head'
import { App } from 'src/components/App'
import Document from 'src/components/Document'
import { Share } from 'src/components/Share'
import menuModel from 'src/models/menu'
import { buildMenu } from 'src/lib/menu'
import { meta } from 'src/lib/meta'
import { Meta } from 'src/components/Meta'
import { createApiUrl, requestGet, IResponseItems } from 'src/next-lib'
@@ -12,7 +10,6 @@ import { NextPage } from 'next'
import { IMeta } from 'src/types'
type Props = {
pageUrl: string
data: any //(file)
meta: IMeta
}
@@ -26,7 +23,6 @@ const Page: NextPage<Props> = props => {
return (
<App
menu={buildMenu(props.pageUrl, menuModel)}
showAuthor={true}
>
<Head>
@@ -40,14 +36,12 @@ const Page: NextPage<Props> = props => {
}
export const unstable_getStaticProps = async (ctx: any) => {
const pageUrl = '/documents'
const id = ctx.params.slug
const data = await requestGet(createApiUrl(`/api/files/${id}`), {})
return {
props: {
data,
pageUrl,
meta: meta({
// title: file.meta,
})
-6
View File
@@ -1,8 +1,6 @@
import Head from 'next/head'
import { App } from 'src/components/App'
import { Meta } from 'src/components/Meta'
import menuModel from 'src/models/menu'
import { buildMenu } from 'src/lib/menu'
import { meta } from 'src/lib/meta'
import { IDocument } from 'src/types'
import { DocumentList } from 'src/components/DocumentList'
@@ -94,14 +92,12 @@ function getSorted(documents: IDocument[]): IDocumentCategory[] {
interface IProps {
collections: IDocumentCategory[]
pageUrl: string
title: string
meta: any
}
const Page: NextPage<IProps> = props => (
<App
menu={buildMenu(props.pageUrl, menuModel)}
showAuthor={true}
>
<Head>
@@ -122,7 +118,6 @@ const Page: NextPage<IProps> = props => (
)
export const unstable_getStaticProps = async (ctx) => {
const pageUrl = '/documents'
const res = await requestGet<IResponseItems<IDocument>>(createApiUrl('/api/files'), null)
const files = res.items
const title = 'Документы'
@@ -131,7 +126,6 @@ export const unstable_getStaticProps = async (ctx) => {
return {
props: {
collections,
pageUrl,
title,
meta: meta({
title,
-6
View File
@@ -1,8 +1,6 @@
import Head from 'next/head'
import { App } from 'src/components/App'
import { Meta } from 'src/components/Meta'
import menuModel from 'src/models/menu'
import { buildMenu } from 'src/lib/menu'
import { splitBy } from 'src/lib/array'
import { meta } from 'src/lib/meta'
import { createApiUrl, requestGet } from 'src/next-lib'
@@ -64,14 +62,12 @@ const ACollection = ({ title, albums }) => (
interface IProps {
meta: any
pageUrl: string
title: string
collections: any[]
}
const Page: NextPage<IProps> = props => (
<App
menu={buildMenu(props.pageUrl, menuModel)}
showAuthor={true}
wide={true}
>
@@ -96,7 +92,6 @@ const Page: NextPage<IProps> = props => (
export const unstable_getStaticProps = async (ctx: any) => {
// const pageUrl = ctx.req.url
const pageUrl = '/gallery'
const res = await requestGet<any>(createApiUrl(`/api/albums`), null)
if (!res) {
return null
@@ -108,7 +103,6 @@ export const unstable_getStaticProps = async (ctx: any) => {
return {
props: {
collections: [...albumCollections.entries()],
pageUrl,
title,
meta: meta({
title,
+1 -7
View File
@@ -3,15 +3,12 @@ import { App } from 'src/components/App'
import { Meta } from 'src/components/Meta'
import { ArticleGrid } from 'src/components/ArticleGrid'
import { HudozkaTitle } from 'src/components/HudozkaTitle'
import menuModel from 'src/models/menu'
import { meta } from 'src/lib/meta'
import { buildMenu } from 'src/lib/menu'
import { createApiUrl, requestGet, IResponseItems } from 'src/next-lib'
import { NextPage } from 'next'
import { IArticle } from 'src/types'
interface IProps {
pageUrl: string
title: string
meta: any
prevPage: number
@@ -21,7 +18,6 @@ interface IProps {
const Page: NextPage<IProps> = props => (
<App
menu={buildMenu(props.pageUrl, menuModel)}
showAuthor={true}
wide={true}
>
@@ -45,7 +41,6 @@ const Page: NextPage<IProps> = props => (
)
export const unstable_getStaticProps = async () => {
const pageUrl = '/'
const page = 1
const pageSize = process.env.APP_ARTICLES_PAGE_SIZE
const res = await requestGet<IResponseItems<IArticle>>(createApiUrl(`/api/articles?page=${page}&pageSize=${pageSize}`), null)
@@ -63,11 +58,10 @@ export const unstable_getStaticProps = async () => {
articles,
nextPage,
prevPage,
pageUrl,
title,
meta: meta({
title,
url: pageUrl,
url: '/',
})
}
}
-7
View File
@@ -2,20 +2,16 @@ import Head from 'next/head'
import { App } from 'src/components/App'
import { Schedule } from 'src/components/Schedule'
import { Share } from 'src/components/Share'
import menuModel from 'src/models/menu'
import { buildMenu } from 'src/lib/menu'
import { createApiUrl, requestGet } from 'src/next-lib'
import { NextPage } from 'next'
type Props = {
pageUrl: string
title: string
data: any //(schedule)
}
const Page: NextPage<Props> = props => (
<App
menu={buildMenu(props.pageUrl, menuModel)}
showAuthor={true}
wide={true}
>
@@ -30,8 +26,6 @@ const Page: NextPage<Props> = props => (
)
export const unstable_getStaticProps = async (ctx: any) => {
// const pageUrl = ctx.req.url
const pageUrl = '/schedule'
const period = '2016-2017'
const semester = 'spring'
const data = await requestGet(createApiUrl(`/api/schedule?period=${period}&semester=${semester}`), null)
@@ -42,7 +36,6 @@ export const unstable_getStaticProps = async (ctx: any) => {
return {
props: {
data,
pageUrl,
title: 'Расписание',
}
}
-6
View File
@@ -2,8 +2,6 @@ import Head from 'next/head'
import { App } from 'src/components/App'
import { Article } from 'src/components/Article'
import { Meta } from 'src/components/Meta'
import menuModel from 'src/models/menu'
import { buildMenu } from 'src/lib/menu'
import { meta } from 'src/lib/meta'
import { createApiUrl, requestGet, IResponseItems } from 'src/next-lib'
import { NextPage } from 'next'
@@ -11,7 +9,6 @@ import { IMeta } from 'src/types'
import { Html } from 'src/components/Html'
interface IProps {
pageUrl: string
title: string
meta: IMeta
person: any
@@ -26,7 +23,6 @@ const Index: NextPage<IProps> = props => {
return (
<App
menu={buildMenu(props.pageUrl, menuModel)}
showAuthor={true}
>
<Head>
@@ -53,7 +49,6 @@ const Index: NextPage<IProps> = props => {
export const unstable_getStaticProps = async (ctx: any) => {
console.log('call unstable_getStaticProps', ctx)
const pageUrl = '/collective'
// const id = ctx.query.person
// const id = ctx.params.person ?? 'va-sarzhin'
const id = ctx.params.person //?? 'mg-timasheva'
@@ -73,7 +68,6 @@ export const unstable_getStaticProps = async (ctx: any) => {
return {
props: {
pageUrl,
person,
title,
meta: meta({
+1 -4
View File
@@ -13,7 +13,6 @@ const Navigation = dynamic(() => import('../Navigation').then(mod => mod.Navigat
})
export interface IAppProps {
menu: any
showAuthor: boolean
wide?: boolean
contentStyle?: React.CSSProperties
@@ -27,9 +26,7 @@ export const App: React.FC<IAppProps> = ({ wide = false, ...props }) => {
<Wrapper
header={(
<Header>
<Navigation
items={props.menu.items}
/>
<Navigation />
</Header>
)}
footer={(
+4 -3
View File
@@ -2,20 +2,21 @@ import './styles.css'
import cx from 'classnames'
import { MenuItem } from './MenuItem'
import { IMenu } from 'src/types'
export type MenuProps = {
layout: 'desktop' | 'mobile'
items: any[]
items: IMenu[]
}
export const Menu: React.FC<MenuProps> = props => (
<menu className={cx('menu', props.layout)}>
{props.items.map((item, index) => (
<MenuItem key={index}
href={item.url}
href={item.href}
layout={props.layout}
>
{item.text}
{item.name}
</MenuItem>
))}
</menu>
+10 -8
View File
@@ -1,25 +1,27 @@
import * as React from 'react'
import { MenuToggle } from '../MenuToggle'
import { useScreenType } from '../../hooks/useScreenType'
import { useScreenType } from 'src/hooks/useScreenType'
import { Menu } from '../Menu'
import { Overlay } from '../Overlay'
import { useState, useCallback, useContext } from 'react'
import { ConfigContext } from 'src/context/ConfigContext'
export interface INavigationProps {
items: any[]
style?: React.CSSProperties
}
export const Navigation: React.FC<INavigationProps> = props => {
const isMobile = useScreenType(['phone', 'tablet'])
const [open, setOpen] = React.useState(false)
const onClick = React.useCallback(
const [open, setOpen] = useState(false)
const onClick = useCallback(
() => {
setOpen(!open)
},
[open]
)
const { menu } = useContext(ConfigContext)
return (
<nav>
<nav style={props.style}>
<style jsx>{`
nav {
display: flex;
@@ -44,7 +46,7 @@ export const Navigation: React.FC<INavigationProps> = props => {
) : (
<Menu
layout={'desktop'}
items={props.items}
items={menu}
/>
)}
@@ -58,7 +60,7 @@ export const Navigation: React.FC<INavigationProps> = props => {
}}>
<Menu
layout={'mobile'}
items={props.items}
items={menu}
/>
</div>
</Overlay>
+38
View File
@@ -29,5 +29,43 @@ export default {
value: 'https://www.instagram.com/hudozka',
title: 'Инстаграм'
}
],
menu: [
{
name: 'Школа',
href: '/',
},
{
name: 'Расписание',
href: '/schedule',
},
{
name: 'Поступление',
href: '/join',
},
{
name: 'Предметы',
href: '/courses',
},
{
name: 'Коллектив',
href: '/collective',
},
{
name: 'Галерея',
href: '/gallery',
},
{
name: '«Мы соседи»',
href: '/neighbors',
},
{
name: 'Документы',
href: '/documents',
},
{
name: 'Сведения об образовательной организации',
href: '/info/',
},
]
}
-50
View File
@@ -1,50 +0,0 @@
import url from 'url'
import { getPathWithNoTrailingSlash } from '../lib/url'
import { urlToPattern } from '../lib/url'
import { isMatchPathPattern } from '../lib/url'
import { isEqualPath } from '../lib/url'
import { compose, any } from '../lib/common'
function isActive(path, menuItem) {
return isEqualPath(path, menuItem.url, true)
}
function isHighlighted(path, menuItem) {
return any(flatMenuItem(menuItem)
.map(i => isMatchPathPattern(
compose(urlToPattern, getPathWithNoTrailingSlash)(i.url),
path,
true
))
)
}
function flatMenuItem(item) {
const rootUrl = item.url
const flatUrls = items => {
return items.map(item => ({
...item,
url: url.resolve(rootUrl, item.url)
}))
}
return !item.items
? [item]
: item.items.reduce((acc, i) => [...acc, ...compose(flatUrls, flatMenuItem)(i)], [item])
}
/**
* Takes plain menu model and sample path and defines is an item of menu should be active
*
* @param path
* @param menu
* @return {{items}}
*/
export function buildMenu(path, menu) {
const items = menu.map(item => ({
...item,
active: isActive(path, item),
highlighted: isHighlighted(path, item),
}))
return { items }
}
-15
View File
@@ -20,21 +20,6 @@ function isMatchPathPattern(pattern, path, ignoreTrailingSlash = false) {
return pattern.test(test)
}
/**
*
* /article/* -> ^\/article\/[/\w\d-_]+\/?$
*
* @param url
* @return {RegExp}
*/
function urlToPattern(url) {
const u = url.replace('/*', '[/\\w\\d-_]+')
const pattern = `^${u}/?$`
return new RegExp(pattern)
}
exports.getPathWithNoTrailingSlash = getPathWithNoTrailingSlash
exports.isMatchPathPattern = isMatchPathPattern
exports.urlToPattern = urlToPattern
exports.isEqualPath = isEqualPath
-102
View File
@@ -1,102 +0,0 @@
export default [
{
url: '/',
text: 'Школа',
color: 'blue',
items: [
{url: '/summer-school/2017', text: 'Летние каникулы 2017'},
{url: '/articles/*', text: 'Статьи'},
{url: '/article/*', text: ''},
],
},
{
text: 'Расписание',
url: '/schedule/',
color: 'green',
items: [
{url: '*', text: ''},
]
},
{
'text': 'Поступление',
'url': '/join',
'color': 'yellow'
},
{
url: '/courses/',
text: 'Предметы',
color: 'magenta',
items: [
{url: 'ceramics', text: 'Керамика'},
{url: 'batik', text: 'Живопись'},
{url: 'easel-composition', text: 'Живопись'},
{url: 'cg', text: 'Живопись'},
{url: 'scale-modeling', text: 'Живопись'},
{url: 'drawing', text: 'Живопись'},
{url: 'costume-composition', text: 'Живопись'},
{url: 'felting', text: 'Живопись'},
{url: 'art-history', text: 'Живопись'},
{url: 'perishki', text: 'Живопись'},
{url: 'matreshki', text: 'Живопись'},
{url: 'listochki', text: 'Живопись'},
]
},
{
text: 'Коллектив',
url: '/collective',
color: 'pink',
items: [
{url: '/teacher/*', text: ''},
]
},
{
text: 'Галерея',
url: '/gallery',
color: 'red',
items: [
{url: '/album/*', text: ''},
]
},
{
text: '«Мы соседи»',
url: '/neighbors',
color: 'yellow',
},
{
text: 'Документы',
url: '/documents',
color: 'gray',
items: [
{url: '/document/*', text: ''},
]
},
{
url: '/info/',
text: 'Сведения об образовательной организации',
color: 'orange',
items: [
{url: 'main', text: 'Основные сведения'},
{url: 'structure', text: 'Структура и органы управления образовательной организацией'},
{url: 'education', text: 'Образование'},
{url: 'standards', text: 'Образовательные стандарты'},
//{url: '/collective', text: 'Руководство. Педагогический (научно-педагогический) состав'},
{url: 'support', text: 'Материально-техническое обеспечение образовательного процесса'},
{url: 'grants', text: 'Стипендии и иные виды материальной поддержки'},
{url: 'paid-services', text: 'Платные образовательные услуги'},
{url: 'finances', text: 'Финансово-хозяйственная деятельность'},
{url: 'vacancy', text: 'Вакантные места для приема'},
{url: 'tools', text: 'Список рекомендованных материалов'},
{url: 'history', text: 'История школы'},
{url: '*', text: ''},
]
},
{
'text': 'Текущий контроль',
'url': '/info/audit',
'color': 'gray'
}
]
+1 -1
View File
@@ -12,7 +12,7 @@
--biggest-font-size: 2.25rem;
/* MENU */
--menu-colored-mark-thickness: 4px;
--menu-mark-thickness: 4px;
/* SIZE */
--mobile-width: 31.25em;
+7
View File
@@ -1,3 +1,10 @@
export interface IMenu {
name: string
href: string
active: boolean
items?: IMenu[]
}
export interface IDocument {
category: string
fileName: string