1
Fork 0

Sync message popup

This commit is contained in:
viktorstrate 2019-07-20 18:25:15 +02:00
parent ae93c884ba
commit 56800b14a8
9 changed files with 151 additions and 12 deletions

View File

@ -10,6 +10,7 @@
"apollo-link-context": "^1.0.18", "apollo-link-context": "^1.0.18",
"apollo-link-error": "^1.1.11", "apollo-link-error": "^1.1.11",
"apollo-link-http": "^1.5.15", "apollo-link-http": "^1.5.15",
"apollo-link-ws": "^1.0.18",
"babel-plugin-styled-components": "^1.10.6", "babel-plugin-styled-components": "^1.10.6",
"cookie": "^0.4.0", "cookie": "^0.4.0",
"graphql": "^14.2.1", "graphql": "^14.2.1",
@ -24,7 +25,8 @@
"react-spring": "^8.0.27", "react-spring": "^8.0.27",
"semantic-ui-css": "^2.4.1", "semantic-ui-css": "^2.4.1",
"semantic-ui-react": "^0.87.2", "semantic-ui-react": "^0.87.2",
"styled-components": "^4.3.2" "styled-components": "^4.3.2",
"subscriptions-transport-ws": "^0.9.16"
}, },
"scripts": { "scripts": {
"start": "parcel start src/index.html", "start": "parcel start src/index.html",

View File

@ -9,6 +9,7 @@ const GlobalStyle = createGlobalStyle`
` `
import Routes from './Routes' import Routes from './Routes'
import Messages from './Messages'
class App extends Component { class App extends Component {
render() { render() {
@ -16,6 +17,7 @@ class App extends Component {
<> <>
<GlobalStyle /> <GlobalStyle />
<Routes /> <Routes />
<Messages />
</> </>
) )
} }

View File

@ -82,7 +82,7 @@ class Layout extends Component {
<Icon name="image outline" /> <Icon name="image outline" />
<SideButtonLabel>Photos</SideButtonLabel> <SideButtonLabel>Photos</SideButtonLabel>
</SideButton> </SideButton>
<SideButton to="/" exact> <SideButton to="/albums" exact>
<Icon name="images outline" /> <Icon name="images outline" />
<SideButtonLabel>Albums</SideButtonLabel> <SideButtonLabel>Albums</SideButtonLabel>
</SideButton> </SideButton>

77
ui/src/Messages.js Normal file
View File

@ -0,0 +1,77 @@
import React, { Component } from 'react'
import styled from 'styled-components'
import { Message, Progress } from 'semantic-ui-react'
import gql from 'graphql-tag'
import { Subscription } from 'react-apollo'
const syncSubscription = gql`
subscription syncSubscription {
scannerStatusUpdate {
finished
error
errorMessage
progress
}
}
`
const Container = styled.div`
position: fixed;
bottom: 20px;
right: 20px;
width: 500px;
`
const MessageProgress = ({ header, content, percent, ...props }) => {
const StyledProgress = styled(Progress)`
position: absolute !important;
bottom: 0;
left: 0;
width: 100%;
`
return (
<Message floating {...props}>
<Message.Content>
<Message.Header>{header}</Message.Header>
{content}
<StyledProgress
percent={percent}
size="tiny"
attached="bottom"
indicating
/>
</Message.Content>
</Message>
)
}
class Messages extends Component {
render() {
return (
<Container>
<Subscription subscription={syncSubscription} shouldResubscribe>
{({ loading, error, data }) => {
if (error) return <div>error {error.message}</div>
if (loading) return null
console.log('Data update', data)
const update = data.scannerStatusUpdate
return (
<MessageProgress
header={update.finished ? 'Synced' : 'Syncing'}
content={
update.finished ? 'Finished syncing' : 'Syncing in progress'
}
percent={update.progress}
/>
)
}}
</Subscription>
</Container>
)
}
}
export default Messages

View File

@ -2,7 +2,7 @@ import React, { Component } from 'react'
import Albums from './Albums' import Albums from './Albums'
import Layout from '../../Layout' import Layout from '../../Layout'
class HomePage extends Component { class AlbumsPage extends Component {
render() { render() {
return ( return (
<Layout> <Layout>
@ -13,4 +13,4 @@ class HomePage extends Component {
} }
} }
export default HomePage export default AlbumsPage

View File

@ -1,8 +1,8 @@
import React, { Component } from 'react' import React, { Component } from 'react'
import { Route, Switch } from 'react-router-dom' import { Route, Switch, Redirect } from 'react-router-dom'
import LoginPage from './Pages/LoginPage' import LoginPage from './Pages/LoginPage'
import HomePage from './Pages/HomePage/HomePage' import AlbumsPage from './Pages/AllAlbumsPage/AlbumsPage'
import AlbumPage from './Pages/AlbumPage/AlbumPage' import AlbumPage from './Pages/AlbumPage/AlbumPage'
import AuthorizedRoute from './AuthorizedRoute' import AuthorizedRoute from './AuthorizedRoute'
import PhotosPage from './Pages/PhotosPage/PhotosPage' import PhotosPage from './Pages/PhotosPage/PhotosPage'
@ -12,9 +12,11 @@ class Routes extends Component {
return ( return (
<Switch> <Switch>
<Route path="/login" component={LoginPage} /> <Route path="/login" component={LoginPage} />
<AuthorizedRoute exact path="/" component={HomePage} /> <AuthorizedRoute exact path="/albums" component={AlbumsPage} />
<AuthorizedRoute path="/album/:id" component={AlbumPage} /> <AuthorizedRoute path="/album/:id" component={AlbumPage} />
<AuthorizedRoute path="/photos" component={PhotosPage} /> <AuthorizedRoute path="/photos" component={PhotosPage} />
<Route path="/" exact render={() => <Redirect to="photos" />} />
<Route render={() => <div>Page not found</div>} />
</Switch> </Switch>
) )
} }

View File

@ -1,15 +1,41 @@
import { ApolloClient } from 'apollo-client' import { ApolloClient } from 'apollo-client'
import { InMemoryCache } from 'apollo-cache-inmemory' import { InMemoryCache } from 'apollo-cache-inmemory'
import { HttpLink } from 'apollo-link-http' import { HttpLink } from 'apollo-link-http'
import { WebSocketLink } from 'apollo-link-ws'
import { onError } from 'apollo-link-error' import { onError } from 'apollo-link-error'
import { setContext } from 'apollo-link-context' import { setContext } from 'apollo-link-context'
import { ApolloLink } from 'apollo-link' import { ApolloLink, split } from 'apollo-link'
import { getMainDefinition } from 'apollo-utilities'
const httpLink = new HttpLink({ const httpLink = new HttpLink({
uri: process.env.REACT_APP_GRAPHQL_URI, uri: process.env.REACT_APP_GRAPHQL_URI,
credentials: 'same-origin', credentials: 'same-origin',
}) })
const wsLink = new WebSocketLink({
uri: `ws://localhost:4001/graphql`,
credentials: 'same-origin',
options: {
reconnect: true,
connectionParams: {
Authorization: `Bearer ${localStorage.getItem('token')}`,
},
},
})
const link = split(
// split based on operation type
({ query }) => {
const definition = getMainDefinition(query)
return (
definition.kind === 'OperationDefinition' &&
definition.operation === 'subscription'
)
},
wsLink,
httpLink
)
const linkError = onError(({ graphQLErrors, networkError }) => { const linkError = onError(({ graphQLErrors, networkError }) => {
if (graphQLErrors) if (graphQLErrors)
graphQLErrors.map(({ message, locations, path }) => graphQLErrors.map(({ message, locations, path }) =>
@ -17,7 +43,8 @@ const linkError = onError(({ graphQLErrors, networkError }) => {
`[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}` `[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`
) )
) )
if (networkError) console.log(`[Network error]: ${networkError}`) if (networkError)
console.log(`[Network error]: ${JSON.stringify(networkError)}`)
}) })
const authLink = setContext((_, { headers }) => { const authLink = setContext((_, { headers }) => {
@ -33,7 +60,7 @@ const authLink = setContext((_, { headers }) => {
}) })
const client = new ApolloClient({ const client = new ApolloClient({
link: ApolloLink.from([linkError, authLink.concat(httpLink)]), link: ApolloLink.from([linkError, authLink.concat(link)]),
cache: new InMemoryCache(), cache: new InMemoryCache(),
}) })

View File

@ -1133,6 +1133,14 @@ apollo-link-http@^1.5.15:
apollo-link-http-common "^0.2.14" apollo-link-http-common "^0.2.14"
tslib "^1.9.3" tslib "^1.9.3"
apollo-link-ws@^1.0.18:
version "1.0.18"
resolved "https://registry.yarnpkg.com/apollo-link-ws/-/apollo-link-ws-1.0.18.tgz#281b9b0826d5fc7e2aa14d2784c5193d8b761112"
integrity sha512-nrWh9m7k1FQw1AK1GB1VTJS0o01cpsP2RYmTAh2j+P4lL2/72WgsblhbuF+yA1/jsgVrzg6xa+TNw3UwgGp3+g==
dependencies:
apollo-link "^1.2.12"
tslib "^1.9.3"
apollo-link@^1.0.0, apollo-link@^1.2.12: apollo-link@^1.0.0, apollo-link@^1.2.12:
version "1.2.12" version "1.2.12"
resolved "https://registry.yarnpkg.com/apollo-link/-/apollo-link-1.2.12.tgz#014b514fba95f1945c38ad4c216f31bcfee68429" resolved "https://registry.yarnpkg.com/apollo-link/-/apollo-link-1.2.12.tgz#014b514fba95f1945c38ad4c216f31bcfee68429"
@ -1328,6 +1336,11 @@ babylon-walk@^1.0.2:
babel-types "^6.15.0" babel-types "^6.15.0"
lodash.clone "^4.5.0" lodash.clone "^4.5.0"
backo2@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947"
integrity sha1-MasayLEpNjRj41s+u2n038+6eUc=
balanced-match@^1.0.0: balanced-match@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
@ -2515,6 +2528,11 @@ etag@~1.8.1:
resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=
eventemitter3@^3.1.0:
version "3.1.2"
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.2.tgz#2d3d48f9c346698fce83a85d7d664e98535df6e7"
integrity sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==
events@^3.0.0: events@^3.0.0:
version "3.0.0" version "3.0.0"
resolved "https://registry.yarnpkg.com/events/-/events-3.0.0.tgz#9a0a0dfaf62893d92b875b8f2698ca4114973e88" resolved "https://registry.yarnpkg.com/events/-/events-3.0.0.tgz#9a0a0dfaf62893d92b875b8f2698ca4114973e88"
@ -3531,7 +3549,7 @@ isstream@~0.1.2:
resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=
iterall@^1.2.2: iterall@^1.2.1, iterall@^1.2.2:
version "1.2.2" version "1.2.2"
resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.2.2.tgz#92d70deb8028e0c39ff3164fdbf4d8b088130cd7" resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.2.2.tgz#92d70deb8028e0c39ff3164fdbf4d8b088130cd7"
integrity sha512-yynBb1g+RFUPY64fTrFv7nsjRrENBQJaX2UL+2Szc9REFrSNm1rpSXHGzhmAy7a9uv3vlvgBlXnf9RqmPH1/DA== integrity sha512-yynBb1g+RFUPY64fTrFv7nsjRrENBQJaX2UL+2Szc9REFrSNm1rpSXHGzhmAy7a9uv3vlvgBlXnf9RqmPH1/DA==
@ -6034,6 +6052,17 @@ stylis@^3.5.0:
resolved "https://registry.yarnpkg.com/stylis/-/stylis-3.5.4.tgz#f665f25f5e299cf3d64654ab949a57c768b73fbe" resolved "https://registry.yarnpkg.com/stylis/-/stylis-3.5.4.tgz#f665f25f5e299cf3d64654ab949a57c768b73fbe"
integrity sha512-8/3pSmthWM7lsPBKv7NXkzn2Uc9W7NotcwGNpJaa3k7WMM1XDCA4MgT5k/8BIexd5ydZdboXtU90XH9Ec4Bv/Q== integrity sha512-8/3pSmthWM7lsPBKv7NXkzn2Uc9W7NotcwGNpJaa3k7WMM1XDCA4MgT5k/8BIexd5ydZdboXtU90XH9Ec4Bv/Q==
subscriptions-transport-ws@^0.9.16:
version "0.9.16"
resolved "https://registry.yarnpkg.com/subscriptions-transport-ws/-/subscriptions-transport-ws-0.9.16.tgz#90a422f0771d9c32069294c08608af2d47f596ec"
integrity sha512-pQdoU7nC+EpStXnCfh/+ho0zE0Z+ma+i7xvj7bkXKb1dvYHSZxgRPaU6spRP+Bjzow67c/rRDoix5RT0uU9omw==
dependencies:
backo2 "^1.0.2"
eventemitter3 "^3.1.0"
iterall "^1.2.1"
symbol-observable "^1.0.4"
ws "^5.2.0"
supports-color@^2.0.0: supports-color@^2.0.0:
version "2.0.0" version "2.0.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
@ -6080,7 +6109,7 @@ svgo@^1.0.0, svgo@^1.0.5:
unquote "~1.1.1" unquote "~1.1.1"
util.promisify "~1.0.0" util.promisify "~1.0.0"
symbol-observable@^1.0.2, symbol-observable@^1.1.0: symbol-observable@^1.0.2, symbol-observable@^1.0.4, symbol-observable@^1.1.0:
version "1.2.0" version "1.2.0"
resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804"
integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ== integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==