fetch breadcrumbs from api; button disabled support; component fix

This commit is contained in:
tmshv committed 2020-02-23 04:29:26 +03:00
1 parent 26c03dfbbf
commit aefa0ae2d4
9 files changed
+94 -50

No files matched your search

+9 -4
View File
@@ -6,7 +6,7 @@ import { Meta } from 'src/components/Meta'
import { meta } from 'src/lib/meta'
import { createApiUrl, requestGet, wrapInitialProps, IResponseItems } from 'src/next-lib'
import { NextPage } from 'next'
import { IBreadcumbsPart, IMeta } from 'src/types'
import { IBreadcumbsPart, IMeta, IPage } from 'src/types'
function array<T>(value: T | T[]) {
return Array.isArray(value)
@@ -15,9 +15,10 @@ function array<T>(value: T | T[]) {
}
type Props = {
page: any
title: string
content: string
breadcrumbs: IBreadcumbsPart[]
breadcrumb: IBreadcumbsPart[]
meta: IMeta
}
@@ -27,7 +28,7 @@ const Index: NextPage<Props> = props => (
contentStyle={{
marginTop: 'var(--size-l)'
}}
breadcrumbs={props.breadcrumbs}
breadcrumbs={props.breadcrumb}
>
<Head>
<title>{props.title}</title>
@@ -49,14 +50,17 @@ export const unstable_getStaticProps = async (ctx: any) => {
} else {
slug = '/' + array(ctx.params.slug).join('/')
}
const page = await requestGet(createApiUrl(`/api/page?page=${slug}`), null)
const page = await requestGet<IPage>(createApiUrl(`/api/page?page=${slug}`), null)
if (!page) {
throw new Error(`Not found: ${slug}`)
}
const image = page.preview ? page.preview.artifacts.fb : {}
const breadcrumbSize = page.breadcrumb?.length ?? 0
const breadcrumb = breadcrumbSize < 2 ? null : page.breadcrumb
return {
props: {
page,
content: page.data,
title: page.title,
meta: meta({
@@ -65,6 +69,7 @@ export const unstable_getStaticProps = async (ctx: any) => {
imageWidth: image.width,
imageHeight: image.height,
}),
breadcrumb,
}
}
}
+5 -1
View File
@@ -8,6 +8,8 @@ import { Content } from '../Content'
import { Block } from '../Block'
import { Breadcrumbs } from '../Breadcrumbs'
import { IBreadcumbsPart } from 'src/types'
import { useRouter } from 'next/router'
import { route } from 'next/dist/next-server/server/router'
const Navigation = dynamic(() => import('../Navigation').then(mod => mod.Navigation), {
ssr: false,
@@ -21,6 +23,7 @@ export interface IAppProps {
}
export const App: React.FC<IAppProps> = props => {
const router = useRouter()
const wide = props.wide ?? false
const blockStyle = {
alignItems: 'center'
@@ -36,7 +39,8 @@ export const App: React.FC<IAppProps> = props => {
<Block direction={'vertical'} style={blockStyle}>
<Content wide={wide}>
<Breadcrumbs
path={props.breadcrumbs}
items={props.breadcrumbs}
path={router.asPath}
/>
</Content>
</Block>
+27 -16
View File
@@ -2,30 +2,41 @@ import './styles.css'
import { IBreadcumbsPart } from 'src/types'
import { Button } from '../Button'
import { insertBetween } from 'src/lib/array'
export type BreadcrumbsProps = {
style?: React.CSSProperties
path: IBreadcumbsPart[]
items: IBreadcumbsPart[]
path: string
}
export const Breadcrumbs: React.FC<BreadcrumbsProps> = props => {
const items = insertBetween(props.items, () => '/')
return (
<nav className={'breadcrumbs'} style={props.style}>
{props.path.map((x, i) => (
<li key={x.href}>
<Button
href={x.href}
theme={'ghost'}
size={'small'}
>
{x.name}
</Button>
{items.map((x, i) => {
if (typeof x === 'string') {
return (
<li key={i}>
<span style={{ margin: '0 var(--size-xs)' }}>{x}</span>
</li>
)
}
{!(i < props.path.length - 1) ? null : (
<span style={{ margin: '0 var(--size-xs)' }}>/</span>
)}
</li>
))}
</nav>
return (
<li key={x.href}>
<Button
href={x.href}
theme={'ghost'}
size={'small'}
disabled={x.href === props.path}
>
{x.name}
</Button>
</li>
)
})}
</nav >
)
}
+6
View File
@@ -5,3 +5,9 @@
position: relative;
right: var(--size-s);
}
.breadcrumbCurrent {
color: var(--color-text-second);
font-size: var(--font-size-second);
text-overflow: ellipsis;
}
+8 -3
View File
@@ -8,13 +8,18 @@ export type ButtonProps = {
href?: string
theme?: 'default' | 'ghost'
size?: 'default' | 'small'
disabled?: boolean
}
export const Button: React.FC<ButtonProps> = ({ size='default', theme = 'default', ...props }) => {
export const Button: React.FC<ButtonProps> = ({ size = 'default', theme = 'default', disabled = false, ...props }) => {
const className = cx('button', theme, size, {
disabled
})
if (props.href) {
return (
<Link href={props.href}>
<a className={cx('button', theme, size)} style={props.style}>
<a className={className} style={props.style}>
{props.children}
</a>
</Link>
@@ -22,7 +27,7 @@ export const Button: React.FC<ButtonProps> = ({ size='default', theme = 'default
}
return (
<button className={'button'} style={props.style}>
<button className={className} style={props.style}>
{props.children}
</button>
)
+7
View File
@@ -24,6 +24,13 @@
box-shadow: var(--shadow-active);
}
/* MODIFICATORS */
.button.disabled {
pointer-events: none;
color: var(--color-text-second);
}
/* THEME */
.button.ghost {
-26
View File
@@ -1,26 +0,0 @@
export function splitBy(fn) {
return items => {
return items.reduce((acc, item) => {
const key = fn(item)
const items = acc.get(key) || []
return acc.set(key, [...items, item])
}, new Map())
}
}
export function head(list) {
return Array.isArray(list) && list.length
? list[0]
: null
}
export function last(list) {
return Array.isArray(list) && list.length
? list[list.length - 1]
: null
}
// exports.splitBy = splitBy
// exports.head = head
// exports.last = last
+22
View File
@@ -0,0 +1,22 @@
export function splitBy(fn) {
return items => {
return items.reduce((acc, item) => {
const key = fn(item)
const items = acc.get(key) || []
return acc.set(key, [...items, item])
}, new Map())
}
}
export function insertBetween<T, I = T>(items: T[], fn: (i: number) => I): Array<T | I> {
return items.reduce((acc, x, i) => {
acc.push(x)
if (i < items.length - 1) {
acc.push(fn(i))
}
return acc
}, [])
}
+10
View File
@@ -8,6 +8,16 @@ export interface IBreadcumbsPart {
href: string
}
export interface IPage {
id: string
title: string
url: string
data: string
preview: any //IImage
tokens: any[]
breadcrumb?: IBreadcumbsPart[]
}
export interface IDocument {
category: string
fileName: string