mirror of
https://github.com/pds-nest/nest.git
synced 2024-11-21 20:44:18 +00:00
✨ Add chart visualization
This commit is contained in:
parent
eb56dbbfc2
commit
5a27a8e734
8 changed files with 137 additions and 23 deletions
60
nest_frontend/components/base/BoxChart.js
Normal file
60
nest_frontend/components/base/BoxChart.js
Normal file
|
@ -0,0 +1,60 @@
|
|||
import React, { useRef } from "react"
|
||||
import BoxFull from "./BoxFull"
|
||||
import ChartComponent from "react-chartjs-2"
|
||||
|
||||
|
||||
export default function BoxChart({chartProps, ...props}) {
|
||||
const boxContentsRef = useRef(null)
|
||||
const getCssVar = (variable) => {
|
||||
const computedStyle = window.getComputedStyle(boxContentsRef.current)
|
||||
console.debug(variable, computedStyle.getPropertyValue(variable))
|
||||
return computedStyle.getPropertyValue(variable).trim()
|
||||
}
|
||||
|
||||
return (
|
||||
<BoxFull
|
||||
childrenProps={{ref: boxContentsRef}}
|
||||
{...props}
|
||||
>
|
||||
{boxContentsRef.current ?
|
||||
<ChartComponent
|
||||
width={boxContentsRef.current.offsetWidth}
|
||||
height={boxContentsRef.current.offsetHeight}
|
||||
options={{
|
||||
responsive: true,
|
||||
scales: {
|
||||
x: {
|
||||
beginAtZero: true,
|
||||
grid: {
|
||||
borderColor: getCssVar("--bg-light"),
|
||||
color: getCssVar("--bg-light"),
|
||||
},
|
||||
ticks: {
|
||||
color: getCssVar("--fg-primary"),
|
||||
}
|
||||
},
|
||||
y: {
|
||||
beginAtZero: true,
|
||||
grid: {
|
||||
borderColor: getCssVar("--bg-light"),
|
||||
color: getCssVar("--bg-light"),
|
||||
},
|
||||
ticks: {
|
||||
color: getCssVar("--fg-primary"),
|
||||
}
|
||||
},
|
||||
},
|
||||
elements: {
|
||||
bar: {
|
||||
backgroundColor: getCssVar("--fg-primary"),
|
||||
borderColor: "transparent",
|
||||
color: getCssVar("--fg-primary"),
|
||||
},
|
||||
},
|
||||
}}
|
||||
{...chartProps}
|
||||
/>
|
||||
: null}
|
||||
</BoxFull>
|
||||
)
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
import React from "react"
|
||||
import BoxFull from "../base/BoxFull"
|
||||
import BoxChart from "../base/BoxChart"
|
||||
|
||||
|
||||
export default function BoxVisualizationChart({ tweets, ...props }) {
|
||||
// TODO: translate this
|
||||
const hours = [...Array(24).keys()].map(hour => hour.toString())
|
||||
const hourlyTweetCount = Array(24).fill(0)
|
||||
for(const tweet of tweets) {
|
||||
const insertDate = new Date(tweet["insert_time"])
|
||||
const insertHour = insertDate.getHours()
|
||||
console.log(insertHour)
|
||||
hourlyTweetCount[insertHour] += 1
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<BoxChart
|
||||
header={"Hourly graph"}
|
||||
chartProps={{
|
||||
type: "bar",
|
||||
data: {
|
||||
labels: hours.map(hour => hour.toString()),
|
||||
datasets: [
|
||||
{
|
||||
label: "Tweets",
|
||||
data: hourlyTweetCount,
|
||||
}
|
||||
],
|
||||
}
|
||||
}}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
import React from "react"
|
||||
import BoxFull from "../base/BoxFull"
|
||||
|
||||
|
||||
export default function BoxVisualizationGraph({ children, className, ...props }) {
|
||||
// TODO: translate this
|
||||
// TODO: implement this
|
||||
|
||||
return (
|
||||
<BoxFull header={"Hourly graph"} {...props}>
|
||||
{children}
|
||||
</BoxFull>
|
||||
)
|
||||
}
|
|
@ -41,8 +41,6 @@ export default function BoxVisualizationStats({ tweets, words, totalTweetCount,
|
|||
[tweetContentCount, tweetCount],
|
||||
)
|
||||
|
||||
console.debug(words)
|
||||
|
||||
const wordCount = useMemo(
|
||||
() => words.map(word => word.value).reduce((a, b) => a + b),
|
||||
[words],
|
||||
|
|
|
@ -6,6 +6,10 @@ import { faChartBar, faCloud, faMap, faStar } from "@fortawesome/free-solid-svg-
|
|||
export default function PickerVisualization({ currentTab, setTab, ...props }) {
|
||||
return (
|
||||
<div {...props}>
|
||||
<ButtonIconOnly
|
||||
onClick={() => setTab("stats")} disabled={currentTab ===
|
||||
"stats"} color={"Grey"} icon={faStar}
|
||||
/>
|
||||
<ButtonIconOnly
|
||||
onClick={() => setTab("wordcloud")} disabled={currentTab ===
|
||||
"wordcloud"} color={"Grey"} icon={faCloud}
|
||||
|
@ -15,10 +19,6 @@ export default function PickerVisualization({ currentTab, setTab, ...props }) {
|
|||
"histogram"} color={"Grey"} icon={faChartBar}
|
||||
/>
|
||||
<ButtonIconOnly onClick={() => setTab("map")} disabled={currentTab === "map"} color={"Grey"} icon={faMap}/>
|
||||
<ButtonIconOnly
|
||||
onClick={() => setTab("stats")} disabled={currentTab ===
|
||||
"stats"} color={"Grey"} icon={faStar}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
|
|||
import { useParams } from "react-router"
|
||||
import Loading from "../components/base/Loading"
|
||||
import BoxVisualizationStats from "../components/interactive/BoxVisualizationStats"
|
||||
import BoxVisualizationGraph from "../components/interactive/BoxVisualizationGraph"
|
||||
import BoxVisualizationChart from "../components/interactive/BoxVisualizationChart"
|
||||
import BoxVisualizationMap from "../components/interactive/BoxVisualizationMap"
|
||||
import BoxVisualizationWordcloud from "../components/interactive/BoxVisualizationWordcloud"
|
||||
import BoxFull from "../components/base/BoxFull"
|
||||
|
@ -25,7 +25,7 @@ export default function PageRepository({ className, ...props }) {
|
|||
const { id } = useParams()
|
||||
const { strings } = useContext(ContextLanguage)
|
||||
|
||||
const [visualizationTab, setVisualizationTab] = useState("wordcloud")
|
||||
const [visualizationTab, setVisualizationTab] = useState("stats")
|
||||
const [addFilterTab, setAddFilterTab] = useState("hashtag")
|
||||
|
||||
const repositoryBr = useBackendResource(
|
||||
|
@ -99,7 +99,7 @@ export default function PageRepository({ className, ...props }) {
|
|||
/>
|
||||
: null}
|
||||
{visualizationTab === "histogram" ?
|
||||
<BoxVisualizationGraph
|
||||
<BoxVisualizationChart
|
||||
className={Style.Wordcloud}
|
||||
tweets={tweets}
|
||||
/>
|
||||
|
|
33
package-lock.json
generated
33
package-lock.json
generated
|
@ -22,6 +22,7 @@
|
|||
"is-string": "^1.0.5",
|
||||
"leaflet": "^1.7.1",
|
||||
"react": "^17.0.2",
|
||||
"react-chartjs-2": "^3.0.3",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-leaflet": ">=3.1.0 <3.2.0 || ^3.2.1",
|
||||
"react-router": "^5.2.0",
|
||||
|
@ -5132,6 +5133,12 @@
|
|||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/chart.js": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/chart.js/-/chart.js-3.2.1.tgz",
|
||||
"integrity": "sha512-XsNDf3854RGZkLCt+5vWAXGAtUdKP2nhfikLGZqud6G4CvRE2ts64TIxTTfspOin2kEZvPgomE29E6oU02dYjQ==",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/check-types": {
|
||||
"version": "11.1.2",
|
||||
"resolved": "https://registry.npmjs.org/check-types/-/check-types-11.1.2.tgz",
|
||||
|
@ -16155,6 +16162,18 @@
|
|||
"react-scripts": ">=2.1.3"
|
||||
}
|
||||
},
|
||||
"node_modules/react-chartjs-2": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-3.0.3.tgz",
|
||||
"integrity": "sha512-jOFZKwZ8sMLkddewZ/tToxuu4pYimAvvY5I6uK+hCpSFT16Pvo2bdHhUoZ0X87zu9I+dx2I+JCqaLN6XhmrbDg==",
|
||||
"dependencies": {
|
||||
"lodash": "^4.17.19"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"chart.js": "^3.1.0",
|
||||
"react": "^16.8.0 || ^17.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-dev-utils": {
|
||||
"version": "11.0.4",
|
||||
"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-11.0.4.tgz",
|
||||
|
@ -26645,6 +26664,12 @@
|
|||
"resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz",
|
||||
"integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw=="
|
||||
},
|
||||
"chart.js": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/chart.js/-/chart.js-3.2.1.tgz",
|
||||
"integrity": "sha512-XsNDf3854RGZkLCt+5vWAXGAtUdKP2nhfikLGZqud6G4CvRE2ts64TIxTTfspOin2kEZvPgomE29E6oU02dYjQ==",
|
||||
"peer": true
|
||||
},
|
||||
"check-types": {
|
||||
"version": "11.1.2",
|
||||
"resolved": "https://registry.npmjs.org/check-types/-/check-types-11.1.2.tgz",
|
||||
|
@ -35334,6 +35359,14 @@
|
|||
"semver": "^5.6.0"
|
||||
}
|
||||
},
|
||||
"react-chartjs-2": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-3.0.3.tgz",
|
||||
"integrity": "sha512-jOFZKwZ8sMLkddewZ/tToxuu4pYimAvvY5I6uK+hCpSFT16Pvo2bdHhUoZ0X87zu9I+dx2I+JCqaLN6XhmrbDg==",
|
||||
"requires": {
|
||||
"lodash": "^4.17.19"
|
||||
}
|
||||
},
|
||||
"react-dev-utils": {
|
||||
"version": "11.0.4",
|
||||
"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-11.0.4.tgz",
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
"is-string": "^1.0.5",
|
||||
"leaflet": "^1.7.1",
|
||||
"react": "^17.0.2",
|
||||
"react-chartjs-2": "^3.0.3",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-leaflet": ">=3.1.0 <3.2.0 || ^3.2.1",
|
||||
"react-router": "^5.2.0",
|
||||
|
|
Loading…
Reference in a new issue