Skip to content

Commit

Permalink
Baseline react demonstration
Browse files Browse the repository at this point in the history
This commit is way too large, but there isn't a huge amount of value in
breaking it up at this point... I always say that.

Anyway, this contains a very basic interface to show off the talking
point tracker functionality as it stands. It even includes a VERY
IMPRESSIVE logo which is safe to consider 100% final.

This is written in react, and leverages graphQL to load in the data
itself.

Issue #13
  • Loading branch information
slifty committed Jan 10, 2019
1 parent 7bcfbed commit 5fe050a
Show file tree
Hide file tree
Showing 18 changed files with 946 additions and 0 deletions.
7 changes: 7 additions & 0 deletions src/client/ApolloClient.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import ApolloClient from 'apollo-boost'

const client = new ApolloClient({
uri: 'http://localhost:3000/graphql',
})

export default client
68 changes: 68 additions & 0 deletions src/client/components/App.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// Imports
import React from 'react'
import { ApolloProvider } from 'react-apollo'
import { Route, BrowserRouter as Router } from 'react-router-dom'

// App Imports
import Dashboard from './Dashboard'
import EntityDetail from './EntityDetail'
import Header from './Header'
import client from '../ApolloClient'

// Component
class App extends React.Component {
state = {}

setStartTime = (startTime) => {
this.setState({ startTime })
}

setEndTime = (endTime) => {
this.setState({ endTime })
}

render() {
const { startTime, endTime } = this.state
return (
<>
<div className="container">
<Router>
<ApolloProvider client={client}>
<Header
startTime={startTime}
setStartTime={this.setStartTime}
endTime={endTime}
setEndTime={this.setEndTime}
/>
<Route
exact
path="/"
render={props => (
<Dashboard
{...props}
startTime={startTime}
endTime={endTime}
/>
)
}
/>
<Route
path="/detail"
render={props => (
<EntityDetail
{...props}
startTime={startTime}
endTime={endTime}
/>
)
}
/>
</ApolloProvider>
</Router>
</div>
</>
)
}
}

export default App
136 changes: 136 additions & 0 deletions src/client/components/Dashboard.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
import React from 'react'
import PropTypes from 'prop-types'

import { Query } from 'react-apollo'
import gql from 'graphql-tag'

import FrequencyChart from './FrequencyChart'
import SentenceViewer from './SentenceViewer'

const ALL_ENTITIES_QUERY = gql`
query ALL_ENTITIES_QUERY(
$after: String,
$before: String) {
namedEntities (
after: $after,
before: $before
) {
entity
type
createdAt
}
}
`

const RECENT_SENTENCES_QUERY = gql`
query RECENT_SENTENCES_QUERY($after: String!) {
sentences (
after: $after
) {
content
createdAt
}
}
`

class Dashboard extends React.Component {
static propTypes = {
startTime: PropTypes.number.isRequired,
endTime: PropTypes.number.isRequired,
}

render() {
const { startTime, endTime } = this.props
const currentDate = new Date()
return (
<>
<div className="row no-gutters">
<div className="col-sm-7 col-12">
<div id="dashboardEntityChart" className="elementContainer">
<h2>Keyword Counts</h2>
<Query
query={ALL_ENTITIES_QUERY}
variables={{
after: startTime,
before: endTime,
}}
>
{({ data, error, loading }) => {
if (loading) {
return <p>Loading...</p>
}
if (error) {
return (
<p>
Error:
{error.message}
</p>
)
}

const aggregatedData = data.namedEntities.reduce((accumulator, currentValue) => {
if (!(currentValue.entity in accumulator)) {
accumulator[currentValue.entity] = 0
}
accumulator[currentValue.entity] += 1
return accumulator
}, {})

const masterList = Object.keys(aggregatedData).map(key => ({
key,
val: aggregatedData[key],
}))

const sortedList = masterList.sort((a, b) => a.val < b.val)

const labels = sortedList.map(x => x.key)
const values = sortedList.map(x => x.val)

return (
<FrequencyChart
data={values}
labels={labels}
/>
)
}}
</Query>
</div>
</div>
<div className="col-sm-5 col-12">
<div id="dashboardSentences" className="elementContainer">
<h2>Recent Transcript</h2>
<Query
query={RECENT_SENTENCES_QUERY}
variables={{ after: currentDate.toISOString() }}
>
{({ data, error, loading }) => {
if (loading) {
return <p>Loading...</p>
}
if (error) {
return (
<p>
Error:
{error.message}
</p>
)
}
return (
<SentenceViewer
sentences={data.sentences}
/>
)
}}
</Query>
</div>
<div id="dashboardRecentEntities" className="elementContainer">
<h2>Recent Entities</h2>
</div>
</div>
</div>
</>
)
}
}

export default Dashboard
159 changes: 159 additions & 0 deletions src/client/components/EntityDetail.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
import React from 'react'
import PropTypes from 'prop-types'
import qs from 'query-string'

import { Query } from 'react-apollo'
import gql from 'graphql-tag'

import FrequencyChart from './FrequencyChart'
import SentenceViewer from './SentenceViewer'

const RELATED_ENTITIES_QUERY = gql`
query RELATED_ENTITIES_QUERY(
$relatedTo: String!,
$after: String,
$before: String) {
namedEntities (
relatedTo: $relatedTo,
after: $after,
before: $before
) {
entity
type
createdAt
}
}
`

const RELATED_SENTENCES_QUERY = gql`
query RELATED_SENTENCES_QUERY(
$relatedTo: String!,
$after: String,
$before: String) {
sentences (
relatedTo: $relatedTo,
after: $after,
before: $before
) {
content
createdAt
}
}
`

class Dashboard extends React.Component {
static propTypes = {
location: PropTypes.shape({
search: PropTypes.string,
}).isRequired,
startTime: PropTypes.number.isRequired,
endTime: PropTypes.number.isRequired,
}

render() {
const { location, startTime, endTime } = this.props
const relatedTo = qs.parse(location.search, { ignoreQueryPrefix: true }).entity

return (
<>
<div className="row no-gutters">
<div className="col-sm-7">
<div className="elementContainer">
<h2>
Content referencing
&quot;
{relatedTo}
&quot;
</h2>
<Query
query={RELATED_SENTENCES_QUERY}
variables={{
relatedTo,
after: startTime,
before: endTime,
}}
>
{({ data, error, loading }) => {
if (loading) {
return <p>Loading...</p>
}
if (error) {
return (
<p>
Error:
{error.message}
</p>
)
}
return (
<SentenceViewer
sentences={data.sentences}
/>
)
}}
</Query>
</div>
</div>
<div className="col-sm-5">
<div className="elementContainer">
<h2>Count over time</h2>
</div>
<div className="elementContainer">
<h2>Related Keywords</h2>
<Query
query={RELATED_ENTITIES_QUERY}
variables={{
relatedTo,
after: startTime,
before: endTime,
}}
>
{({ data, error, loading }) => {
if (loading) {
return <p>Loading...</p>
}
if (error) {
return (
<p>
Error:
{error.message}
</p>
)
}

const aggregatedData = data.namedEntities.reduce((accumulator, currentValue) => {
if (!(currentValue.entity in accumulator)) {
accumulator[currentValue.entity] = 0
}
accumulator[currentValue.entity] += 1
return accumulator
}, {})

const masterList = Object.keys(aggregatedData).map(key => ({
key,
val: aggregatedData[key],
}))

const sortedList = masterList.sort((a, b) => a.val < b.val)

const labels = sortedList.map(x => x.key)
const values = sortedList.map(x => x.val)

return (
<FrequencyChart
data={values}
labels={labels}
size={[500, 500]}
/>
)
}}
</Query>
</div>
</div>
</div>
</>
)
}
}

export default Dashboard
Loading

0 comments on commit 5fe050a

Please sign in to comment.