From e743f57477daed0c2815201fa1f6bd35cda1a6d9 Mon Sep 17 00:00:00 2001 From: thefringeninja <495495+thefringeninja@users.noreply.github.com> Date: Mon, 18 Mar 2019 08:41:45 +0100 Subject: [PATCH 1/2] split up hal store into multiple files --- src/SqlStreamStoreBrowser.tsx | 4 +- src/stream-store/store/hal.ts | 71 --------------------- src/stream-store/store/hal/body.ts | 11 ++++ src/stream-store/store/hal/forms.ts | 23 +++++++ src/stream-store/store/hal/index.ts | 13 ++++ src/stream-store/store/hal/links.ts | 9 +++ src/stream-store/store/hal/loading.ts | 31 +++++++++ src/stream-store/store/hal/streamBrowser.ts | 29 +++++++++ src/stream-store/store/hal/url.ts | 5 ++ src/stream-store/store/index.ts | 2 + src/stream-store/store/markdown.ts | 2 +- 11 files changed, 126 insertions(+), 74 deletions(-) delete mode 100644 src/stream-store/store/hal.ts create mode 100644 src/stream-store/store/hal/body.ts create mode 100644 src/stream-store/store/hal/forms.ts create mode 100644 src/stream-store/store/hal/index.ts create mode 100644 src/stream-store/store/hal/links.ts create mode 100644 src/stream-store/store/hal/loading.ts create mode 100644 src/stream-store/store/hal/streamBrowser.ts create mode 100644 src/stream-store/store/hal/url.ts diff --git a/src/SqlStreamStoreBrowser.tsx b/src/SqlStreamStoreBrowser.tsx index 50493ac..c96fd63 100644 --- a/src/SqlStreamStoreBrowser.tsx +++ b/src/SqlStreamStoreBrowser.tsx @@ -33,7 +33,7 @@ const getSelfAlias = (links: HalLinks) => .flatMap(rel => links[rel]) .filter(({ rel }) => rel && rel.indexOf('streamStore:') === 0) .filter( - ({ rel, href }) => + ({ href }) => !!links.self.filter(link => link.href === href).length, ) .map(({ rel }) => rel); @@ -58,7 +58,7 @@ const state$ = createState( store.hal$.links$.map(links => ['_links', () => links]), store.hal$.forms$.map(forms => ['forms', () => forms]), store.hal$.loading$.map(loading => ['loading', () => loading]), - store.hal$.mediaType$.map(mediaType => ['mediaType', () => mediaType]), + store.mediaType$.map(mediaType => ['mediaType', () => mediaType]), themes.theme$.map(theme => ['theme', () => theme]), ), obs.of({ diff --git a/src/stream-store/store/hal.ts b/src/stream-store/store/hal.ts deleted file mode 100644 index d489342..0000000 --- a/src/stream-store/store/hal.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { JSONSchema7 } from 'json-schema'; -import { Observable as obs } from 'rxjs'; -import actions from 'stream-store/actions'; -import { HalResource } from 'types'; -import { hal, mediaTypes } from 'utils'; -import mediaType$ from './mediaType'; - -const body$ = actions.get.response - .zip(mediaType$) - .filter(([body, mediaType]) => mediaType === mediaTypes.hal) - .map(([{ body }]) => hal.normalizeResource(body as HalResource)); - -const url$ = actions.get.response.map(({ url }) => url); - -const links$ = body$ - .zip(url$) - .map(([{ _links }, url]) => hal.resolveLinks(url, _links)); - -const isJsonSchema = (schema: JSONSchema7 & HalResource) => - schema && schema.$schema && schema.$schema.endsWith('schema#'); - -const forms$ = body$ - .map(({ _embedded }) => _embedded) - .map(embedded => - Object.keys(embedded) - .filter(rel => isJsonSchema(embedded[rel][0])) - .reduce( - (akk, rel) => ({ - ...akk, - [rel]: embedded[rel][0], - }), - // tslint:disable-next-line:no-object-literal-type-assertion - {} as JSONSchema7, - ), - ); - -const verbs = Object.keys(actions); - -const requests$ = obs.merge( - ...verbs.map((verb: keyof typeof actions) => actions[verb].request), -); - -const responses$ = obs.merge( - ...verbs.map((verb: keyof typeof actions) => actions[verb].response), -); - -const delayedRequests$ = requests$.delay(1000); - -const loading$ = requests$ - .timestamp() - .combineLatest( - responses$.timestamp(), - delayedRequests$.timestamp(), - ( - { timestamp: requestTs }, - { timestamp: responseTs }, - { timestamp: delayedTs }, - ) => - requestTs > responseTs && - delayedTs > responseTs && - delayedTs >= requestTs, - ); - -export default { - body$, - forms$, - links$, - loading$, - mediaType$, - url$, -}; diff --git a/src/stream-store/store/hal/body.ts b/src/stream-store/store/hal/body.ts new file mode 100644 index 0000000..f5746bb --- /dev/null +++ b/src/stream-store/store/hal/body.ts @@ -0,0 +1,11 @@ +import { HalResource } from '../../../types'; +import { hal, mediaTypes } from '../../../utils'; +import actions from '../../actions'; +import mediaType$ from '../mediaType'; + +const body$ = actions.get.response + .zip(mediaType$) + .filter(([, mediaType]) => mediaType === mediaTypes.hal) + .map(([{ body }]) => hal.normalizeResource(body as HalResource)); + +export default body$; diff --git a/src/stream-store/store/hal/forms.ts b/src/stream-store/store/hal/forms.ts new file mode 100644 index 0000000..da970b1 --- /dev/null +++ b/src/stream-store/store/hal/forms.ts @@ -0,0 +1,23 @@ +import { JSONSchema7 } from 'json-schema'; +import { HalResource } from 'types'; +import body$ from './body'; + +const isJsonSchema = (schema: JSONSchema7 & HalResource) => + schema && schema.$schema && schema.$schema.endsWith('schema#'); + +const forms$ = body$ + .map(({ _embedded }) => _embedded) + .map(embedded => + Object.keys(embedded) + .filter(rel => isJsonSchema(embedded[rel][0])) + .reduce( + (akk, rel) => ({ + ...akk, + [rel]: embedded[rel][0], + }), + // tslint:disable-next-line:no-object-literal-type-assertion + {} as JSONSchema7, + ), + ); + +export default forms$; diff --git a/src/stream-store/store/hal/index.ts b/src/stream-store/store/hal/index.ts new file mode 100644 index 0000000..c413411 --- /dev/null +++ b/src/stream-store/store/hal/index.ts @@ -0,0 +1,13 @@ +import body$ from './body'; +import forms$ from './forms'; +import links$ from './links'; +import loading$ from './loading'; +import url$ from './url'; + +export default { + body$, + forms$, + links$, + loading$, + url$, +}; diff --git a/src/stream-store/store/hal/links.ts b/src/stream-store/store/hal/links.ts new file mode 100644 index 0000000..40c85cc --- /dev/null +++ b/src/stream-store/store/hal/links.ts @@ -0,0 +1,9 @@ +import { hal } from 'utils'; +import body$ from './body'; +import url$ from './url'; + +const links$ = body$ + .zip(url$) + .map(([{ _links }, url]) => hal.resolveLinks(url, _links)); + +export default links$; diff --git a/src/stream-store/store/hal/loading.ts b/src/stream-store/store/hal/loading.ts new file mode 100644 index 0000000..a707c4c --- /dev/null +++ b/src/stream-store/store/hal/loading.ts @@ -0,0 +1,31 @@ +import { Observable as obs } from 'rxjs'; +import actions from '../../actions'; + +const verbs = Object.keys(actions); + +const requests$ = obs.merge( + ...verbs.map((verb: keyof typeof actions) => actions[verb].request), +); + +const responses$ = obs.merge( + ...verbs.map((verb: keyof typeof actions) => actions[verb].response), +); + +const delayedRequests$ = requests$.delay(1000); + +const loading$ = requests$ + .timestamp() + .combineLatest( + responses$.timestamp(), + delayedRequests$.timestamp(), + ( + { timestamp: requestTs }, + { timestamp: responseTs }, + { timestamp: delayedTs }, + ) => + requestTs > responseTs && + delayedTs > responseTs && + delayedTs >= requestTs, + ); + +export default loading$; diff --git a/src/stream-store/store/hal/streamBrowser.ts b/src/stream-store/store/hal/streamBrowser.ts new file mode 100644 index 0000000..11d6bd3 --- /dev/null +++ b/src/stream-store/store/hal/streamBrowser.ts @@ -0,0 +1,29 @@ +import { createAction } from 'reactive'; +import { Observable } from 'rxjs'; +import rels from 'stream-store/rels'; +import uriTemplate from 'uri-template'; +import links$ from './links'; + +const isPotentialStreamId = (data: any) => + typeof data === 'number' || typeof data === 'string'; + +const clickPotentialStreamId = createAction().filter( + isPotentialStreamId, +) as Observable; + +const pattern$ = Observable.merge( + clickPotentialStreamId.map(pattern => pattern), + clickPotentialStreamId.map(pattern => String(pattern).replace(/-/g, '')), +).distinct(); + +const template$ = links$ + .filter(links => !!links[rels.browse]) + .map(links => links[rels.browse][0]) + .map(link => uriTemplate.parse(decodeURI(link.href))); + +pattern$.combineLatest(template$, (p, template) => ({ + headers: { authorization: '' }, + link: { + href: template.expand({ p, t: 'e' }), + }, +})); diff --git a/src/stream-store/store/hal/url.ts b/src/stream-store/store/hal/url.ts new file mode 100644 index 0000000..a6b1de7 --- /dev/null +++ b/src/stream-store/store/hal/url.ts @@ -0,0 +1,5 @@ +import actions from '../../actions'; + +const url$ = actions.get.response.map(({ url }) => url); + +export default url$; diff --git a/src/stream-store/store/index.ts b/src/stream-store/store/index.ts index 5b5d58d..12f25c2 100644 --- a/src/stream-store/store/index.ts +++ b/src/stream-store/store/index.ts @@ -1,7 +1,9 @@ import hal$ from './hal'; import markdown$ from './markdown'; +import mediaType$ from './mediaType'; export default { hal$, markdown$, + mediaType$, }; diff --git a/src/stream-store/store/markdown.ts b/src/stream-store/store/markdown.ts index e97d69c..57e8800 100644 --- a/src/stream-store/store/markdown.ts +++ b/src/stream-store/store/markdown.ts @@ -4,7 +4,7 @@ import mediaType$ from './mediaType'; const body$ = actions.get.response .zip(mediaType$) - .filter(([body, mediaType]) => mediaType === mediaTypes.markdown) + .filter(([, mediaType]) => mediaType === mediaTypes.markdown) .map(([{ body }]) => body); export default { From cef198eb1317e496172c144f0209be424c30a22d Mon Sep 17 00:00:00 2001 From: thefringeninja <495495+thefringeninja@users.noreply.github.com> Date: Mon, 18 Mar 2019 08:48:08 +0100 Subject: [PATCH 2/2] replaced deprecated component --- src/components/AuthorizationProvider.tsx | 4 ++-- src/components/HyperMediaControls/Dialog.tsx | 4 ++-- src/components/HyperMediaControls/RelButton.tsx | 4 ++-- src/components/NavigationLinks.tsx | 4 ++-- src/components/NavigationProvider.tsx | 4 ++-- src/stream-store/Viewer/HalViewer/Home.tsx | 6 +++--- src/stream-store/Viewer/HalViewer/Stream.tsx | 4 ++-- src/stream-store/Viewer/HalViewer/StreamMetadata.tsx | 6 +++--- .../Viewer/HalViewer/components/StreamMessageDetails.tsx | 4 ++-- src/stream-store/Viewer/HalViewer/index.tsx | 4 ++-- 10 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/components/AuthorizationProvider.tsx b/src/components/AuthorizationProvider.tsx index b91f950..fe7866d 100644 --- a/src/components/AuthorizationProvider.tsx +++ b/src/components/AuthorizationProvider.tsx @@ -1,4 +1,4 @@ -import React, { ComponentType, ReactNode, StatelessComponent } from 'react'; +import React, { ComponentType, FunctionComponent, ReactNode } from 'react'; import { AuthorizationProps } from 'types'; import getDisplayName from './getDisplayName'; @@ -6,7 +6,7 @@ const { Consumer, Provider } = React.createContext( undefined, ); -const AuthorizationProvider: StatelessComponent< +const AuthorizationProvider: FunctionComponent< AuthorizationProps & { children: ReactNode; } diff --git a/src/components/HyperMediaControls/Dialog.tsx b/src/components/HyperMediaControls/Dialog.tsx index 8926ba3..ef345ba 100644 --- a/src/components/HyperMediaControls/Dialog.tsx +++ b/src/components/HyperMediaControls/Dialog.tsx @@ -11,7 +11,7 @@ import { } from '@material-ui/core'; import { SlideProps } from '@material-ui/core/Slide'; import RelIcon from 'components/RelIcon'; -import React, { FormEvent, PureComponent, StatelessComponent } from 'react'; +import React, { FormEvent, FunctionComponent, PureComponent } from 'react'; import { HalLink } from 'types'; import HelpButton from './HelpButton'; import RelButton from './RelButton'; @@ -22,7 +22,7 @@ const styles = (theme: Theme) => ({ }, }); -const SlideUp: StatelessComponent = props => ( +const SlideUp: FunctionComponent = props => ( ); diff --git a/src/components/HyperMediaControls/RelButton.tsx b/src/components/HyperMediaControls/RelButton.tsx index 02ed47e..88feea8 100644 --- a/src/components/HyperMediaControls/RelButton.tsx +++ b/src/components/HyperMediaControls/RelButton.tsx @@ -1,14 +1,14 @@ import { Button } from '@material-ui/core'; import { ButtonProps } from '@material-ui/core/Button'; import RelIcon from 'components/RelIcon'; -import React, { StatelessComponent } from 'react'; +import React, { FunctionComponent } from 'react'; interface RelButtonProps { rel: string; title?: string; } -const RelButton: StatelessComponent = ({ +const RelButton: FunctionComponent = ({ rel, onClick, title, diff --git a/src/components/NavigationLinks.tsx b/src/components/NavigationLinks.tsx index 825c89c..0fb4266 100644 --- a/src/components/NavigationLinks.tsx +++ b/src/components/NavigationLinks.tsx @@ -2,8 +2,8 @@ import { IconButton } from '@material-ui/core'; import React, { ComponentType, FormEventHandler, + FunctionComponent, PureComponent, - StatelessComponent, } from 'react'; import { navigation } from 'stream-store'; import { HalLink, HalLinks, NavigatableProps } from 'types'; @@ -45,7 +45,7 @@ interface NavigationLinksProps { _links: HalLinks; } -const NavigationLinks: StatelessComponent = ({ +const NavigationLinks: FunctionComponent = ({ _links, }) => (