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/App.js | 77 +++++++++++++++++++++ react-frontend/src/App.test.js | 8 +++ 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 +++++++++++++++++++ react-frontend/src/css/App.css | 76 +++++++++++++++++++++ react-frontend/src/css/Canvas.css | 7 ++ react-frontend/src/css/CoordSelector.css | 52 ++++++++++++++ react-frontend/src/css/Route.css | 56 +++++++++++++++ react-frontend/src/css/UserCheckin.css | 94 ++++++++++++++++++++++++++ react-frontend/src/index.css | 14 ++++ react-frontend/src/index.js | 17 +++++ react-frontend/src/logo.svg | 1 + react-frontend/src/reportWebVitals.js | 13 ++++ react-frontend/src/setupTests.js | 5 ++ 19 files changed, 726 insertions(+) create mode 100644 react-frontend/src/App.js create mode 100644 react-frontend/src/App.test.js 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 create mode 100644 react-frontend/src/css/App.css create mode 100644 react-frontend/src/css/Canvas.css create mode 100644 react-frontend/src/css/CoordSelector.css create mode 100644 react-frontend/src/css/Route.css create mode 100644 react-frontend/src/css/UserCheckin.css create mode 100644 react-frontend/src/index.css create mode 100644 react-frontend/src/index.js create mode 100644 react-frontend/src/logo.svg create mode 100644 react-frontend/src/reportWebVitals.js create mode 100644 react-frontend/src/setupTests.js (limited to 'react-frontend/src') diff --git a/react-frontend/src/App.js b/react-frontend/src/App.js new file mode 100644 index 0000000..2eb0c81 --- /dev/null +++ b/react-frontend/src/App.js @@ -0,0 +1,77 @@ +// 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'; + +// 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 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 = () => { + 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 => { + setData(data.holders); + 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) ? : +
+
Welcome to WatchDogs!
+
+
+
+ + + +
+ } + + ); +} + +export default App; diff --git a/react-frontend/src/App.test.js b/react-frontend/src/App.test.js new file mode 100644 index 0000000..1f03afe --- /dev/null +++ b/react-frontend/src/App.test.js @@ -0,0 +1,8 @@ +import { render, screen } from '@testing-library/react'; +import App from './App'; + +test('renders learn react link', () => { + render(); + const linkElement = screen.getByText(/learn react/i); + expect(linkElement).toBeInTheDocument(); +}); 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; + diff --git a/react-frontend/src/css/App.css b/react-frontend/src/css/App.css new file mode 100644 index 0000000..90e9046 --- /dev/null +++ b/react-frontend/src/css/App.css @@ -0,0 +1,76 @@ +.App { + display: grid; + grid-template-areas: "head canvasFill2 canvasFill3 checkin" + "canvasFill1 canvasFill2 canvasFill3 checkin" + "route canvasFill2 canvasFill3 checkin"; + grid-template-rows: max-content auto max-content; + grid-template-columns: max-content auto max-content max-content; + background-color: #121212; +} + +.App-logo { + height: 40vmin; + pointer-events: none; +} + + +.Canvas-filler { + width: 100%; + height: 100%; + + z-index: 1; +} + +.Canvas-filler-1 { + grid-area: canvasFill1; +} +.Canvas-filler-2 { + grid-area: canvasFill2; +} +.Canvas-filler-3 { + grid-area: canvasFill3; +} + +@media (prefers-reduced-motion: no-preference) { + .App-logo { + animation: App-logo-spin infinite 20s linear; + } +} + +.App-header { + grid-area: head; + min-height: 7vh; + width: max-content; + display: flex; + padding: 0 20px; + flex-direction: column; + align-items: center; + justify-content: center; + font-size: calc(10px + 2vmin); + color: white; + z-index: 10; + background-color: #333333; + border-radius: 5px; + margin: 5px; +} + +.App-link { + color: #61dafb; +} + +@keyframes App-logo-spin { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +} + +.Loading { + z-index: 100; + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); +} \ No newline at end of file diff --git a/react-frontend/src/css/Canvas.css b/react-frontend/src/css/Canvas.css new file mode 100644 index 0000000..e67d87d --- /dev/null +++ b/react-frontend/src/css/Canvas.css @@ -0,0 +1,7 @@ +.Map-canvas { + /*touch-action: none; */ + position: absolute; + z-index: 5; + width: 100vw; + height: 100vh; +} \ No newline at end of file diff --git a/react-frontend/src/css/CoordSelector.css b/react-frontend/src/css/CoordSelector.css new file mode 100644 index 0000000..881be08 --- /dev/null +++ b/react-frontend/src/css/CoordSelector.css @@ -0,0 +1,52 @@ +/* CSS adapted from w3school buttons */ +.Btn-select-left > p, .Btn-select-right > p { + padding: 0; + margin: 0; +} + +.Btn-select-left { + background-color: #424242; + border: 4px solid pink; +} + +.Btn-select-left:hover { + box-shadow: 3px 3px #888888; + color: black; + background-color: pink; +} + +.Btn-select-right { + background-color: #424242; + border: 4px solid lightblue; +} + +.Btn-select-right:hover { + box-shadow: 3px 3px #888888; + color: black; + background-color: lightblue; +} + +.Btn:disabled, +.Btn[disabled]{ + border: 1px solid #999999; + background-color: #cccccc; + color: #666666; + box-shadow: none; + cursor: default; +} + +/* +.Btn:disabled:hover, +.Btn[disabled]:hover{ +} +*/ + +.Textbox { + width: 100px; +} + +.Number-input { + width: 90%; +} + + diff --git a/react-frontend/src/css/Route.css b/react-frontend/src/css/Route.css new file mode 100644 index 0000000..efc4868 --- /dev/null +++ b/react-frontend/src/css/Route.css @@ -0,0 +1,56 @@ +.Route { + grid-area: route; + z-index: 10; + color: white; + border-radius: 10px; + background-color: #121212; + /*cursor: default;*/ + /* Transparent background */ + background: rgba(0, 0, 0, 0); +} + +.Coord-selectors-flex { + display: flex; + gap: 20px; + padding: 8px; + margin: 0; + align-content: flex-end; + background-color: #333333; + margin: 5px; + border-radius: 3px; +} + +/* CSS adapted from w3school buttons */ +.Btn { + color: white; + padding: 16px 32px; + text-align: center; + text-decoration: none; + display: inline-block; + font-size: 16px; + margin: 4px 2px; + transition-duration: 0.4s; + cursor: pointer; + outline: none; +} + +.Route-btn:hover { + box-shadow: 3px 3px #ccc; + color: black; + background-color: lightgreen; +} + +.Route-btn { + background-color: #424242; + border: 2px solid lightgreen; + box-shadow: .5px .5px 0 2px lightgreen; +} + +.Btn:disabled, +.Btn[disabled]{ + border: 1px solid #999999; + background-color: #cccccc; + color: #666666; + /*cursor: default;*/ + box-shadow: none; +} \ No newline at end of file diff --git a/react-frontend/src/css/UserCheckin.css b/react-frontend/src/css/UserCheckin.css new file mode 100644 index 0000000..141cc01 --- /dev/null +++ b/react-frontend/src/css/UserCheckin.css @@ -0,0 +1,94 @@ +.User-checkin { + grid-area: checkin; + height: 100vh; + background-color: #121212; + z-index: 10; + color: white; + border-radius: 10px; + display: flex; + font-size: 18px; + cursor: default; + /* Transparent background */ + background: rgba(0, 0, 0, 0); +} + +ul { + list-style-type: none; +} + +.User-checkin > div { + z-index: 10; + background-color: #333333; + border-radius: 20px; + margin: 5px; +} + +.Coord-ex { + height: 1vh; + margin: 0; + padding: 0; + text-align: center; +} + +.Chosen-user > h2, .Checkins > h2 { + display: flex; + justify-content: space-evenly; + height: 5vh; + padding: 0 10px; +} + +.Checkin-list { + padding: 0 20px; + height: 86vh; + overflow-y: scroll; + cursor: default; +} + +.User-checkin-list { + height: 80vh; + overflow-y: scroll; + + list-style-position: inside; + padding: 0 20px; + text-align: center; + text-indent: -12px; +} + +.User-checkin-list > li { + margin-bottom: 20px; +} + + +.Checkin { + padding-top: 10px; + border-bottom: 1px solid #e6ecf0; +} + +.Checkin:last-child { + border-bottom: none; +} + +.Img-flex { + margin: 5px 10px 10px 0; + gap: 20px; + display: flex; + justify-content: space-between; + align-items: center; +} + +.Img-btn { + background-color: #424242; + border-radius: 50%; + margin-right: 10px; +} + +.Img-btn:hover { + box-shadow: 3px 3px #333333; + cursor: pointer; +} + +.Clickable-name { + cursor: pointer; + text-decoration: underline; + color: lightgreen; +} \ No newline at end of file diff --git a/react-frontend/src/index.css b/react-frontend/src/index.css new file mode 100644 index 0000000..72f4b2d --- /dev/null +++ b/react-frontend/src/index.css @@ -0,0 +1,14 @@ +body { + margin: 0; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', + 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', + sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + background-color: #121212; +} + +code { + font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', + monospace; +} diff --git a/react-frontend/src/index.js b/react-frontend/src/index.js new file mode 100644 index 0000000..ef2edf8 --- /dev/null +++ b/react-frontend/src/index.js @@ -0,0 +1,17 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import './index.css'; +import App from './App'; +import reportWebVitals from './reportWebVitals'; + +ReactDOM.render( + + + , + document.getElementById('root') +); + +// If you want to start measuring performance in your app, pass a function +// to log results (for example: reportWebVitals(console.log)) +// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals +reportWebVitals(); diff --git a/react-frontend/src/logo.svg b/react-frontend/src/logo.svg new file mode 100644 index 0000000..9dfc1c0 --- /dev/null +++ b/react-frontend/src/logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/react-frontend/src/reportWebVitals.js b/react-frontend/src/reportWebVitals.js new file mode 100644 index 0000000..5253d3a --- /dev/null +++ b/react-frontend/src/reportWebVitals.js @@ -0,0 +1,13 @@ +const reportWebVitals = onPerfEntry => { + if (onPerfEntry && onPerfEntry instanceof Function) { + import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { + getCLS(onPerfEntry); + getFID(onPerfEntry); + getFCP(onPerfEntry); + getLCP(onPerfEntry); + getTTFB(onPerfEntry); + }); + } +}; + +export default reportWebVitals; diff --git a/react-frontend/src/setupTests.js b/react-frontend/src/setupTests.js new file mode 100644 index 0000000..8f2609b --- /dev/null +++ b/react-frontend/src/setupTests.js @@ -0,0 +1,5 @@ +// jest-dom adds custom jest matchers for asserting on DOM nodes. +// allows you to do things like: +// expect(element).toHaveTextContent(/react/i) +// learn more: https://github.com/testing-library/jest-dom +import '@testing-library/jest-dom'; -- 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') 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') 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 cdcf7602c5fd2066f69fdbe64562e2faca915422 Mon Sep 17 00:00:00 2001 From: 9308233900 Date: Sat, 17 Apr 2021 02:37:15 -0700 Subject: some landing page improvements, css cleaned --- landing.html | 55 +++++++++++++--------------- react-frontend/src/css/Landing.css | 69 ++++++++++++++++------------------- react-frontend/src/images/reagan.png | Bin 0 -> 2150995 bytes 3 files changed, 56 insertions(+), 68 deletions(-) create mode 100644 react-frontend/src/images/reagan.png (limited to 'react-frontend/src') diff --git a/landing.html b/landing.html index 80bb9dc..c87d582 100644 --- a/landing.html +++ b/landing.html @@ -7,13 +7,13 @@
    Hello welcome to watchdog @@ -23,50 +23,45 @@
    pic preview
    -

    Our App

    -

    subtitle

    +

    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

    +
    +
    +

    Meet the Team

    -
    -
    -
    +
    +
    +
    -

    Clark

    -

    subtxt

    +

    Clark

    -
    -
    +
    +
    -

    Julia

    -

    subtxt

    +

    Julia

    -
    -
    +
    +
    -

    Michael

    -

    subtxt

    +

    Michael

    -
    -
    - +
    +
    +
    -

    Reagan

    -

    subtxt

    +

    Reagan Hunt

    diff --git a/react-frontend/src/css/Landing.css b/react-frontend/src/css/Landing.css index 5a39bfe..e6841f8 100644 --- a/react-frontend/src/css/Landing.css +++ b/react-frontend/src/css/Landing.css @@ -40,31 +40,34 @@ body { font-family:Verdana, Geneva, Tahoma, sans-serif; overflow-y: scroll; overflow-x: hidden; - position: relative; - left: 0px; - + display: flex; + flex-direction: column; + width: 80vw; } main { margin-top: 65px; display: flex; flex-direction: column; - position: relative; - left: 0px; } .intro { - height: 120vh; + height: 1000px; width: 100vw; background-color: rgb(3, 2, 24); - color: white; - + color: white; + position: relative; + left: -10px; } .app-preview { - height: 90vh; + height: 1000px; width: 100vw; background-color: #b7ffb9; color: white; + position: relative; + left: 0px; + position: relative; + left: -10px; } section { @@ -74,35 +77,39 @@ section { flex-direction: column; justify-content: center; align-items: center; + } #app-intro{ padding-top: 160px; } -.s-i { +.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; } -.s-i-p { +.center { display: flex; flex-direction: column; justify-content: center; } -.s-i-p-heading{ +.heading{ font-size: 45px; margin: 10px 0 0 0; text-align: center; font-weight: bold; } -.s-i-p-text{ +.text{ color: rgba(0,0,0, 0.6); font-size: 18px; display: flex; @@ -113,44 +120,27 @@ section { 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; + position: relative; + left: -10px; } -#s-i-p-heading-team{ +#team-heading{ 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 { +#team-holder { flex-direction: column; max-width: 1000px; max-height: 500px; height: 500px; } -#s-i-p-team-c{ +#people-holder{ display: flex; flex-direction: row; justify-content: center; @@ -158,7 +148,7 @@ section { width: 100%; } -.s-i-p-team-person-c{ +.team-person-holder{ display: flex; flex-direction: column; justify-content: center; @@ -166,7 +156,7 @@ section { margin-top: 50px; } -.s-i-p-team-person{ +.team-person{ border-radius: 100px; overflow: hidden; margin: 20px; @@ -175,7 +165,7 @@ section { box-shadow: 0 0 2px 2px rgba(0,0,0,0.15); } -.s-i-p-team-text{ +.team-text{ color: rgba(0,0,0, 1); font-size: 18px; display: flex; @@ -193,6 +183,8 @@ section { flex-direction: column; justify-content: center; align-items: center; + position: relative; + left: -10px; } .footer-item{ @@ -200,3 +192,4 @@ section { font-size: 20px; } + diff --git a/react-frontend/src/images/reagan.png b/react-frontend/src/images/reagan.png new file mode 100644 index 0000000..15c02f0 Binary files /dev/null and b/react-frontend/src/images/reagan.png differ -- 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') 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 0eff49053d862dfbc0fa1d1ed6587517b0526e04 Mon Sep 17 00:00:00 2001 From: 9308233900 Date: Sat, 17 Apr 2021 18:18:08 -0700 Subject: landing preview/disclaimer added --- landing.html | 26 +++++++++++++++++++++----- react-frontend/src/css/Landing.css | 14 ++++++++++++++ 2 files changed, 35 insertions(+), 5 deletions(-) (limited to 'react-frontend/src') diff --git a/landing.html b/landing.html index 47ca60e..d97c2ba 100644 --- a/landing.html +++ b/landing.html @@ -28,10 +28,16 @@

    Our App

    -

    subtitle

    -

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

    -
    our data
    -
    our algorithm
    +

    +

    Inspiration

    +
    who we are; our inspi
    +

    +

    The Data

    +
    who we are; our inspi
    +

    +

    The Algorithm

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

    @@ -74,8 +80,18 @@
    +

    - +

    + +

    diff --git a/react-frontend/src/css/Landing.css b/react-frontend/src/css/Landing.css index 0a5a845..c2bc567 100644 --- a/react-frontend/src/css/Landing.css +++ b/react-frontend/src/css/Landing.css @@ -117,6 +117,8 @@ section { #app-intro{ padding-top: 160px; + height: fit-content; + width: 100vw; } .team { @@ -220,11 +222,23 @@ section { align-items: center; position: relative; left: -10px; + height: fit-content; + width: 100vw; } .footer-item{ color: white; font-size: 20px; } +.footer-subtext{ + color: white; + font-size: 15px; + width: 80vw; +} + +.appinfotxt { + font-size: 15px; + color:rgb(3, 2, 24); +} -- 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') 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') 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') 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') 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