From d339801aba3fcedc0b3027f73dac91deaae14acc Mon Sep 17 00:00:00 2001 From: Michael Foiani Date: Fri, 16 Apr 2021 18:58:58 -0400 Subject: Removed old testing react app for frontend. --- react-frontend/src/components/DateSelector.js | 17 +++++++ react-frontend/src/components/Hub.js | 24 +++++++++ react-frontend/src/components/HubList.js | 62 +++++++++++++++++++++++ react-frontend/src/components/InvestorInfo.js | 66 ++++++++++++++++++++++++ react-frontend/src/components/Loading.js | 20 ++++++++ react-frontend/src/components/TimeSelector.js | 48 ++++++++++++++++++ react-frontend/src/components/Visualization.js | 69 ++++++++++++++++++++++++++ 7 files changed, 306 insertions(+) create mode 100644 react-frontend/src/components/DateSelector.js create mode 100644 react-frontend/src/components/Hub.js create mode 100644 react-frontend/src/components/HubList.js create mode 100644 react-frontend/src/components/InvestorInfo.js create mode 100644 react-frontend/src/components/Loading.js create mode 100644 react-frontend/src/components/TimeSelector.js create mode 100644 react-frontend/src/components/Visualization.js (limited to 'react-frontend/src/components') diff --git a/react-frontend/src/components/DateSelector.js b/react-frontend/src/components/DateSelector.js new file mode 100644 index 0000000..bf01d44 --- /dev/null +++ b/react-frontend/src/components/DateSelector.js @@ -0,0 +1,17 @@ +// CSS import +import '../css/Route.css'; +import '../css/CoordSelector.css'; + +/** + * The component that selects and displays a coordinate. + * @param {Object} props The props for the element. + */ +function DateSelector(props) { + return ( +
+ props.changedFunc(new Date(e.target.value))} onClick={() => props.clickedFunc()}/> +
+ ); +} + +export default DateSelector; \ No newline at end of file diff --git a/react-frontend/src/components/Hub.js b/react-frontend/src/components/Hub.js new file mode 100644 index 0000000..8a3ac1c --- /dev/null +++ b/react-frontend/src/components/Hub.js @@ -0,0 +1,24 @@ +// React import +import { useState } from "react"; + +// CSS import +import '../css/UserCheckin.css'; + +/** + * Componenet for checkins. Has a toggle to show more info. + * @param {Object} props The props of the component. + * @returns {import('react').HtmlHTMLAttributes} A list element holding a checkin's info. + */ +function Hub(props) { + // State - toggled + + return ( +
  • +
    + console.log(props.id)}>{props.name} + {props.value.toFixed(3)} +
    +
  • ); +} + +export default Hub; \ No newline at end of file diff --git a/react-frontend/src/components/HubList.js b/react-frontend/src/components/HubList.js new file mode 100644 index 0000000..f5b1414 --- /dev/null +++ b/react-frontend/src/components/HubList.js @@ -0,0 +1,62 @@ +// React and component imports +import { useEffect, useState } from "react"; +import Hub from "./Hub.js"; +import InvestorInfo from "./InvestorInfo.js"; + +// CSS import +import '../css/UserCheckin.css'; + +/** + * Component that build the checkin list and displays checkin info. + * @returns {import('react').HtmlHTMLAttributes} A div with the hubs + * in a vertical layout. + */ +function HubList(props) { + const [hubItems, setHubItems] = useState([]); + const [isSelected, setIsSelected] = useState(false); + const [name, setName] = useState(''); + + /** + * Loads new the checkins into the current cache/map of hubs. + */ + const updateHubItems = () => { + // sort and create the elemnts + let hubs = []; + const sorted = props.data.sort((a, b) => b.suspicionScore - a.suspicionScore); + sorted.forEach(hub => hubs.push( + + )); + + setHubItems(hubs); + } + + const getName = () => { + props.data.forEach(hub => { + if (hub.id == props.selected) { + setName(hub.name); + } + }) + setName(''); + } + + // React hook that updates when the hubs are recalculated + useEffect(() => updateHubItems(), [props.data]); + + //React hook to show data for an investor + useEffect(() => { + setIsSelected(true) + getName(); + }, [props.selected]); + + return ( +
    +
    +

    Suspicion Ranks

    +
      {hubItems}
    +
    + +
    + ); +} + +export default HubList; \ No newline at end of file diff --git a/react-frontend/src/components/InvestorInfo.js b/react-frontend/src/components/InvestorInfo.js new file mode 100644 index 0000000..d368984 --- /dev/null +++ b/react-frontend/src/components/InvestorInfo.js @@ -0,0 +1,66 @@ +// React import +import { useEffect, useState } from "react"; + +// CSS import +import '../css/UserCheckin.css'; + +/** + * Componenet for checkins. Has a toggle to show more info. + * @param {Object} props The props of the component. + * @returns {import('react').HtmlHTMLAttributes} A list element holding a checkin's info. + */ +function InvestorInfo(props) { + const [info, setInfo] = useState({}); + + const toEpochMilli = date => Date.parse(date); + const getInfo = () => { + console.log({ + person: props.name, + start: toEpochMilli(props.dates.start), + end: toEpochMilli(props.dates.end) + }); + + if (props.name === "") { + return; + } + + fetch("http://localhost:4567/profit", { + method: "POST", + body: JSON.stringify({ + person: props.name, + start: toEpochMilli(props.dates.start), + end: toEpochMilli(props.dates.end) + }), + headers: { + "Content-Type": "application/json", + }, + credentials: "same-origin" + }) + .then(res => { + console.log(res); + res.json(); + }) + .then(data => { + console.log(data); + setInfo(data); + }) + .catch(err => console.log(err)); + } + /* + + const coords = userCoords.map((coord, index) => +
  • + {'('+coord[0].toFixed(6)}, {coord[1].toFixed(6)+')'} +
  • + );*/ + + useEffect(() => getInfo(), [props.name, props.isSelected, props.personId]) + + return ( + + ); +} + +export default InvestorInfo; \ No newline at end of file diff --git a/react-frontend/src/components/Loading.js b/react-frontend/src/components/Loading.js new file mode 100644 index 0000000..6fdf5ba --- /dev/null +++ b/react-frontend/src/components/Loading.js @@ -0,0 +1,20 @@ +// CSS import +import '../css/App.css'; + +/** + * Component that shows the program initially loading. + * @returns The loading widget - spinning logo :) + */ +function Loading() { + return ( +
    +
    + logo +

    Loading WatchDogs

    +

    It takes a minute to connect to the servers and database :)

    +
    +
    + ); +} + +export default Loading; \ No newline at end of file diff --git a/react-frontend/src/components/TimeSelector.js b/react-frontend/src/components/TimeSelector.js new file mode 100644 index 0000000..6960807 --- /dev/null +++ b/react-frontend/src/components/TimeSelector.js @@ -0,0 +1,48 @@ +// React/Component imports +import { useEffect, useState } from "react"; +import DateSelector from './DateSelector.js'; + +// CSS imports +import '../css/Route.css'; + + +/** + * The component that hold the forms for routing. + * @param {Object} props + */ +function TimeSelector(props) { + const [current, setCurrent] = useState(""); + + const toValue = date => new Date(date).toISOString().slice(0, 10); + + const [startDate, setStartDate] = useState(props.dates.start); + const [endDate, setEndDate] = useState(props.dates.end); + + const changeTimeframe = () => { + props.setDates({ + start: startDate, + end: endDate + }); + } + + useEffect(() => setCurrent(""), [startDate, endDate]); + + // The div with the html elements for routing. + return ( +
    +
    + +
    +

    Adjust Timeframe :)

    + +
    + +
    +
    + ); +} + +export default TimeSelector; \ No newline at end of file diff --git a/react-frontend/src/components/Visualization.js b/react-frontend/src/components/Visualization.js new file mode 100644 index 0000000..91082e9 --- /dev/null +++ b/react-frontend/src/components/Visualization.js @@ -0,0 +1,69 @@ +// JS module imports +import { useEffect, useRef, useState } from "react"; +import uuid from 'react-uuid'; +import Graph from 'vis-react'; + +// CSS imports +import '../css/Canvas.css'; + +/** + * This function renders and mantains thhe canvas. + * @param {Object} props The props for the canvas. + * @returns {import("react").HtmlHTMLAttributes} The canvas to be retured. + */ +function Visualization(props) { + const options = { + edges: { + color: "#ffffff" + }, + autoResize: true + }; + const events = { + select: () => event => props.setSelected(event.nodes[0]) + }; + + const [graphState, setGraphState] = useState({ + nodes: [], + edges: [] + }); + const getNodes = () => { + let nodes = []; + props.data.forEach(hub => { + nodes.push({ + id: hub.id, + label: hub.name, + size: hub.suspicionScore * 10 + }); + }); + return nodes; + } + const getEdges = () => { + let edges = [] + props.data.forEach(hub => { + hub.followers.forEach(follower => { + edges.push({ + from: hub.id, + to: follower.id + }); + }); + }); + return edges; + } + + // Hooks to update graph state + useEffect(() => setGraphState({nodes: getNodes(), edges: getEdges()}), [JSON.stringify(props.data)]); + + return ( +
    + + +
    + ); +} + +export default Visualization; + -- cgit v1.2.3-70-g09d2 From fc88d4d950e4cfad96102267d1ec7c0042ed78f2 Mon Sep 17 00:00:00 2001 From: 9308233900 Date: Sat, 17 Apr 2021 00:12:57 -0700 Subject: orientation completed --- react-frontend/src/App.js | 3 + react-frontend/src/components/HubList.js | 1 + react-frontend/src/components/Modal.js | 70 ++++++++++++++ react-frontend/src/components/landing.html | 10 ++ react-frontend/src/css/Modal.css | 146 +++++++++++++++++++++++++++++ 5 files changed, 230 insertions(+) create mode 100644 react-frontend/src/components/Modal.js create mode 100644 react-frontend/src/components/landing.html create mode 100644 react-frontend/src/css/Modal.css (limited to 'react-frontend/src/components') diff --git a/react-frontend/src/App.js b/react-frontend/src/App.js index 2eb0c81..fd7d648 100644 --- a/react-frontend/src/App.js +++ b/react-frontend/src/App.js @@ -4,6 +4,7 @@ import TimeSelector from './components/TimeSelector.js'; import Visualization from './components/Visualization.js'; import HubList from './components/HubList.js'; import Loading from './components/Loading.js'; +import Modal from './components/Modal.js'; // CSS import import './css/App.css'; @@ -50,6 +51,7 @@ function App() { setIsChanging(false); } + // Hooks to update data on init and switching of data useEffect(() => getGraphData(), []); useEffect(() => { @@ -61,6 +63,7 @@ function App() { <> {(!hasLoaded) ? :
    + PHP
    Welcome to WatchDogs!
    diff --git a/react-frontend/src/components/HubList.js b/react-frontend/src/components/HubList.js index f5b1414..5736e89 100644 --- a/react-frontend/src/components/HubList.js +++ b/react-frontend/src/components/HubList.js @@ -39,6 +39,7 @@ function HubList(props) { setName(''); } + // React hook that updates when the hubs are recalculated useEffect(() => updateHubItems(), [props.data]); diff --git a/react-frontend/src/components/Modal.js b/react-frontend/src/components/Modal.js new file mode 100644 index 0000000..3ce5d39 --- /dev/null +++ b/react-frontend/src/components/Modal.js @@ -0,0 +1,70 @@ +import { useEffect, useState } from "react"; + +import '../css/Modal.css'; + + +function Modal() { + + const [count, setCount] = useState(0); + + const nextModal1 = () => { + setCount(1); + } + const nextModal2 = () => { + setCount(2); + } + const nextModal3 = () => { + setCount(3); + } + const nextModal4 = () => { + setCount(4); + } + const startModal = () => { + document.getElementById("main-modal").style.display = 'block'; + setCount(0); + } + const exitModal = () => { + document.getElementById("main-modal").style.display = 'none'; + } + + + return ( +
    +
    + {(count == 0) &&

    +

    Welcome to WatchDogs!

    +

    Click start for an introduction to the WatchDogs interface.

    +

    +

    +

    } + {(count == 1) &&

    +

    + This is the suspicion ranking pane, which displays + high-profile traders and the suspicion score our algorithm assigned + to them. The higher an individual is ranked, the more likely they are involved in insider trading. +

    +

    } + {(count == 2) &&

    +

    + The Timeframe pane + allows you to chose the timespan you'd like to see trade data from. Individuals' suspicion score will + be calculated based on the trades that occured during the timeframe you select. +

    +

    +

    } + {count == 3 &&

    +

    + The Trader Graph + shows how traders are related. Click on a name in the graph to see more information about that individual. +

    +

    } + {count == 4 &&

    + +

    } +
    + +
    + ); +} + +export default Modal; \ No newline at end of file diff --git a/react-frontend/src/components/landing.html b/react-frontend/src/components/landing.html new file mode 100644 index 0000000..8b33b5c --- /dev/null +++ b/react-frontend/src/components/landing.html @@ -0,0 +1,10 @@ + + + + + WatchDogLanding + + +

    Hello welcome to watchdog

    + + diff --git a/react-frontend/src/css/Modal.css b/react-frontend/src/css/Modal.css new file mode 100644 index 0000000..7ee5045 --- /dev/null +++ b/react-frontend/src/css/Modal.css @@ -0,0 +1,146 @@ +.modal { + background-color: aqua; + display: block; /* Hidden by default */ + position: fixed; /* Stay in place */ + z-index: 100; /* Sit on top */ + padding-top: 100px; /* Location of the box */ + left: 0; + top: 0; + width: 100%; /* Full width */ + height: 100%; /* Full height */ + overflow: auto; /* Enable scroll if needed */ + background-color: rgba(0, 0, 0, 0.8); + color: white; +} + +.m{ + border: 7px solid rgb(7, 94, 12); + border-radius: 5px; + background-color: white; + color: black; + position: fixed; + height: fit-content; + width: 20vw; + padding: .5%; +} + +.modal0{ + top: 30vh; + left: 40vw; +} +.modal1{ + top: 7vh; + right: 29vw; +} +@media (max-width: 750px) { + .modal1{ + top: 7vh; + right: 0vw; + } +} +.modal2{ + bottom: 20vh; + left: 5vw; +} +.modal3{ + top: 35vh; + left: 45vw; +} +.modal4{ + top: 30vh; + left: 37vw; + padding: 2%; +} + +.restart-modal:after{ + z-index: 101; + border: 7px solid rgb(7, 94, 12); + border-radius: 15px; + background-color: white; + color: black; + position: fixed; + height: 25px; + width: 30px; + bottom: 30px; + right: 3vw; + content:'?'; +} +.restart-modal:hover:after{ + content:'Restart Orientation'; + width: 150px; +} + +span { + font-weight: bold; + color:rgba(10, 9, 71); +} + +.arrow { + border: solid black; + border-width: 0 3px 3px 0; + display: inline-block; + padding: 3px; + } + + .right { + transform: rotate(-45deg); + -webkit-transform: rotate(-45deg); + } + + .left { + transform: rotate(135deg); + -webkit-transform: rotate(135deg); + } + + .up { + transform: rotate(-135deg); + -webkit-transform: rotate(-135deg); + } + + .down { + transform: rotate(45deg); + -webkit-transform: rotate(45deg); + } + + .align-right{ + text-align: right; + margin-right: 15px; + } + + .align-center{ + text-align: center; + } + + .align-left{ + text-align: left; + margin-left: 15px; + } + + .next{ + background-color: rgb(206, 206, 206); + color: black; + border: 2px solid rgba(10, 9, 71); + border-radius: 5px; + padding: 5px 10px; + text-align: center; + text-decoration: none; + display: inline-block; + font-size: 16px; + } + + .next:hover { + background-color: rgb(7, 94, 12); + color: white; + } + + .skip{ + background-color: white; + border: none; + color:rgb(119, 119, 119); + } + + .skip:hover{ + color: black; + } + + -- cgit v1.2.3-70-g09d2 From c1bcc55be1ada49e63a7cfd49c36695019e36658 Mon Sep 17 00:00:00 2001 From: 9308233900 Date: Sat, 17 Apr 2021 01:59:47 -0700 Subject: sidebar contrast bug fixed, landing page started --- landing.html | 83 ++++++++++++ react-frontend/src/components/Modal.js | 8 +- react-frontend/src/components/landing.html | 10 -- react-frontend/src/css/Landing.css | 202 +++++++++++++++++++++++++++++ react-frontend/src/css/Modal.css | 2 +- 5 files changed, 290 insertions(+), 15 deletions(-) create mode 100644 landing.html delete mode 100644 react-frontend/src/components/landing.html create mode 100644 react-frontend/src/css/Landing.css (limited to 'react-frontend/src/components') diff --git a/landing.html b/landing.html new file mode 100644 index 0000000..80bb9dc --- /dev/null +++ b/landing.html @@ -0,0 +1,83 @@ + + + + + WatchDogLanding + + + + +
    + +
    Hello welcome to watchdog + +
    + +
    pic preview
    + +
    +

    Our App

    +

    subtitle

    +

    who we are; our inspiration; purpose of our app: who for, what it's not

    +
    our data
    +
    our algorithm
    +
    + +
    +
    +
    +

    Meet the Team

    +

    subtext

    + +
    +
    +
    + +
    +

    Clark

    +

    subtxt

    +
    + +
    +
    + +
    +

    Julia

    +

    subtxt

    +
    + +
    +
    + +
    +

    Michael

    +

    subtxt

    +
    + +
    +
    + +
    +

    Reagan

    +

    subtxt

    +
    +
    +
    +
    +
    +
    + +
    + + +
    + + + diff --git a/react-frontend/src/components/Modal.js b/react-frontend/src/components/Modal.js index 3ce5d39..ad69650 100644 --- a/react-frontend/src/components/Modal.js +++ b/react-frontend/src/components/Modal.js @@ -32,21 +32,21 @@ function Modal() {
    {(count == 0) &&

    -

    Welcome to WatchDogs!

    +

    Welcome to WatchDogs!

    Click start for an introduction to the WatchDogs interface.

    } {(count == 1) &&

    - This is the suspicion ranking pane, which displays + This is the suspicion ranking pane, which displays high-profile traders and the suspicion score our algorithm assigned to them. The higher an individual is ranked, the more likely they are involved in insider trading.

    } {(count == 2) &&

    - The Timeframe pane + The Timeframe pane allows you to chose the timespan you'd like to see trade data from. Individuals' suspicion score will be calculated based on the trades that occured during the timeframe you select.

    @@ -54,7 +54,7 @@ function Modal() {

    } {count == 3 &&

    - The Trader Graph + The Trader Graph shows how traders are related. Click on a name in the graph to see more information about that individual.

    } diff --git a/react-frontend/src/components/landing.html b/react-frontend/src/components/landing.html deleted file mode 100644 index 8b33b5c..0000000 --- a/react-frontend/src/components/landing.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - WatchDogLanding - - -

    Hello welcome to watchdog

    - - diff --git a/react-frontend/src/css/Landing.css b/react-frontend/src/css/Landing.css new file mode 100644 index 0000000..5a39bfe --- /dev/null +++ b/react-frontend/src/css/Landing.css @@ -0,0 +1,202 @@ +.nav-bar{ + position: fixed; + top: 0px; + left: 0px; + width: 100vw; + height: 70px; + background-color: rgb(7, 7, 44); + z-index: 100; +} + +.topnav { + background-color: rgb(7, 7, 44); + overflow: hidden; + margin-right: 30px; +} + +.topnav a { + float: right; + color: #f2f2f2; + text-align: center; + padding: 14px 16px; + text-decoration: none; + font-size: 17px; + height: 30px; + padding-top: 25px; +} + +.topnav a:hover { + background-color: rgb(17, 11, 99); + color: white; +} + +.topnav a.active { + background-color: #4CAF50; + color: white; +} + +body { + background-color: #f3f3f3; + font-family:Verdana, Geneva, Tahoma, sans-serif; + overflow-y: scroll; + overflow-x: hidden; + position: relative; + left: 0px; + +} +main { + margin-top: 65px; + display: flex; + flex-direction: column; + position: relative; + left: 0px; +} + +.intro { + height: 120vh; + width: 100vw; + background-color: rgb(3, 2, 24); + color: white; + +} + +.app-preview { + height: 90vh; + width: 100vw; + background-color: #b7ffb9; + color: white; +} + +section { + width: 100vw; + overflow: hidden; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; +} + +#app-intro{ + padding-top: 160px; +} + +.s-i { + width: 100%; + max-width: 1600px; + display: flex; + flex-direction: row; + justify-content: space-evenly; + padding-top: 0px; +} + +.s-i-p { + display: flex; + flex-direction: column; + justify-content: center; +} + +.s-i-p-heading{ + font-size: 45px; + margin: 10px 0 0 0; + text-align: center; + font-weight: bold; +} + +.s-i-p-text{ + color: rgba(0,0,0, 0.6); + font-size: 18px; + display: flex; + justify-content: center; + align-items: center; + text-align: center; + max-width: 700px; + margin: 10px 0 20px 0; +} + +.s2-i-s { + padding-top: 0px; + width: 80%; + max-width: 1600px; + min-height: 500px; + align-items: center; +} + +#team { + width: 100vw; + padding: 50px 0 200px 0; + justify-content: flex-start; + background-color: #cccccc; +} + +#s-i-p-heading-team{ + margin-bottom: 0px; +} + +#s-i-p-heading-text { + color: rgba(0,0,0, 1); + font-size: 18px; + display: flex; + justify-content: center; + align-items: center; + text-align: center; + width: 100%; + margin: 0; +} + +#s3-i-t-p { + flex-direction: column; + max-width: 1000px; + max-height: 500px; + height: 500px; +} + +#s-i-p-team-c{ + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + width: 100%; +} + +.s-i-p-team-person-c{ + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + margin-top: 50px; +} + +.s-i-p-team-person{ + border-radius: 100px; + overflow: hidden; + margin: 20px; + height: 200px; + width: 200px; + box-shadow: 0 0 2px 2px rgba(0,0,0,0.15); +} + +.s-i-p-team-text{ + color: rgba(0,0,0, 1); + font-size: 18px; + display: flex; + justify-content: center; + align-items: center; + text-align: center; + max-width: 700px; + margin: 0; +} + +#footer { + width: 100vw; + background: rgb(7, 7, 44); + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + } + +.footer-item{ + color: white; + font-size: 20px; +} + diff --git a/react-frontend/src/css/Modal.css b/react-frontend/src/css/Modal.css index 7ee5045..96f9066 100644 --- a/react-frontend/src/css/Modal.css +++ b/react-frontend/src/css/Modal.css @@ -70,7 +70,7 @@ width: 150px; } -span { +.span { font-weight: bold; color:rgba(10, 9, 71); } -- cgit v1.2.3-70-g09d2 From 860ba5b0e34ecdd27d2ec081191ab5bf9b32524b Mon Sep 17 00:00:00 2001 From: 9308233900 Date: Sat, 17 Apr 2021 16:41:56 -0700 Subject: landing page nav bar done --- landing.html | 18 ++++++---- react-frontend/src/App.js | 4 ++- react-frontend/src/components/TimeSelector.js | 2 +- react-frontend/src/components/images/logo.png | Bin 0 -> 43282 bytes react-frontend/src/components/images/mainlogo.png | Bin 0 -> 269065 bytes react-frontend/src/css/App.css | 13 ++++++-- react-frontend/src/css/Landing.css | 39 ++++++++++++++++++++-- react-frontend/src/images/previewwatchdog.png | Bin 0 -> 321433 bytes 8 files changed, 63 insertions(+), 13 deletions(-) create mode 100644 react-frontend/src/components/images/logo.png create mode 100644 react-frontend/src/components/images/mainlogo.png create mode 100644 react-frontend/src/images/previewwatchdog.png (limited to 'react-frontend/src/components') diff --git a/landing.html b/landing.html index c87d582..47ca60e 100644 --- a/landing.html +++ b/landing.html @@ -8,19 +8,23 @@ +
    -
    Hello welcome to watchdog - +
    + logo +
    -
    pic preview
    +
    + + preview +

    Our App

    diff --git a/react-frontend/src/App.js b/react-frontend/src/App.js index fd7d648..34632eb 100644 --- a/react-frontend/src/App.js +++ b/react-frontend/src/App.js @@ -5,6 +5,7 @@ import Visualization from './components/Visualization.js'; import HubList from './components/HubList.js'; import Loading from './components/Loading.js'; import Modal from './components/Modal.js'; +import logo from './components/images/logo.png'; // CSS import import './css/App.css'; @@ -64,7 +65,8 @@ function App() { {(!hasLoaded) ? :
    PHP -
    Welcome to WatchDogs!
    +
    +
    diff --git a/react-frontend/src/components/TimeSelector.js b/react-frontend/src/components/TimeSelector.js index 6960807..652a9ec 100644 --- a/react-frontend/src/components/TimeSelector.js +++ b/react-frontend/src/components/TimeSelector.js @@ -34,7 +34,7 @@ function TimeSelector(props) {
    -

    Adjust Timeframe :)

    +

    Adjust Timeframe

    diff --git a/react-frontend/src/components/images/logo.png b/react-frontend/src/components/images/logo.png new file mode 100644 index 0000000..7e4e9ee Binary files /dev/null and b/react-frontend/src/components/images/logo.png differ diff --git a/react-frontend/src/components/images/mainlogo.png b/react-frontend/src/components/images/mainlogo.png new file mode 100644 index 0000000..a26df0f Binary files /dev/null and b/react-frontend/src/components/images/mainlogo.png differ diff --git a/react-frontend/src/css/App.css b/react-frontend/src/css/App.css index 90e9046..f632a7f 100644 --- a/react-frontend/src/css/App.css +++ b/react-frontend/src/css/App.css @@ -49,9 +49,14 @@ font-size: calc(10px + 2vmin); color: white; z-index: 10; - background-color: #333333; - border-radius: 5px; margin: 5px; + +} + +#in-app-logo-holder { + border: 7px solid rgb(7, 94, 12); + border-radius: 5px; + background-color: white; } .App-link { @@ -73,4 +78,8 @@ top: 50%; left: 50%; transform: translate(-50%, -50%); +} + +#in-app-logo { + width: 200px; } \ No newline at end of file diff --git a/react-frontend/src/css/Landing.css b/react-frontend/src/css/Landing.css index e6841f8..0a5a845 100644 --- a/react-frontend/src/css/Landing.css +++ b/react-frontend/src/css/Landing.css @@ -1,3 +1,7 @@ +html { + scroll-behavior: smooth; + } + .nav-bar{ position: fixed; top: 0px; @@ -43,6 +47,7 @@ body { display: flex; flex-direction: column; width: 80vw; + scroll-behavior: smooth slow; } main { margin-top: 65px; @@ -51,7 +56,7 @@ main { } .intro { - height: 1000px; + height: 900px; width: 100vw; background-color: rgb(3, 2, 24); color: white; @@ -59,8 +64,27 @@ main { left: -10px; } +#enter-watchdogs { + background-color: rgb(206, 206, 206); + color: rgba(10, 9, 71); + border: 2px solid rgb(255, 255, 255); + border-radius: 5px; + padding: 5px 10px; + text-align: center; + text-decoration: none; + display: inline-block; + font-size: 16px; + height: 70px; + width: 200px; + font-weight: bold; + font-family:sans-serif; +} +#enter-watchdogs:hover { + background-color: #94ff73; + } + .app-preview { - height: 1000px; + height: 900px; width: 100vw; background-color: #b7ffb9; color: white; @@ -70,6 +94,17 @@ main { left: -10px; } +#preview { + width: 70vw; + border: 10px solid rgb(255, 255, 255); + border-radius: 5px; +} + +#preview-text { + color:#868686; + font-size: small; +} + section { width: 100vw; overflow: hidden; diff --git a/react-frontend/src/images/previewwatchdog.png b/react-frontend/src/images/previewwatchdog.png new file mode 100644 index 0000000..56669d8 Binary files /dev/null and b/react-frontend/src/images/previewwatchdog.png differ -- cgit v1.2.3-70-g09d2 From e00c435a929afeac1965e04b8f6585696a915e77 Mon Sep 17 00:00:00 2001 From: Michael Foiani Date: Sun, 18 Apr 2021 00:53:51 -0400 Subject: Working build that scales with the large database. We need to figure out the profit calculation on the large scale, though. --- react-frontend/src/App.js | 5 +++++ react-frontend/src/components/Visualization.js | 15 ++++++++------- 2 files changed, 13 insertions(+), 7 deletions(-) (limited to 'react-frontend/src/components') diff --git a/react-frontend/src/App.js b/react-frontend/src/App.js index 34632eb..c9451a9 100644 --- a/react-frontend/src/App.js +++ b/react-frontend/src/App.js @@ -31,6 +31,10 @@ function App() { const toEpochMilli = date => Date.parse(date); const getGraphData = () => { + console.log({ + start: toEpochMilli(dates.start), + end: toEpochMilli(dates.end) + }); fetch("http://localhost:4567/data", { method: "POST", body: JSON.stringify({ @@ -46,6 +50,7 @@ function App() { .then(data => { setData(data.holders); setHasLoaded(true); + console.log(data.holders); }) .catch(err => console.log(err)); diff --git a/react-frontend/src/components/Visualization.js b/react-frontend/src/components/Visualization.js index 91082e9..2016129 100644 --- a/react-frontend/src/components/Visualization.js +++ b/react-frontend/src/components/Visualization.js @@ -15,8 +15,7 @@ function Visualization(props) { const options = { edges: { color: "#ffffff" - }, - autoResize: true + } }; const events = { select: () => event => props.setSelected(event.nodes[0]) @@ -29,11 +28,13 @@ function Visualization(props) { const getNodes = () => { let nodes = []; props.data.forEach(hub => { - nodes.push({ - id: hub.id, - label: hub.name, - size: hub.suspicionScore * 10 - }); + if (hub.followers) { + nodes.push({ + id: hub.id, + label: hub.name, + size: hub.suspicionScore * 10 + }); + } }); return nodes; } -- cgit v1.2.3-70-g09d2 From 4cfdb31be3697565e5c4ae95cdc4b60161bd4e84 Mon Sep 17 00:00:00 2001 From: Michael Foiani Date: Sun, 18 Apr 2021 01:31:20 -0400 Subject: Have a good working canvas now by limiting the results shown. --- react-frontend/src/App.js | 8 +++++--- react-frontend/src/components/HubList.js | 4 ++-- react-frontend/src/components/Visualization.js | 2 +- .../edu/brown/cs/student/term/DatabaseQuerier.java | 24 +++++++++++++++++----- 4 files changed, 27 insertions(+), 11 deletions(-) (limited to 'react-frontend/src/components') diff --git a/react-frontend/src/App.js b/react-frontend/src/App.js index c9451a9..0a6e6c1 100644 --- a/react-frontend/src/App.js +++ b/react-frontend/src/App.js @@ -48,9 +48,11 @@ function App() { }) .then(res => res.json()) .then(data => { - setData(data.holders); + //TODO: optimize this + const sliced = data.holders.slice(0, 500); + console.log(sliced); + setData(sliced); setHasLoaded(true); - console.log(data.holders); }) .catch(err => console.log(err)); @@ -59,7 +61,7 @@ function App() { // Hooks to update data on init and switching of data - useEffect(() => getGraphData(), []); + //useEffect(() => getGraphData(), []); useEffect(() => { setIsChanging(true); getGraphData(); diff --git a/react-frontend/src/components/HubList.js b/react-frontend/src/components/HubList.js index 5736e89..0df3020 100644 --- a/react-frontend/src/components/HubList.js +++ b/react-frontend/src/components/HubList.js @@ -22,8 +22,8 @@ function HubList(props) { const updateHubItems = () => { // sort and create the elemnts let hubs = []; - const sorted = props.data.sort((a, b) => b.suspicionScore - a.suspicionScore); - sorted.forEach(hub => hubs.push( + //const sorted = props.data.sort((a, b) => b.suspicionScore - a.suspicionScore); + props.data.forEach(hub => hubs.push( )); diff --git a/react-frontend/src/components/Visualization.js b/react-frontend/src/components/Visualization.js index 2016129..1975e86 100644 --- a/react-frontend/src/components/Visualization.js +++ b/react-frontend/src/components/Visualization.js @@ -32,7 +32,7 @@ function Visualization(props) { nodes.push({ id: hub.id, label: hub.name, - size: hub.suspicionScore * 10 + size: hub.suspicionScore }); } }); diff --git a/src/main/java/edu/brown/cs/student/term/DatabaseQuerier.java b/src/main/java/edu/brown/cs/student/term/DatabaseQuerier.java index 4ff02f9..53c8cdc 100644 --- a/src/main/java/edu/brown/cs/student/term/DatabaseQuerier.java +++ b/src/main/java/edu/brown/cs/student/term/DatabaseQuerier.java @@ -53,8 +53,8 @@ public class DatabaseQuerier { ResultSet rs = prep.executeQuery(); while (rs.next()) { - String ticker = rs.getString(1); - if (isValidTicker(ticker)) { + String ticker = validateTicker(rs.getString(1)); + if (!ticker.equals("")) { stocks.add(ticker); } } @@ -97,9 +97,10 @@ public class DatabaseQuerier { public List getTradeByStock(String stock, int isBuy, Instant startDate, Instant endDate) throws SQLException { List trades = new ArrayList<>(); + /* if (isValidStock(stock)) { return trades; - } + }*/ PreparedStatement prep = conn.prepareStatement( "SELECT * FROM trades WHERE (stock_name = ? AND is_buy = ?) " @@ -140,14 +141,14 @@ public class DatabaseQuerier { while (rs.next()) { String ticker = rs.getString("stock_name"); - if (isValidTicker(ticker)) { + //if (isValidTicker(ticker)) { trades.addFirst(new Trade(rs.getInt("trade_id"), ticker, rs.getDouble("trade_timestamp"), rs.getInt("is_buy"), rs.getInt("number_of_shares"), new Holder(rs.getInt("holder_id"), rs.getString("holder_name")), rs.getDouble("share_price"))); - } + //} } prep.close(); } catch (SQLException e) { @@ -155,4 +156,17 @@ public class DatabaseQuerier { } return trades; } + + private String validateTicker(String ticker) { + //this is cleaning some improperly formatted tickers + ticker = ticker.replaceAll("[^a-zA-Z0-9]", "").toUpperCase(); + if(ticker.contains("[0-9]") || + ticker.length() > 5 || + ticker.length() < 2 || + ticker.contains("NONE")) { + return ""; + } + + return ticker; + } } -- cgit v1.2.3-70-g09d2 From f0866fc8c35b2124d1690ff83fc6a55c3e720eda Mon Sep 17 00:00:00 2001 From: 9308233900 Date: Sun, 18 Apr 2021 15:23:36 -0700 Subject: landing page rough draft completed --- react-frontend/src/App.js | 226 +++++++++------ react-frontend/src/components/WatchDogs.js | 89 ++++++ react-frontend/src/components/images/mainlogo.png | Bin 269065 -> 0 bytes react-frontend/src/css/App.css | 1 + react-frontend/src/css/Landing.css | 322 +++++++++++----------- react-frontend/src/images/mainlogo.png | Bin 0 -> 269065 bytes 6 files changed, 406 insertions(+), 232 deletions(-) create mode 100644 react-frontend/src/components/WatchDogs.js delete mode 100644 react-frontend/src/components/images/mainlogo.png create mode 100644 react-frontend/src/images/mainlogo.png (limited to 'react-frontend/src/components') diff --git a/react-frontend/src/App.js b/react-frontend/src/App.js index 0a6e6c1..a639edd 100644 --- a/react-frontend/src/App.js +++ b/react-frontend/src/App.js @@ -1,89 +1,161 @@ // React/component imports import React, {useEffect, useState} from 'react'; -import TimeSelector from './components/TimeSelector.js'; -import Visualization from './components/Visualization.js'; -import HubList from './components/HubList.js'; -import Loading from './components/Loading.js'; -import Modal from './components/Modal.js'; -import logo from './components/images/logo.png'; - -// CSS import -import './css/App.css'; - -/** - * Main component of the app. Holds the main layout of the big components. - * @returns {import('react').HtmlHTMLAttributes} A div of the body of the page. - */ +import WatchDogs from './components/WatchDogs.js'; +import reagan from './images/reagan.png'; +import previewwatchdog from './images/previewwatchdog.png'; +import mainlogo from './images/mainlogo.png'; + + +import './css/Landing.css'; + function App() { - // State to open app when loaded - const [hasLoaded, setHasLoaded] = useState(false); - // State indicate if canvas is redrawing - const [isChanging, setIsChanging] = useState(false); - // State to hold dates -> two weeks apart on initialization. - const [dates, setDates] = useState({ - start: new Date(Date.now() - 12096e5), - end: new Date() - }); - // State for visualization data - const [data, setData] = useState([]); - // State for selected person - const [selected, setSelected] = useState(-1); - - const toEpochMilli = date => Date.parse(date); - const getGraphData = () => { - console.log({ - start: toEpochMilli(dates.start), - end: toEpochMilli(dates.end) - }); - fetch("http://localhost:4567/data", { - method: "POST", - body: JSON.stringify({ - start: toEpochMilli(dates.start), - end: toEpochMilli(dates.end) - }), - headers: { - "Content-Type": "application/json", - }, - credentials: "same-origin" - }) - .then(res => res.json()) - .then(data => { - //TODO: optimize this - const sliced = data.holders.slice(0, 500); - console.log(sliced); - setData(sliced); - setHasLoaded(true); - }) - .catch(err => console.log(err)); - - setIsChanging(false); - } - - - // Hooks to update data on init and switching of data - //useEffect(() => getGraphData(), []); - useEffect(() => { - setIsChanging(true); - getGraphData(); - }, [dates]); + const [startApp, setStartApp] = useState(false); + + const startModal = () => { + document.getElementById("main-modal").style.display = 'block'; + setStartApp(false); + } + const exitModal = () => { + document.getElementById("main-modal").style.display = 'none'; + setStartApp(true); + } + return ( <> - {(!hasLoaded) ? : -
    - PHP -
    -
    -
    -
    -
    - - - + + {(!startApp) ? +
    + + +
    + +
    + logo + +
    + +
    + + preview +
    + +
    +

    About Our App

    +

    +

    WatchDogs utilizes a simple, + interactive interface to provide you with the latest + data relating to high-profile investors’ trades. Directly from + the SEC, WatchDogs relays information regarding “inside” investors + and their recent trades, as well as provides computed values such + as an individual’s net profit from a stock at time of trade and a + ranking of individuals most likely recently involved in insider trading. + The computed “suspicion ranks” are determined using multiple factors + (including recent trade profitability and investor connectedness) + and a complex algorithm. For added convenience, YOU choose the + timeframe WatchDogs considers when analyzing trade data. WatchDogs + makes insider trade data accessible to the public, and provides + low-level intuition regarding which investors are more and less + likely to be committing unlawful insider trading.

    +
    It is important to remember that suspicion + ranks returned by WatchDogs’ algorithm DO NOT prove--or even suggest--that + an individual has engaged in insider trading. WatchDogs suspicion + ranks should not be interpreted as indication of an individual’s + participation in illegal activity. WatchDogs data, including suspicion ranks, + cannot be used as evidence in legal proceedings. Please use WatchDogs + as it is intended, and use discretion when interpreting algorithmic + results.
    +

    +

    The Data

    +
    WatchDogs uses data retrieved from SEC.gov’s + EDGAR API. Trades analyzed by WatchDogs are of the type Form 4, + meaning the filing individual is an “insider” (e.g. the CEO) at + the company whose stock they are trading. In-app data relating + to investors, trades, and profitability is accessible to the public via + the SEC, and only public data is input to the SuspicionRank algorithm.
    +

    +

    Our Algorithm

    +
    WatchDogs suspicion rank represents the likelihood + of an individual being involved in insider trading. The SuspicionRank algorithm, + a derivative of Lary Page’s PageRank algorithm, considers “insiders” who similarly + trade stocks (within a given timeframe) as “linked”, while simultaneously + considering involved individuals’ net profit on their stocks at the time + of trade. (Obviously, an “inside” investor who makes a counter-productive + trade is not likely to be insider trading.)
    +

    +
    + +
    +
    +
    +

    Meet the Team

    +
    +
    +
    + +
    +

    Clark Oh-Willeke

    +
    + +
    +
    + +
    +

    Julia McCauley

    +
    + +
    +
    + +
    +

    Michael Foiani

    +
    + +
    +
    + +
    +

    Reagan Hunt

    +
    +
    +
    +
    +
    +
    + +
    +

    + +

    + +

    +
    + + : + } + ); } -export default App; + + + + + +export default App; \ No newline at end of file diff --git a/react-frontend/src/components/WatchDogs.js b/react-frontend/src/components/WatchDogs.js new file mode 100644 index 0000000..d631ea9 --- /dev/null +++ b/react-frontend/src/components/WatchDogs.js @@ -0,0 +1,89 @@ +// React/component imports +import React, {useEffect, useState} from 'react'; +import TimeSelector from './TimeSelector.js'; +import Visualization from './Visualization.js'; +import HubList from './HubList.js'; +import Loading from './Loading.js'; +import Modal from './Modal.js'; +import logo from './images/logo.png'; + +// CSS import +import '../css/App.css'; + +/** + * Main component of the app. Holds the main layout of the big components. + * @returns {import('react').HtmlHTMLAttributes} A div of the body of the page. + */ +function WatchDogs() { + // State to open app when loaded + const [hasLoaded, setHasLoaded] = useState(false); + // State indicate if canvas is redrawing + const [isChanging, setIsChanging] = useState(false); + // State to hold dates -> two weeks apart on initialization. + const [dates, setDates] = useState({ + start: new Date(Date.now() - 12096e5), + end: new Date() + }); + // State for visualization data + const [data, setData] = useState([]); + // State for selected person + const [selected, setSelected] = useState(-1); + + const toEpochMilli = date => Date.parse(date); + const getGraphData = () => { + console.log({ + start: toEpochMilli(dates.start), + end: toEpochMilli(dates.end) + }); + fetch("http://localhost:4567/data", { + method: "POST", + body: JSON.stringify({ + start: toEpochMilli(dates.start), + end: toEpochMilli(dates.end) + }), + headers: { + "Content-Type": "application/json", + }, + credentials: "same-origin" + }) + .then(res => res.json()) + .then(data => { + //TODO: optimize this + const sliced = data.holders.slice(0, 500); + console.log(sliced); + setData(sliced); + setHasLoaded(true); + }) + .catch(err => console.log(err)); + + setIsChanging(false); + } + + + // Hooks to update data on init and switching of data + //useEffect(() => getGraphData(), []); + useEffect(() => { + setIsChanging(true); + getGraphData(); + }, [dates]); + + return ( + <> + {(!hasLoaded) ? : +
    + PHP +
    +
    +
    +
    +
    + + + +
    + } + + ); +} + +export default WatchDogs; diff --git a/react-frontend/src/components/images/mainlogo.png b/react-frontend/src/components/images/mainlogo.png deleted file mode 100644 index a26df0f..0000000 Binary files a/react-frontend/src/components/images/mainlogo.png and /dev/null differ diff --git a/react-frontend/src/css/App.css b/react-frontend/src/css/App.css index f632a7f..e39eb3e 100644 --- a/react-frontend/src/css/App.css +++ b/react-frontend/src/css/App.css @@ -6,6 +6,7 @@ grid-template-rows: max-content auto max-content; grid-template-columns: max-content auto max-content max-content; background-color: #121212; + } .App-logo { diff --git a/react-frontend/src/css/Landing.css b/react-frontend/src/css/Landing.css index c2bc567..58658b0 100644 --- a/react-frontend/src/css/Landing.css +++ b/react-frontend/src/css/Landing.css @@ -1,244 +1,256 @@ html { - scroll-behavior: smooth; - } + scroll-behavior: smooth; + z-index: 1000; + +} .nav-bar{ - position: fixed; - top: 0px; - left: 0px; - width: 100vw; - height: 70px; - background-color: rgb(7, 7, 44); - z-index: 100; + position: fixed; + top: 0px; + left: 0px; + width: 100vw; + height: 70px; + background-color: rgb(7, 7, 44); + z-index: 100; } .topnav { - background-color: rgb(7, 7, 44); - overflow: hidden; - margin-right: 30px; + background-color: rgb(7, 7, 44); + overflow: hidden; + margin-right: 30px; } .topnav a { - float: right; - color: #f2f2f2; - text-align: center; - padding: 14px 16px; - text-decoration: none; - font-size: 17px; - height: 30px; - padding-top: 25px; + float: right; + color: #f2f2f2; + text-align: center; + padding: 14px 16px; + text-decoration: none; + font-size: 17px; + height: 30px; + padding-top: 25px; } .topnav a:hover { - background-color: rgb(17, 11, 99); - color: white; + background-color: rgb(17, 11, 99); + color: white; } .topnav a.active { - background-color: #4CAF50; - color: white; + background-color: #4CAF50; + color: white; } -body { - background-color: #f3f3f3; - font-family:Verdana, Geneva, Tahoma, sans-serif; - overflow-y: scroll; - overflow-x: hidden; - display: flex; - flex-direction: column; - width: 80vw; - scroll-behavior: smooth slow; +.body { + background-color: #f3f3f3; + font-family:Verdana, Geneva, Tahoma, sans-serif; + overflow-y: scroll; + overflow-x: hidden; + display: flex; + flex-direction: column; + width: 100vw; + scroll-behavior: smooth slow; + z-index: 100; } main { - margin-top: 65px; - display: flex; - flex-direction: column; + margin-top: 65px; + display: flex; + flex-direction: column; } .intro { - height: 900px; - width: 100vw; - background-color: rgb(3, 2, 24); - color: white; - position: relative; - left: -10px; + height: 900px; + width: 100vw; + background-color: rgb(3, 2, 24); + color: white; + position: relative; + left: -10px; } #enter-watchdogs { - background-color: rgb(206, 206, 206); - color: rgba(10, 9, 71); - border: 2px solid rgb(255, 255, 255); - border-radius: 5px; - padding: 5px 10px; - text-align: center; - text-decoration: none; - display: inline-block; - font-size: 16px; - height: 70px; - width: 200px; - font-weight: bold; - font-family:sans-serif; + background-color: rgb(206, 206, 206); + color: rgba(10, 9, 71); + border: 2px solid rgb(255, 255, 255); + border-radius: 5px; + padding: 5px 10px; + text-align: center; + text-decoration: none; + display: inline-block; + font-size: 16px; + height: 70px; + width: 200px; + font-weight: bold; + font-family:sans-serif; } #enter-watchdogs:hover { - background-color: #94ff73; - } + background-color: #94ff73; +} .app-preview { - height: 900px; - width: 100vw; - background-color: #b7ffb9; - color: white; - position: relative; - left: 0px; - position: relative; - left: -10px; + height: 900px; + width: 100vw; + background-color: #b7ffb9; + color: white; + position: relative; + left: 0px; + position: relative; + left: -10px; } #preview { - width: 70vw; - border: 10px solid rgb(255, 255, 255); - border-radius: 5px; + width: 70vw; + border: 10px solid rgb(255, 255, 255); + border-radius: 5px; } #preview-text { - color:#868686; - font-size: small; + color:#868686; + font-size: small; } section { - width: 100vw; - overflow: hidden; - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; +width: 100vw; +overflow: hidden; +display: flex; +flex-direction: column; +justify-content: center; +align-items: center; } #app-intro{ - padding-top: 160px; - height: fit-content; - width: 100vw; +padding-top: 160px; +height: fit-content; +width: 100vw; } .team { - width: 100%; - max-width: 1600px; - display: flex; - flex-direction: row; - justify-content: space-evenly; - padding-top: 0px; - width: 80%; - min-height: 500px; - align-items: center; +width: 100%; +max-width: 1600px; +display: flex; +flex-direction: row; +justify-content: space-evenly; +padding-top: 0px; +width: 80%; +min-height: 500px; +align-items: center; } .center { - display: flex; - flex-direction: column; - justify-content: center; +display: flex; +flex-direction: column; +justify-content: center; } .heading{ - font-size: 45px; - margin: 10px 0 0 0; - text-align: center; - font-weight: bold; +font-size: 45px; +margin: 10px 0 0 0; +text-align: center; +font-weight: bold; } .text{ - color: rgba(0,0,0, 0.6); - font-size: 18px; - display: flex; - justify-content: center; - align-items: center; - text-align: center; - max-width: 700px; - margin: 10px 0 20px 0; +color: rgba(0,0,0, 0.6); +font-size: 18px; +display: flex; +justify-content: center; +align-items: center; +text-align: center; +max-width: 70vw; +margin: 10px 0 20px 0; } #team { - width: 100vw; - padding: 50px 0 200px 0; - justify-content: flex-start; - background-color: #cccccc; - position: relative; - left: -10px; +width: 100vw; +padding: 50px 0 200px 0; +justify-content: flex-start; +background-color: #cccccc; +position: relative; +left: -10px; } #team-heading{ - margin-bottom: 0px; +margin-bottom: 0px; } #team-holder { - flex-direction: column; - max-width: 1000px; - max-height: 500px; - height: 500px; +flex-direction: column; +max-width: 1000px; +max-height: 500px; +height: 500px; } #people-holder{ - display: flex; - flex-direction: row; - justify-content: center; - align-items: center; - width: 100%; +display: flex; +flex-direction: row; +justify-content: center; +align-items: center; +width: 100%; } .team-person-holder{ - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - margin-top: 50px; +display: flex; +flex-direction: column; +justify-content: center; +align-items: center; +margin-top: 50px; } .team-person{ - border-radius: 100px; - overflow: hidden; - margin: 20px; - height: 200px; - width: 200px; - box-shadow: 0 0 2px 2px rgba(0,0,0,0.15); +border-radius: 100px; +overflow: hidden; +margin: 20px; +height: 200px; +width: 200px; +box-shadow: 0 0 2px 2px rgba(0,0,0,0.15); } .team-text{ - color: rgba(0,0,0, 1); - font-size: 18px; +color: rgba(0,0,0, 1); +font-size: 18px; +display: flex; +justify-content: center; +align-items: center; +text-align: center; +max-width: 700px; +margin: 0; +} + +#footer { + width: 100vw; + background: rgb(7, 7, 44); display: flex; + flex-direction: column; justify-content: center; align-items: center; - text-align: center; - max-width: 700px; - margin: 0; + position: relative; + left: -10px; + height: fit-content; + width: 100vw; } -#footer { - width: 100vw; - background: rgb(7, 7, 44); - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - position: relative; - left: -10px; - height: fit-content; - width: 100vw; - } - .footer-item{ - color: white; - font-size: 20px; + color: white; + font-size: 20px; } .footer-subtext{ - color: white; - font-size: 15px; - width: 80vw; + color: white; + font-size: 15px; + width: 80vw; } .appinfotxt { - font-size: 15px; - color:rgb(3, 2, 24); +font-size: 15px; +color:rgb(3, 2, 24); +max-width: 70vw; +} + +.h2 { +font-size: 30px; +color: black; } +#return-to-landing { +z-index: 1000; +} diff --git a/react-frontend/src/images/mainlogo.png b/react-frontend/src/images/mainlogo.png new file mode 100644 index 0000000..a26df0f Binary files /dev/null and b/react-frontend/src/images/mainlogo.png differ -- cgit v1.2.3-70-g09d2 From 0466db8b9051cb6300f274f0bba480d1020c63cf Mon Sep 17 00:00:00 2001 From: Julia McCauley Date: Sun, 18 Apr 2021 23:23:34 -0400 Subject: cleaned up graph visualization, added colors, score based node scaling --- react-frontend/src/components/HubList.js | 2 +- react-frontend/src/components/Visualization.js | 39 +++++++++++++++++++++++-- react-frontend/src/components/images/person.svg | 1 + 3 files changed, 38 insertions(+), 4 deletions(-) create mode 100644 react-frontend/src/components/images/person.svg (limited to 'react-frontend/src/components') diff --git a/react-frontend/src/components/HubList.js b/react-frontend/src/components/HubList.js index 0df3020..c9a5156 100644 --- a/react-frontend/src/components/HubList.js +++ b/react-frontend/src/components/HubList.js @@ -32,7 +32,7 @@ function HubList(props) { const getName = () => { props.data.forEach(hub => { - if (hub.id == props.selected) { + if (hub.id === props.selected) { setName(hub.name); } }) diff --git a/react-frontend/src/components/Visualization.js b/react-frontend/src/components/Visualization.js index 1975e86..0a0c82a 100644 --- a/react-frontend/src/components/Visualization.js +++ b/react-frontend/src/components/Visualization.js @@ -6,6 +6,7 @@ import Graph from 'vis-react'; // CSS imports import '../css/Canvas.css'; + /** * This function renders and mantains thhe canvas. * @param {Object} props The props for the canvas. @@ -29,10 +30,37 @@ function Visualization(props) { let nodes = []; props.data.forEach(hub => { if (hub.followers) { + let colorVal = '#f6f7d4'; + const score = hub.suspicionScore; + + if(score > 0.8){ + colorVal = '#d92027' + } + if(score < 0.8 && score > 0.6){ + colorVal = '#f37121' + } + if(score < 0.6 && score > 0.4){ + colorVal = '#fdca40' + } nodes.push({ id: hub.id, + autoResize: true, label: hub.name, - size: hub.suspicionScore + labelHighlightBold: true, + shape: "dot", + value: hub.suspicionScore*1000, + color: { + background: colorVal, + border: '#2b2e4a', + highlight:{ + background: '#29bb89', + border: '#fdca40' + } + }, + font: { + color: '#9fd8df', + size: 20, + } }); } }); @@ -43,8 +71,13 @@ function Visualization(props) { props.data.forEach(hub => { hub.followers.forEach(follower => { edges.push({ - from: hub.id, - to: follower.id + from: follower.id, + to: hub.id, + dashes: false, + color:{ + opacity: 0.7, + highlight:'#fdca40', + } }); }); }); diff --git a/react-frontend/src/components/images/person.svg b/react-frontend/src/components/images/person.svg new file mode 100644 index 0000000..6a93d8f --- /dev/null +++ b/react-frontend/src/components/images/person.svg @@ -0,0 +1 @@ +Person \ No newline at end of file -- cgit v1.2.3-70-g09d2