Skip to content
This repository has been archived by the owner on May 11, 2021. It is now read-only.

Commit

Permalink
feat(modal): add wip modals with routing
Browse files Browse the repository at this point in the history
  • Loading branch information
igorkamyshev committed Apr 30, 2019
1 parent 5295b31 commit 7205edb
Show file tree
Hide file tree
Showing 16 changed files with 137 additions and 21 deletions.
2 changes: 2 additions & 0 deletions front/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"next-compose-plugins": "^2.1.1",
"next-css-unpluggable": "^2.1.13",
"next-routes": "^1.4.2",
"qs": "^6.7.0",
"react": "^16.8.1",
"react-chartjs-2": "^2.7.4",
"react-dom": "^16.8.1",
Expand All @@ -50,6 +51,7 @@
"@types/js-cookie": "^2.2.0",
"@types/lodash": "^4.14.120",
"@types/next": "^7.0.7",
"@types/qs": "^6.5.3",
"@types/randomcolor": "^0.5.1",
"@types/react": "^16.8.2",
"@types/react-redux": "^7.0.1",
Expand Down
12 changes: 12 additions & 0 deletions front/src/features/app/features/navigation/Navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Menu } from '@front/ui/components/controls/menu/Menu'
import { MenuItem } from '@front/ui/components/controls/menu/MenuItem'
import { pushRoute } from '@front/features/routing'
import { getUserIsManager } from '@front/domain/user/selectors/getUserIsManager'
// import { useModalActions, useModalState } from '@front/features/modal'

interface Props {
className?: string
Expand All @@ -12,6 +13,17 @@ interface Props {
export const Navigation = ({ className }: Props) => {
const isManager = useMappedState(getUserIsManager)

// const a = useModalActions('kfd')
// const t = useModalState('kfd')
// console.log(t)

// return (
// <>
// <button onClick={a.open}>OPEN</button>
// <button onClick={a.close}>CLOSE</button>
// </>
// )

const defaultMenu = [
<MenuItem id="home" selected>
Home
Expand Down
4 changes: 2 additions & 2 deletions front/src/features/modal/ModalContext.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { createContext } from 'react'

interface ModalContextValue {
openKeys: string[]
openKeys: Set<string>
open: (key: string) => void
close: (key: string) => void
}

export const ModalContext = createContext<ModalContextValue>({
openKeys: [],
openKeys: new Set(),
open: () => null,
close: () => null,
})
52 changes: 44 additions & 8 deletions front/src/features/modal/ModalContextProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,60 @@
import { ReactNode, useState, useCallback } from 'react'
import { uniq } from 'lodash'
import qs from 'qs'

import { ModalContext } from './ModalContext'
import { useEffect } from 'react'
import { getModalKeys } from './helpers/getModalKeys'
import { updateRoute } from './helpers/updateRoute'
import { MODAL_QUERY_PREFIX } from './helpers/MODAL_QUERY_PREFIX'

interface Props {
children: ReactNode
initialQuery: any
}

export const ModalContextProvider = ({ children }: Props) => {
const [keys, setKeys] = useState<string[]>([])
export const ModalContextProvider = ({ children, initialQuery }: Props) => {
const [keys, setKeys] = useState(getModalKeys(initialQuery))

const open = useCallback((key: string) => {
setKeys(prevKeys => uniq([...prevKeys, key]))
const open = useCallback(async (key: string) => {
await updateRoute(`${MODAL_QUERY_PREFIX}${key}`, 'open')
}, [])

const close = useCallback((key: string) => {
setKeys(prevKeys => prevKeys.filter(prevKey => prevKey !== key))
const close = useCallback(async (key: string) => {
updateRoute(`${MODAL_QUERY_PREFIX}${key}`)
}, [])

// TODO: add working with routes
const onRouteChangeStart = useCallback(
({ url }: { url: string }) => {
const [, queryString] = url.split('?')
const parsedQuery = qs.parse(queryString)
const newKeys = getModalKeys(parsedQuery)
setKeys(newKeys)
},
[setKeys],
)

useEffect(() => {
const _wr = function(type: string) {
const orig = (history as any)[type]
return function(...args: any[]) {
const rv = orig.apply(this, args)
const e: any = new Event('routeChanges')
e.url = window.location.href
.replace(window.location.host, '')
.replace(`${window.location.protocol}//`, '')
window.dispatchEvent(e)
return rv
}
}
history.pushState = _wr('pushState')
history.replaceState = _wr('replaceState')

window.addEventListener('routeChanges', onRouteChangeStart as any)

return () => {
window.removeEventListener('routeChanges', onRouteChangeStart as any)
}
}, [onRouteChangeStart])

return (
<ModalContext.Provider
Expand Down
1 change: 1 addition & 0 deletions front/src/features/modal/helpers/MODAL_QUERY_PREFIX.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const MODAL_QUERY_PREFIX = 'modal__'
8 changes: 8 additions & 0 deletions front/src/features/modal/helpers/getModalKeys.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { MODAL_QUERY_PREFIX } from './MODAL_QUERY_PREFIX'

export const getModalKeys = (query: object) =>
new Set(
Object.keys(query)
.filter(key => key.startsWith(MODAL_QUERY_PREFIX))
.map(key => key.replace(MODAL_QUERY_PREFIX, '')),
)
15 changes: 15 additions & 0 deletions front/src/features/modal/helpers/updateRoute/getNewPathname.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { getQuery } from './getQuery'
import { getNewSearch } from './getNewSearch'

export const getNewPathname = (
search: string,
keyName: string,
keyValue: string | undefined,
pathname: string,
) => {
const prevQuery = getQuery(search)
const newSearch = getNewSearch(prevQuery, keyName, keyValue)
const searchSuffix = newSearch.length > 0 ? `?${newSearch}` : ''
const newPathname = `${pathname}${searchSuffix}`
return newPathname
}
11 changes: 11 additions & 0 deletions front/src/features/modal/helpers/updateRoute/getNewSearch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import qs from 'qs'

export const getNewSearch = (
prevQuery: any,
keyName: string,
currentKey?: string,
) =>
qs.stringify({
...(prevQuery || {}),
[keyName]: currentKey,
})
3 changes: 3 additions & 0 deletions front/src/features/modal/helpers/updateRoute/getQuery.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import qs from 'qs'

export const getQuery = (search: string) => qs.parse(search.split('?')[1])
1 change: 1 addition & 0 deletions front/src/features/modal/helpers/updateRoute/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { updateRoute } from './updateRoute'
10 changes: 10 additions & 0 deletions front/src/features/modal/helpers/updateRoute/updateRoute.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { pushRoute } from '@front/features/routing'

import { getNewPathname } from './getNewPathname'

export const updateRoute = (keyName: string, keyValue?: string) => {
const { pathname, search } = window.location
const newPathname = getNewPathname(search, keyName, keyValue, pathname)

return pushRoute(newPathname)
}
11 changes: 4 additions & 7 deletions front/src/features/modal/useModalActions.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
import { useContext } from 'react'
import { useMemo } from 'react'
import { ModalContext } from './ModalContext'

export const useModalActions = (key: string) => {
const { open, close } = useContext(ModalContext)

return useMemo(() => {
return {
open: () => open(key),
close: () => close(key),
}
}, [open, close, key])
return {
open: () => open(key),
close: () => close(key),
}
}
2 changes: 1 addition & 1 deletion front/src/features/modal/useModalState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ import { ModalContext } from './ModalContext'
export const useModalState = (key: string) => {
const { openKeys } = useContext(ModalContext)

return openKeys.includes(key)
return openKeys.has(key)
}
15 changes: 12 additions & 3 deletions front/src/features/modal/withModals.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,32 @@ import { ModalContextProvider } from './ModalContextProvider'

type NextProps = AppProps & DefaultAppIProps

interface QueryProps {
query: any
}

export const withModals = (Application: AppComponentType<NextProps>) => {
return class AppWithRedux extends React.Component<NextProps> {
return class AppWithRedux extends React.Component<NextProps & QueryProps> {
public static async getInitialProps(appContext: NextAppContext) {
let appProps = {}
if (typeof Application.getInitialProps === 'function') {
appProps = await Application.getInitialProps(appContext)
}

const { query } = appContext.router

return {
...appProps,
query,
}
}

public render() {
const { query, ...appProps } = this.props

return (
<ModalContextProvider>
<Application {...this.props} />
<ModalContextProvider initialQuery={query}>
<Application {...appProps} />
</ModalContextProvider>
)
}
Expand Down
1 change: 1 addition & 0 deletions front/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitAny": true,
"noImplicitThis": false,
"preserveConstEnums": true,
"removeComments": false,
"skipLibCheck": true,
Expand Down
10 changes: 10 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1288,6 +1288,11 @@
resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8"
integrity sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw==

"@types/qs@^6.5.3":
version "6.5.3"
resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.5.3.tgz#1c3b71b091eaeaf5924538006b7f70603ce63d38"
integrity sha512-Jugo5V/1bS0fRhy2z8+cUAHEyWOATaz4rbyLVvcFs7+dXp5HfwpEwzF1Q11bB10ApUqHf+yTauxI0UXQDwGrbA==

"@types/randomcolor@^0.5.1":
version "0.5.1"
resolved "https://registry.yarnpkg.com/@types/randomcolor/-/randomcolor-0.5.1.tgz#c8f5505b1ef88da8cf55a08ebef66d7bbf8fec4d"
Expand Down Expand Up @@ -9921,6 +9926,11 @@ qs@6.5.2:
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==

qs@^6.7.0:
version "6.7.0"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc"
integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==

query-string@^5.0.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/query-string/-/query-string-5.1.1.tgz#a78c012b71c17e05f2e3fa2319dd330682efb3cb"
Expand Down

0 comments on commit 7205edb

Please sign in to comment.