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

+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