Skip to content
This repository was archived by the owner on Sep 3, 2024. It is now read-only.

Commit 8db83ba

Browse files
Merge pull request #11 from thefringeninja/defcontent-negotiation-1
Map Content Types to Views on Client
2 parents 912046c + c95f078 commit 8db83ba

File tree

21 files changed

+198
-138
lines changed

21 files changed

+198
-138
lines changed

package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,9 @@
3131
"react-schema-form": "0.5.0",
3232
"react-scripts": "2.0.5",
3333
"react-tap-event-plugin": "3.0.2",
34-
"resolve-relative-url": "1.0.0",
3534
"rxjs": "5.4.3",
35+
"uri-js": "4.2.2",
3636
"uri-template": "1.0.1",
37-
"url-join": "2.0.2",
3837
"uuid": "3.3.2"
3938
},
4039
"author": "thefringeninja <joao.paul@braganca.name>",

src/SqlStreamStoreBrowser.js

Lines changed: 15 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { createElement } from 'react';
1+
import React from 'react';
22
import { CssBaseline, AppBar, Toolbar, Typography } from '@material-ui/core';
33
import { MuiThemeProvider } from '@material-ui/core/styles';
44
import { Observable as obs } from 'rxjs';
@@ -7,37 +7,43 @@ import {
77
withAuthorization,
88
AuthorizationProvider,
99
Notifications,
10-
HyperMediaControls,
11-
NavigationLinks,
1210
Loading,
1311
} from './components';
1412
import { SqlStreamStore } from './components/Icons';
15-
import { actions, store, rels, views } from './stream-store';
13+
import { actions, store, Viewer } from './stream-store';
1614
import theme from './theme';
1715
import { createState, connect } from './reactive';
1816
import { mediaTypes } from './utils';
1917

2018
const getSelfAlias = links =>
2119
Object.keys(links)
22-
.filter(rel => rel.indexOf('streamStore:') === 0)
23-
.filter(rel => links[rel].href === links.self.href)[0];
20+
.flatMap(rel => links[rel])
21+
.filter(({ rel }) => rel.indexOf('streamStore:') === 0)
22+
.filter(
23+
({ rel, href }) =>
24+
!!links.self.filter(link => link.href === href).length,
25+
)
26+
.map(({ rel }) => rel);
2427

2528
const self$ = store.links$
2629
.filter(links => links.self)
2730
.map(getSelfAlias)
28-
.filter(rel => !!rel);
31+
.filter(rel => !!rel)
32+
.map(([link]) => link);
2933

3034
const state$ = createState(
3135
obs.merge(
3236
self$.map(self => ['self', () => self]),
3337
store.links$.map(links => ['links', () => links]),
3438
store.forms$.map(forms => ['forms', () => forms]),
3539
store.loading$.map(loading => ['loading', () => loading]),
40+
store.mediaType$.map(mediaType => ['mediaType', () => mediaType]),
3641
),
3742
obs.of({ links: {}, forms: {}, loading: false }),
3843
);
3944

4045
const onNavigate = (link, authorization) =>
46+
link.href.indexOf('#') === -1 &&
4147
actions.get.request.next({ link, headers: { authorization } });
4248

4349
const initialNavigation = ({ authorization }) =>
@@ -46,13 +52,6 @@ const initialNavigation = ({ authorization }) =>
4652
authorization,
4753
);
4854

49-
const formActions = {
50-
[rels.append]: actions.post,
51-
[rels.metadata]: actions.post,
52-
[rels.deleteStream]: actions.delete,
53-
[rels.deleteMessage]: actions.delete,
54-
};
55-
5655
const Hero = () => (
5756
<AppBar position={'static'}>
5857
<Toolbar>
@@ -65,27 +64,13 @@ const Hero = () => (
6564
);
6665

6766
const SqlStreamStoreBrowser = withAuthorization()(
68-
mount(initialNavigation)(({ self, links, forms, loading }) => (
67+
mount(initialNavigation)(({ loading, ...props }) => (
6968
<MuiThemeProvider theme={theme}>
7069
<div>
7170
<CssBaseline />
7271
<Hero />
7372
<Loading open={loading} />
74-
<section>
75-
<NavigationLinks onNavigate={onNavigate} links={links} />
76-
<HyperMediaControls
77-
actions={formActions}
78-
forms={forms}
79-
links={links}
80-
onNavigate={onNavigate}
81-
/>
82-
{createElement(views[self] || views._unknown, {
83-
links,
84-
forms,
85-
self,
86-
onNavigate,
87-
})}
88-
</section>
73+
<Viewer {...props} onNavigate={onNavigate} />
8974
<Notifications />
9075
</div>
9176
</MuiThemeProvider>

src/components/HyperMediaControls/index.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import FormButton from './FormButton';
77
import { rels } from '../../stream-store';
88

99
const isNotSelf = (rel, links) =>
10-
links[rels.self] && links[rel].href !== links[rels.self].href;
10+
links[rels.self] && links[rel][0].href !== links[rels.self][0].href;
1111

1212
const state$ = createState(store.url$.map(href => ['href', () => href]));
1313

@@ -22,10 +22,10 @@ const HyperMediaControls = ({ forms, href, actions, links, onNavigate }) => (
2222
<LinkButton
2323
key={rel}
2424
rel={rel}
25-
link={links[rel]}
25+
link={links[rel][0]}
2626
onNavigate={onNavigate}
2727
color={'active'}
28-
curies={[links[rels.curies]]}
28+
curies={links[rels.curies]}
2929
/>
3030
))}
3131
</div>
@@ -37,7 +37,7 @@ const HyperMediaControls = ({ forms, href, actions, links, onNavigate }) => (
3737
link={{ href }}
3838
actions={actions}
3939
schema={forms[rel]}
40-
curies={[links[rels.curies]]}
40+
curies={links[rels.curies]}
4141
/>
4242
))}
4343
</div>

src/components/NavigationLinks.js

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,50 @@
1-
import React from 'react';
1+
import React, { PureComponent } from 'react';
22
import { IconButton } from '@material-ui/core';
33
import RelIcon from './RelIcon';
44
import { withAuthorization } from './AuthorizationProvider';
55
import { navigation } from '../stream-store';
66
import { preventDefault } from '../utils';
77

8-
const FeedNavigationLink = ({ disabled, onClick, rel }) => (
9-
<IconButton
10-
variant={disabled ? 'disabled' : 'raised'}
11-
disabled={disabled}
12-
onClick={onClick}
13-
>
14-
<RelIcon rel={rel} />
15-
</IconButton>
8+
const FeedNavigationLink = withAuthorization()(
9+
class FeedNavigationLink extends PureComponent {
10+
_handleOnClick = e => {
11+
const { onNavigate, authorization, link } = this.props;
12+
13+
e.preventDefault();
14+
15+
if (!link) {
16+
return;
17+
}
18+
19+
return onNavigate(link, authorization);
20+
};
21+
22+
render() {
23+
const { rel, link } = this.props;
24+
return (
25+
<IconButton
26+
variant={!link ? 'disabled' : 'raised'}
27+
disabled={!link}
28+
onClick={this._handleOnClick}
29+
>
30+
<RelIcon rel={rel} />
31+
</IconButton>
32+
);
33+
}
34+
},
1635
);
1736

18-
const NavigationLinks = ({ onNavigate, links, authorization }) => (
37+
const NavigationLinks = ({ onNavigate, links }) => (
1938
<nav>
2039
{[...navigation].map(rel => (
2140
<FeedNavigationLink
22-
disabled={!links[rel]}
2341
key={rel}
24-
onClick={preventDefault(() =>
25-
onNavigate(links[rel], authorization),
26-
)}
27-
link={links[rel]}
42+
link={(links[rel] || [])[0]}
43+
onNavigate={onNavigate}
2844
rel={rel}
2945
/>
3046
))}
3147
</nav>
3248
);
3349

34-
export default withAuthorization()(NavigationLinks);
50+
export default NavigationLinks;
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
import React from 'react';
22
import { Observable as obs } from 'rxjs';
33
import inflector from 'inflector-js';
4-
import { createState, connect } from '../../reactive';
5-
import store from '../store';
4+
import { createState, connect } from '../../../reactive';
5+
import store from '../../store';
66
import {
77
Table,
88
TableBody,
99
TableRow,
1010
TableHead,
1111
TableCell,
12-
} from '../../components/StripeyTable';
12+
} from '../../../components/StripeyTable';
1313

1414
const provider$ = store.body$.map(({ provider }) => () => provider);
1515

src/stream-store/views/Stream.js renamed to src/stream-store/Viewer/HalViewer/Stream.js

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
import React from 'react';
22
import { Observable as obs } from 'rxjs';
3-
import { createState, connect } from '../../reactive';
4-
import { resolveLinks } from '../../utils';
5-
import rels from '../rels';
6-
import store from '../store';
3+
import { createState, connect } from '../../../reactive';
4+
import { resolveLinks } from '../../../utils';
5+
import rels from '../../rels';
6+
import store from '../../store';
77
import {
88
Table,
99
TableBody,
1010
TableRow,
1111
TableHead,
1212
TableCell,
13-
} from '../../components/StripeyTable';
14-
import { Hyperlink } from '../../components';
13+
} from '../../../components/StripeyTable';
14+
import { Hyperlink } from '../../../components';
1515

1616
const messages$ = store.body$
1717
.zip(store.url$)
@@ -44,12 +44,12 @@ const Message = ({
4444
<TableCell style={nowrap}>{createdUtc}</TableCell>
4545
<TableCell style={nowrap}>{type}</TableCell>
4646
<TableCell style={nowrap}>
47-
<Hyperlink link={links[rels.feed]} onNavigate={onNavigate}>
47+
<Hyperlink link={links[rels.feed][0]} onNavigate={onNavigate}>
4848
{streamId}
4949
</Hyperlink>
5050
</TableCell>
5151
<TableCell>
52-
<Hyperlink link={links.self} onNavigate={onNavigate}>
52+
<Hyperlink link={links.self[0]} onNavigate={onNavigate}>
5353
{streamId}
5454
{'@'}
5555
{streamVersion}

src/stream-store/views/StreamBrowser.js renamed to src/stream-store/Viewer/HalViewer/StreamBrowser.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import React from 'react';
22
import { Observable as obs } from 'rxjs';
3-
import StreamBrowser from '../../components/StreamBrowser';
4-
import { createState, connect } from '../../reactive';
5-
import rels from '../rels';
6-
import store from '../store';
3+
import StreamBrowser from '../../../components/StreamBrowser';
4+
import { createState, connect } from '../../../reactive';
5+
import rels from '../../rels';
6+
import store from '../../store';
77

88
const streams$ = store.body$.map(({ _embedded = {} }) => () =>
99
(_embedded[rels.feed] || [])

src/stream-store/views/StreamMessage.js renamed to src/stream-store/Viewer/HalViewer/StreamMessage.js

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,13 @@ import {
2121
TableRow,
2222
TableHead,
2323
TableCell,
24-
} from '../../components/StripeyTable';
25-
import { Hyperlink, StreamBrowser } from '../../components';
26-
import { Notes, Settings } from '../../components/Icons';
27-
import { createState, connect } from '../../reactive';
28-
import rels from '../rels';
29-
import { http } from '../../utils';
30-
import store from '../store';
24+
} from '../../../components/StripeyTable';
25+
import { Hyperlink, StreamBrowser } from '../../../components';
26+
import { Notes, Settings } from '../../../components/Icons';
27+
import { createState, connect } from '../../../reactive';
28+
import rels from '../../rels';
29+
import { http } from '../../../utils';
30+
import store from '../../store';
3131

3232
const tryParseJson = payload => {
3333
try {
@@ -73,15 +73,15 @@ const StreamMessageDetails = ({
7373
}) => (
7474
<TableRow>
7575
<TableCell style={nowrap}>
76-
<Hyperlink link={links[rels.feed]} onNavigate={onNavigate}>
76+
<Hyperlink link={links[rels.feed][0]} onNavigate={onNavigate}>
7777
{streamId}
7878
</Hyperlink>
7979
</TableCell>
8080
<TableCell style={nowrap}>{messageId}</TableCell>
8181
<TableCell style={nowrap}>{createdUtc}</TableCell>
8282
<TableCell style={nowrap}>{type}</TableCell>
8383
<TableCell style={{ width: '100%' }}>
84-
<Hyperlink link={links[rels.self]} onNavigate={onNavigate}>
84+
<Hyperlink link={links[rels.self][0]} onNavigate={onNavigate}>
8585
{streamId}
8686
{'@'}
8787
{streamVersion}

src/stream-store/views/StreamMetadata.js renamed to src/stream-store/Viewer/HalViewer/StreamMetadata.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,18 @@ import {
66
ExpansionPanelSummary,
77
ExpansionPanelDetails,
88
} from '@material-ui/core';
9-
import { Code } from '../../components/Icons';
10-
import { createState, connect } from '../../reactive';
11-
import rels from '../rels';
12-
import store from '../store';
9+
import { Code } from '../../../components/Icons';
10+
import { createState, connect } from '../../../reactive';
11+
import rels from '../../rels';
12+
import store from '../../store';
1313
import {
1414
Table,
1515
TableBody,
1616
TableRow,
1717
TableHead,
1818
TableCell,
19-
} from '../../components/StripeyTable';
20-
import { Hyperlink } from '../../components';
19+
} from '../../../components/StripeyTable';
20+
import { Hyperlink } from '../../../components';
2121

2222
const metadata$ = store.body$.map(metadata => () => metadata);
2323

src/stream-store/views/Unknown.js renamed to src/stream-store/Viewer/HalViewer/Unknown.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ import Inspector, {
55
ObjectRootLabel,
66
ObjectName,
77
} from 'react-inspector';
8-
import { createState, connect } from '../../reactive';
9-
import store from '../store';
10-
import { Hyperlink } from '../../components';
8+
import { createState, connect } from '../../../reactive';
9+
import store from '../../store';
10+
import { Hyperlink } from '../../../components';
1111

1212
const state$ = createState(
1313
store.body$.map(data => ['data', () => data]),

0 commit comments

Comments
 (0)