From b7cf252ec0cf2ff47a7daa9296c938222131fb0d Mon Sep 17 00:00:00 2001 From: Daniel Wong Date: Thu, 3 May 2018 10:12:46 -0700 Subject: [PATCH 01/13] add upload modal --- components/FileUpload.js | 35 ++++ components/FileUploadButton.js | 42 +++++ components/ProgressBar.js | 40 +++++ components/SnowflakeApp.js | 43 ++--- components/TitleSelector.js | 58 +++--- components/UploadModal/SubmitStep.js | 27 +++ components/UploadModal/UploadMatrixStep.js | 14 ++ components/UploadModal/UploadModal.js | 98 ++++++++++ components/UploadModal/UploadThresholdStep.js | 12 ++ components/icons/CancelIcon.js | 32 ++++ components/icons/SuccessIcon.js | 30 ++++ package.json | 10 +- palette.js | 9 + yarn.lock | 168 ++++++++++++++++-- 14 files changed, 549 insertions(+), 69 deletions(-) create mode 100644 components/FileUpload.js create mode 100644 components/FileUploadButton.js create mode 100644 components/ProgressBar.js create mode 100644 components/UploadModal/SubmitStep.js create mode 100644 components/UploadModal/UploadMatrixStep.js create mode 100644 components/UploadModal/UploadModal.js create mode 100644 components/UploadModal/UploadThresholdStep.js create mode 100644 components/icons/CancelIcon.js create mode 100644 components/icons/SuccessIcon.js create mode 100644 palette.js diff --git a/components/FileUpload.js b/components/FileUpload.js new file mode 100644 index 00000000..17d9f5b2 --- /dev/null +++ b/components/FileUpload.js @@ -0,0 +1,35 @@ +import * as React from 'react'; +import Papa from 'papaparse'; + +console.log('pap', Papa) + + +class FileUpload extends React.Component { + constructor(props) { + super(props) + + this.state = { + } + } + + onChange = (e) => { + const file = e.target.files[0]; + + Papa.parse(file, { + complete: results => { + console.log('results', results) + } + }) + } + + render() { + return ( +
+

Upload a file

+ +
+ ) + } +} + +export default FileUpload; \ No newline at end of file diff --git a/components/FileUploadButton.js b/components/FileUploadButton.js new file mode 100644 index 00000000..6319c168 --- /dev/null +++ b/components/FileUploadButton.js @@ -0,0 +1,42 @@ +// @flow +import * as React from 'react'; +import glamorous from 'glamorous'; +import { teal, teal2 } from '../palette' + +const HiddenFileInput = glamorous.input({ + width: '100%', + height: '100%', + opacity: 0, + overflow: 'hidden', + position: 'absolute', + left: 0, + top: 0 +}) + +const UploadLabel = glamorous.button({ + position: 'relative', + backgroundColor: teal, + padding: '10px 20px', + borderRadius: '5px', + fontWeight: 600, + ':hover': { + backgroundColor: teal2 + }, + transition: 'background-color 0.25s', + margin: '0 auto', + textAlign: 'center', + width: '80px' +}) + +type FileUploadButtonProps = { + onChange: () => void +} + +const FileUploadButton = ({ onChange }: FileUploadButtonProps) => ( + + Upload + + +) + +export default FileUploadButton; \ No newline at end of file diff --git a/components/ProgressBar.js b/components/ProgressBar.js new file mode 100644 index 00000000..0720bb84 --- /dev/null +++ b/components/ProgressBar.js @@ -0,0 +1,40 @@ +// @flow +import * as React from 'react'; +import glamorous, { Div } from 'glamorous'; +import { green1, gray2 } from '../palette' + +const Circle = glamorous.div({ + display: 'inline-block', + minWidth: '30px', + minHeight: '30px', + borderRadius: '1000px' +}, +({ active }) => ({ backgroundColor: active ? green1 : gray2 }) +) + +const LineBetween = glamorous.hr({ + display: 'inline-block', + width: '100%' +}) + +type ProgressBarProps = { + numBuckets: number, + currentStep: number, + changeStep: (step: number) => void +} + +const ProgressBar = ({ currentStep, numBuckets, changeStep }: ProgressBarProps) => ( +
+ { + [...new Array(numBuckets - 1)].map((_, index) => + + index} onClick={() => changeStep(index + 1)} /> + + + ) + } + = numBuckets} onClick={() => changeStep(numBuckets)} /> +
+) + +export default ProgressBar; \ No newline at end of file diff --git a/components/SnowflakeApp.js b/components/SnowflakeApp.js index db61502f..1e42e198 100644 --- a/components/SnowflakeApp.js +++ b/components/SnowflakeApp.js @@ -10,13 +10,16 @@ import { eligibleTitles, trackIds, milestones, milestoneToPoints } from '../cons import PointSummaries from '../components/PointSummaries' import type { Milestone, MilestoneMap, TrackId } from '../constants' import React from 'react' -import TitleSelector from '../components/TitleSelector' +import Modal from 'react-modal' +import FileUpload from './FileUpload' +import UploadModal from './UploadModal/UploadModal' type SnowflakeAppState = { milestoneByTrack: MilestoneMap, name: string, title: string, focusedTrackId: TrackId, + isUploadModalOpen: boolean } const hashToState = (hash: String): ?SnowflakeAppState => { @@ -67,7 +70,8 @@ const emptyState = (): SnowflakeAppState => { 'RECRUITING': 0, 'COMMUNITY': 0 }, - focusedTrackId: 'MOBILE' + focusedTrackId: 'MOBILE', + isUploadModalOpen: false } } @@ -93,7 +97,8 @@ const defaultState = (): SnowflakeAppState => { 'RECRUITING': 3, 'COMMUNITY': 0 }, - focusedTrackId: 'MOBILE' + focusedTrackId: 'MOBILE', + isUploadModalOpen: false } } @@ -125,6 +130,14 @@ class SnowflakeApp extends React.Component { } } + toggleUploadModal = () => { + console.log('called'); + + this.setState({ + isUploadModalOpen: !this.state.isUploadModalOpen + }) + } + render() { return (
@@ -155,11 +168,6 @@ class SnowflakeApp extends React.Component { text-decoration: none; } `} -
- - - -
@@ -170,11 +178,10 @@ class SnowflakeApp extends React.Component { onChange={e => this.setState({name: e.target.value})} placeholder="Name" /> - this.setTitle(title)} /> +
@@ -185,6 +192,7 @@ class SnowflakeApp extends React.Component { handleTrackMilestoneChangeFn={(track, milestone) => this.handleTrackMilestoneChange(track, milestone)} />
+ { milestoneByTrack={this.state.milestoneByTrack} trackId={this.state.focusedTrackId} handleTrackMilestoneChangeFn={(track, milestone) => this.handleTrackMilestoneChange(track, milestone)} /> -
-
- Made with ❤️ by Medium Eng. - Learn about the growth framework. - Get the source code. - Read the terms of service. -
-
+
) } diff --git a/components/TitleSelector.js b/components/TitleSelector.js index ec9b1d2e..57c1fd6c 100644 --- a/components/TitleSelector.js +++ b/components/TitleSelector.js @@ -1,34 +1,34 @@ // @flow -import React from 'react' -import { eligibleTitles } from '../constants' -import type { MilestoneMap } from '../constants' +// import React from 'react' +// import { eligibleTitles } from '../constants' +// import type { MilestoneMap } from '../constants' -type Props = { - milestoneByTrack: MilestoneMap, - currentTitle: String, - setTitleFn: (string) => void -} +// type Props = { +// milestoneByTrack: MilestoneMap, +// currentTitle: String, +// setTitleFn: (string) => void +// } -class TitleSelector extends React.Component { - render() { - const titles = eligibleTitles(this.props.milestoneByTrack) - return - } -} +// class TitleSelector extends React.Component { +// render() { +// const titles = eligibleTitles(this.props.milestoneByTrack) +// return +// } +// } -export default TitleSelector +// export default TitleSelector diff --git a/components/UploadModal/SubmitStep.js b/components/UploadModal/SubmitStep.js new file mode 100644 index 00000000..b0a6e695 --- /dev/null +++ b/components/UploadModal/SubmitStep.js @@ -0,0 +1,27 @@ +import * as React from 'react'; +import glamorous, { Div, H1 } from 'glamorous' +import { teal, teal2 } from '../../palette' + +const FunButton = glamorous.button({ + backgroundColor: teal, + padding: '10px 20px', + borderRadius: '5px', + fontWeight: 600, + ':hover': { + backgroundColor: teal2 + }, + transition: 'background-color 0.25s', + margin: '0 auto', + textAlign: 'center', + width: '80px' +}) + +const SubmitStep = () => ( +
+

You can submit!

+ + Submit +
+) + +export default SubmitStep \ No newline at end of file diff --git a/components/UploadModal/UploadMatrixStep.js b/components/UploadModal/UploadMatrixStep.js new file mode 100644 index 00000000..9eefb085 --- /dev/null +++ b/components/UploadModal/UploadMatrixStep.js @@ -0,0 +1,14 @@ +import * as React from 'react'; +import FileUploadButton from '../FileUploadButton' +import { Div, H1 } from 'glamorous' + +const UploadMatrixStep = ({ + toNextStep +}) => ( +
+

Please upload your performance matrix.

+ +
+) + +export default UploadMatrixStep; \ No newline at end of file diff --git a/components/UploadModal/UploadModal.js b/components/UploadModal/UploadModal.js new file mode 100644 index 00000000..b63ddd5e --- /dev/null +++ b/components/UploadModal/UploadModal.js @@ -0,0 +1,98 @@ +// @flow +import * as React from 'react'; +import glamorous from 'glamorous'; +import Modal from 'react-modal'; +import CancelIcon from '../icons/CancelIcon' +import SuccessIcon from '../icons/SuccessIcon' +import ProgressBar from '../ProgressBar' +import { teal, teal2 } from '../../palette' +import UploadMatrixStep from './UploadMatrixStep' +import UploadThresholdStep from './UploadThresholdStep' +import SubmitStep from './SubmitStep' + +const UploadModalContainer = glamorous.div({ + padding: '40px', + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + boxSizing: 'border-box', + outline: 'none' +}) + +const ProgressBarContainer = glamorous.div({ + padding: '100px 20% 50px 20%', + width: '100%', + boxSizing: 'border-box' +}) + +type UploadModalProps = { + toggleModal: () => void, + isModalOpen: boolean +} +type UploadModalState = { + currentStep: number +} + +const totalSteps = 3; + +class UploadModal extends React.Component { + constructor(props: UploadModalProps) { + super(props) + + this.state = { + currentStep: 1 + } + } + + incStep = () => { + this.setState({ currentStep: Math.min(this.state.currentStep + 1, totalSteps) }) + } + + changeStep = (step: number) => { + this.setState({ + currentStep: step + }) + } + + getStep = () => { + switch (this.state.currentStep) { + case 1: + return + case 2: + return + case 3: + return + } + } + + onUploadMatrix = (e) => { + e.preventDefault(); + + this.incStep(); + } + + onUploadThreshold = (e) => { + e.preventDefault(); + + this.incStep(); + } + + render() { + return ( + + + + + + + + {this.getStep()} + + ); + } +} + +export default UploadModal \ No newline at end of file diff --git a/components/UploadModal/UploadThresholdStep.js b/components/UploadModal/UploadThresholdStep.js new file mode 100644 index 00000000..39517343 --- /dev/null +++ b/components/UploadModal/UploadThresholdStep.js @@ -0,0 +1,12 @@ +import * as React from 'react'; +import FileUploadButton from '../FileUploadButton' +import { Div, H1 } from 'glamorous' + +const UploadThresholdStep = ({ toNextStep }) => ( +
+

Please upload your threshold matrix.

+ +
+) + +export default UploadThresholdStep; \ No newline at end of file diff --git a/components/icons/CancelIcon.js b/components/icons/CancelIcon.js new file mode 100644 index 00000000..0f0d01ae --- /dev/null +++ b/components/icons/CancelIcon.js @@ -0,0 +1,32 @@ +// @flow + +import * as React from 'react'; +import glamorous from 'glamorous'; + +const IconContainer = glamorous.div({ + height: '50px', + width: '50px', + position: 'absolute', + right: '20px', + top: '20px', + cursor: 'pointer' +}) + +type CancelIconProps = { + onClick: () => void +} + +const CancelIcon = ({ onClick }: CancelIconProps) => ( + + + + + + + + + + +) + +export default CancelIcon; \ No newline at end of file diff --git a/components/icons/SuccessIcon.js b/components/icons/SuccessIcon.js new file mode 100644 index 00000000..e6f6ed8e --- /dev/null +++ b/components/icons/SuccessIcon.js @@ -0,0 +1,30 @@ +// @flow +import * as React from 'react'; +import glamorous from 'glamorous'; + +const IconContainer = glamorous.div({ + height: '50px', + width: '50px', + position: 'absolute', + right: '20px', + top: '20px', + cursor: 'pointer' +}) + +const SuccessIcon = () => ( + + + + + + + + + + +) + +export default SuccessIcon; + + + diff --git a/package.json b/package.json index d060d04e..3bbe117f 100644 --- a/package.json +++ b/package.json @@ -6,9 +6,13 @@ "license": "MIT", "dependencies": { "d3": "^4.11.0", + "glamor": "^2.20.40", + "glamorous": "^4.12.5", "next": "^4.0.0-beta.4", - "react": "^16.0.0", - "react-dom": "^16.0.0" + "papaparse": "^4.4.0", + "react": "^16.3.0", + "react-dom": "^16.3.0", + "react-modal": "^3.4.4" }, "scripts": { "dev": "next", @@ -16,6 +20,6 @@ "flow": "flow" }, "devDependencies": { - "flow-bin": "^0.57.2" + "flow-bin": "^0.59.0" } } diff --git a/palette.js b/palette.js new file mode 100644 index 00000000..9c6d2c29 --- /dev/null +++ b/palette.js @@ -0,0 +1,9 @@ +// @flow + +export const teal: string = '#b5fbe0'; +export const teal2: string = '#56f9bb'; + +export const gray1: string = '#e7e0dd'; +export const gray2: string = '#9faeb3'; + +export const green1: string = '#ccff00'; \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index f0d240ec..80433fed 100644 --- a/yarn.lock +++ b/yarn.lock @@ -906,6 +906,10 @@ boom@5.x.x: dependencies: hoek "4.x.x" +bowser@^1.7.3: + version "1.9.3" + resolved "https://registry.yarnpkg.com/bowser/-/bowser-1.9.3.tgz#6643ae4d783f31683f6d23156976b74183862162" + brace-expansion@^1.1.7: version "1.1.8" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292" @@ -921,6 +925,10 @@ braces@^1.8.2: preserve "^0.2.0" repeat-element "^1.1.2" +brcast@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/brcast/-/brcast-3.0.1.tgz#6256a8349b20de9eed44257a9b24d71493cd48dd" + brorand@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" @@ -1349,6 +1357,17 @@ crypto-browserify@^3.11.0: public-encrypt "^4.0.0" randombytes "^2.0.0" +css-in-js-utils@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/css-in-js-utils/-/css-in-js-utils-2.0.1.tgz#3b472b398787291b47cfe3e44fecfdd9e914ba99" + dependencies: + hyphenate-style-name "^1.0.2" + isobject "^3.0.1" + +csstype@^2.2.0: + version "2.4.2" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.4.2.tgz#158e36c69566bf968da63d0ba14eda1c20e8643a" + currently-unhandled@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" @@ -1896,6 +1915,10 @@ execa@^0.8.0: signal-exit "^3.0.0" strip-eof "^1.0.0" +exenv@^1.2.0: + version "1.2.2" + resolved "https://registry.yarnpkg.com/exenv/-/exenv-1.2.2.tgz#2ae78e85d9894158670b03d47bec1f03bd91bb9d" + expand-brackets@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" @@ -1926,7 +1949,11 @@ fast-deep-equal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff" -fbjs@^0.8.16: +fast-memoize@^2.2.7: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fast-memoize/-/fast-memoize-2.3.2.tgz#f6b9eb8e06a754029cca25b4cd3945f2f6242c90" + +fbjs@^0.8.12, fbjs@^0.8.16: version "0.8.16" resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.16.tgz#5e67432f550dc41b572bf55847b8aca64e5337db" dependencies: @@ -1984,9 +2011,9 @@ find-up@^2.0.0, find-up@^2.1.0: dependencies: locate-path "^2.0.0" -flow-bin@^0.57.2: - version "0.57.2" - resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.57.2.tgz#0b5ed4dd38a1991047e9bee71d62a763ae61b6b7" +flow-bin@^0.59.0: + version "0.59.0" + resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.59.0.tgz#8c151ee7f09f1deed9bf0b9d1f2e8ab9d470f1bb" follow-redirects@0.0.7: version "0.0.7" @@ -2201,6 +2228,29 @@ github@~0.1.10: version "0.1.16" resolved "https://registry.yarnpkg.com/github/-/github-0.1.16.tgz#895d2a85b0feb7980d89ac0ce4f44dcaa03f17b5" +glamor@^2.20.40: + version "2.20.40" + resolved "https://registry.yarnpkg.com/glamor/-/glamor-2.20.40.tgz#f606660357b7cf18dface731ad1a2cfa93817f05" + dependencies: + fbjs "^0.8.12" + inline-style-prefixer "^3.0.6" + object-assign "^4.1.1" + prop-types "^15.5.10" + through "^2.3.8" + +glamorous@^4.12.5: + version "4.12.5" + resolved "https://registry.yarnpkg.com/glamorous/-/glamorous-4.12.5.tgz#909e0ec2ab3136e4749bf82edd9f33b51745e41f" + dependencies: + brcast "^3.0.0" + csstype "^2.2.0" + fast-memoize "^2.2.7" + html-tag-names "^1.1.1" + is-function "^1.0.1" + is-plain-object "^2.0.4" + react-html-attributes "^1.4.2" + svg-tag-names "^1.1.0" + glob-base@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" @@ -2412,10 +2462,18 @@ hosted-git-info@^2.1.4, hosted-git-info@^2.4.2: version "2.5.0" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.5.0.tgz#6d60e34b3abbc8313062c3b798ef8d901a07af3c" +html-element-attributes@^1.0.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/html-element-attributes/-/html-element-attributes-1.3.1.tgz#9fa6a2e37e6b61790a303e87ddbbb9746e8c035f" + html-entities@^1.2.0: version "1.2.1" resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.2.1.tgz#0df29351f0721163515dfb9e5543e5f6eed5162f" +html-tag-names@^1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/html-tag-names/-/html-tag-names-1.1.3.tgz#f81f75e59d626cb8a958a19e58f90c1d69707b82" + htmlescape@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/htmlescape/-/htmlescape-1.1.1.tgz#3a03edc2214bca3b66424a3e7959349509cb0351" @@ -2468,10 +2526,20 @@ https-proxy-agent@^1.0.0: debug "2" extend "3" -iconv-lite@0.4, iconv-lite@~0.4.13: +hyphenate-style-name@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.2.tgz#31160a36930adaf1fc04c6074f7eb41465d4ec4b" + +iconv-lite@0.4: version "0.4.19" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" +iconv-lite@~0.4.13: + version "0.4.21" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.21.tgz#c47f8733d02171189ebc4a400f3218d348094798" + dependencies: + safer-buffer "^2.1.0" + ieee754@^1.1.4: version "1.1.8" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.8.tgz#be33d40ac10ef1926701f6f08a2d86fbfd1ad3e4" @@ -2511,6 +2579,13 @@ ini@^1.2.0, ini@^1.3.2, ini@^1.3.4, ini@~1.3.0: version "1.3.4" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e" +inline-style-prefixer@^3.0.6: + version "3.0.8" + resolved "https://registry.yarnpkg.com/inline-style-prefixer/-/inline-style-prefixer-3.0.8.tgz#8551b8e5b4d573244e66a34b04f7d32076a2b534" + dependencies: + bowser "^1.7.3" + css-in-js-utils "^2.0.0" + interpret@^1.0.0: version "1.0.4" resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.0.4.tgz#820cdd588b868ffb191a809506d6c9c8f212b1b0" @@ -2579,6 +2654,10 @@ is-fullwidth-code-point@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" +is-function@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.1.tgz#12cfb98b65b57dd3d193a3121f5f6e2f437602b5" + is-glob@^2.0.0, is-glob@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" @@ -2626,6 +2705,12 @@ is-path-inside@^1.0.0: dependencies: path-is-inside "^1.0.1" +is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + dependencies: + isobject "^3.0.1" + is-posix-bracket@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" @@ -2678,6 +2763,10 @@ isobject@^2.0.0: dependencies: isarray "1.0.0" +isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + isomorphic-fetch@^2.1.1: version "2.2.1" resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9" @@ -3454,6 +3543,10 @@ pako@~0.2.0: version "0.2.9" resolved "https://registry.yarnpkg.com/pako/-/pako-0.2.9.tgz#f3f7522f4ef782348da8161bad9ecfd51bf83a75" +papaparse@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/papaparse/-/papaparse-4.4.0.tgz#6bcdbda80873e00cfb0bdcd7a4571c72a9a40168" + parse-asn1@^5.0.0: version "5.1.0" resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.0.tgz#37c4f9b7ed3ab65c74817b5f2480937fbf97c712" @@ -3628,7 +3721,7 @@ prop-types-exact@1.1.1: has "^1.0.1" object.assign "^4.0.4" -prop-types@15.6.0, prop-types@^15.5.4, prop-types@^15.6.0: +prop-types@15.6.0, prop-types@^15.5.4: version "15.6.0" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.0.tgz#ceaf083022fc46b4a35f69e13ef75aed0d639856" dependencies: @@ -3636,6 +3729,14 @@ prop-types@15.6.0, prop-types@^15.5.4, prop-types@^15.6.0: loose-envify "^1.3.1" object-assign "^4.1.1" +prop-types@^15.5.10, prop-types@^15.6.0: + version "15.6.1" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.1.tgz#36644453564255ddda391191fb3a125cbdf654ca" + dependencies: + fbjs "^0.8.16" + loose-envify "^1.3.1" + object-assign "^4.1.1" + proto-list@~1.2.1: version "1.2.4" resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" @@ -3724,9 +3825,9 @@ react-deep-force-update@^2.0.1: version "2.1.1" resolved "https://registry.yarnpkg.com/react-deep-force-update/-/react-deep-force-update-2.1.1.tgz#8ea4263cd6455a050b37445b3f08fd839d86e909" -react-dom@^16.0.0: - version "16.0.0" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.0.0.tgz#9cc3079c3dcd70d4c6e01b84aab2a7e34c303f58" +react-dom@^16.3.0: + version "16.3.2" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.3.2.tgz#cb90f107e09536d683d84ed5d4888e9640e0e4df" dependencies: fbjs "^0.8.16" loose-envify "^1.1.0" @@ -3744,15 +3845,34 @@ react-hot-loader@3.0.0-beta.7: redbox-react "^1.3.6" source-map "^0.4.4" +react-html-attributes@^1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/react-html-attributes/-/react-html-attributes-1.4.2.tgz#0d2ccf134fc79b2d3543837dc1591d32b7b903f9" + dependencies: + html-element-attributes "^1.0.0" + +react-lifecycles-compat@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.2.tgz#7279047275bd727a912e25f734c0559527e84eff" + +react-modal@^3.4.4: + version "3.4.4" + resolved "https://registry.yarnpkg.com/react-modal/-/react-modal-3.4.4.tgz#e9dde25e9e85a59c76831f2a2b468712a546aded" + dependencies: + exenv "^1.2.0" + prop-types "^15.5.10" + react-lifecycles-compat "^3.0.0" + warning "^3.0.0" + react-proxy@^3.0.0-alpha.0: version "3.0.0-alpha.1" resolved "https://registry.yarnpkg.com/react-proxy/-/react-proxy-3.0.0-alpha.1.tgz#4400426bcfa80caa6724c7755695315209fa4b07" dependencies: lodash "^4.6.1" -react@^16.0.0: - version "16.0.0" - resolved "https://registry.yarnpkg.com/react/-/react-16.0.0.tgz#ce7df8f1941b036f02b2cca9dbd0cb1f0e855e2d" +react@^16.3.0: + version "16.3.2" + resolved "https://registry.yarnpkg.com/react/-/react-16.3.2.tgz#fdc8420398533a1e58872f59091b272ce2f91ea9" dependencies: fbjs "^0.8.16" loose-envify "^1.1.0" @@ -4074,6 +4194,10 @@ safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@~5.1.0, version "5.1.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" +safer-buffer@^2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + semantic-release@^8.0.3: version "8.1.2" resolved "https://registry.yarnpkg.com/semantic-release/-/semantic-release-8.1.2.tgz#554b77a24df8af35cbc4c0fb423e908329ef5d23" @@ -4394,6 +4518,10 @@ supports-color@^4.0.0, supports-color@^4.2.1: dependencies: has-flag "^2.0.0" +svg-tag-names@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/svg-tag-names/-/svg-tag-names-1.1.1.tgz#9641b29ef71025ee094c7043f7cdde7d99fbd50a" + tapable@^0.2.7: version "0.2.8" resolved "https://registry.yarnpkg.com/tapable/-/tapable-0.2.8.tgz#99372a5c999bf2df160afc0d74bed4f47948cd22" @@ -4442,7 +4570,7 @@ through2@^2.0.0, through2@^2.0.2: readable-stream "^2.1.5" xtend "~4.0.1" -through@2, "through@>=2.2.7 <3": +through@2, "through@>=2.2.7 <3", through@^2.3.8: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" @@ -4529,8 +4657,8 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" ua-parser-js@^0.7.9: - version "0.7.14" - resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.14.tgz#110d53fa4c3f326c121292bbeac904d2e03387ca" + version "0.7.17" + resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.17.tgz#e9ec5f9498b9ec910e7ae3ac626a805c4d09ecac" uglify-js@^2.6, uglify-js@^2.8.29: version "2.8.29" @@ -4627,6 +4755,12 @@ walk@2.3.9, walk@^2.3.9: dependencies: foreachasync "^3.0.0" +warning@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/warning/-/warning-3.0.0.tgz#32e5377cb572de4ab04753bdf8821c01ed605b7c" + dependencies: + loose-envify "^1.0.0" + watchpack@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.4.0.tgz#4a1472bcbb952bd0a9bb4036801f954dfb39faac" @@ -4689,8 +4823,8 @@ webpack@3.6.0: yargs "^8.0.2" whatwg-fetch@>=0.10.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz#9c84ec2dcf68187ff00bc64e1274b442176e1c84" + version "2.0.4" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz#dde6a5df315f9d39991aa17621853d720b85566f" which-module@^2.0.0: version "2.0.0" From 99e706b05ed269ea3f039aa331e9ea634abe2376 Mon Sep 17 00:00:00 2001 From: Daniel Wong Date: Thu, 3 May 2018 10:16:41 -0700 Subject: [PATCH 02/13] remove fileupload --- components/FileUpload.js | 35 ----------------------------------- 1 file changed, 35 deletions(-) delete mode 100644 components/FileUpload.js diff --git a/components/FileUpload.js b/components/FileUpload.js deleted file mode 100644 index 17d9f5b2..00000000 --- a/components/FileUpload.js +++ /dev/null @@ -1,35 +0,0 @@ -import * as React from 'react'; -import Papa from 'papaparse'; - -console.log('pap', Papa) - - -class FileUpload extends React.Component { - constructor(props) { - super(props) - - this.state = { - } - } - - onChange = (e) => { - const file = e.target.files[0]; - - Papa.parse(file, { - complete: results => { - console.log('results', results) - } - }) - } - - render() { - return ( -
-

Upload a file

- -
- ) - } -} - -export default FileUpload; \ No newline at end of file From 10c857474ea978847bd21257b2fbc0fccc509e93 Mon Sep 17 00:00:00 2001 From: Daniel Wong Date: Thu, 3 May 2018 10:21:29 -0700 Subject: [PATCH 03/13] file file upload --- components/SnowflakeApp.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/components/SnowflakeApp.js b/components/SnowflakeApp.js index 1e42e198..a786e5ab 100644 --- a/components/SnowflakeApp.js +++ b/components/SnowflakeApp.js @@ -11,7 +11,6 @@ import PointSummaries from '../components/PointSummaries' import type { Milestone, MilestoneMap, TrackId } from '../constants' import React from 'react' import Modal from 'react-modal' -import FileUpload from './FileUpload' import UploadModal from './UploadModal/UploadModal' type SnowflakeAppState = { @@ -192,7 +191,6 @@ class SnowflakeApp extends React.Component { handleTrackMilestoneChangeFn={(track, milestone) => this.handleTrackMilestoneChange(track, milestone)} /> - Date: Thu, 3 May 2018 11:49:19 -0700 Subject: [PATCH 04/13] add files to state --- components/UploadModal/UploadModal.js | 29 +++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/components/UploadModal/UploadModal.js b/components/UploadModal/UploadModal.js index b63ddd5e..17a88169 100644 --- a/components/UploadModal/UploadModal.js +++ b/components/UploadModal/UploadModal.js @@ -30,9 +30,11 @@ type UploadModalProps = { isModalOpen: boolean } type UploadModalState = { - currentStep: number + currentStep: number, + files: { matrixFile?: File, thresholdFile?: File } } + const totalSteps = 3; class UploadModal extends React.Component { @@ -40,7 +42,8 @@ class UploadModal extends React.Component { super(props) this.state = { - currentStep: 1 + currentStep: 1, + files: {} } } @@ -48,6 +51,15 @@ class UploadModal extends React.Component { this.setState({ currentStep: Math.min(this.state.currentStep + 1, totalSteps) }) } + saveFile = (file: File, name: string) => { + this.setState( + { files: { + ...this.state.files, + [name]: file + } } + ); +} + changeStep = (step: number) => { this.setState({ currentStep: step @@ -65,15 +77,20 @@ class UploadModal extends React.Component { } } - onUploadMatrix = (e) => { + onUploadMatrix = (e: any) => { e.preventDefault(); - + + const matrixFile = e.target.files[0]; + this.saveFile(matrixFile, "matrixFile"); this.incStep(); } - onUploadThreshold = (e) => { + onUploadThreshold = (e: any) => { + debugger; e.preventDefault(); - + + const thresholdFile = e.target.files[0]; + this.saveFile(thresholdFile, "thresholdFile"); this.incStep(); } From 6ebaaed6970248cdd59f739a6121f7fa8b53251d Mon Sep 17 00:00:00 2001 From: Jesus Garcia Date: Thu, 3 May 2018 13:27:53 -0700 Subject: [PATCH 05/13] update modal vh --- api/api.js | 9 +++++++++ api/apiDev.js | 18 ++++++++++++++++++ api/apiServer.js | 2 ++ api/apiType.js | 10 ++++++++++ components/UploadModal/UploadModal.js | 2 +- 5 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 api/api.js create mode 100644 api/apiDev.js create mode 100644 api/apiServer.js create mode 100644 api/apiType.js diff --git a/api/api.js b/api/api.js new file mode 100644 index 00000000..0f2a1c28 --- /dev/null +++ b/api/api.js @@ -0,0 +1,9 @@ +// @flow +import apiDev from './apiDev'; +import apiServer from './apiServer'; + +const isProd = false; + +const api = isProd ? apiServer : apiDev + +export default api; \ No newline at end of file diff --git a/api/apiDev.js b/api/apiDev.js new file mode 100644 index 00000000..bd925703 --- /dev/null +++ b/api/apiDev.js @@ -0,0 +1,18 @@ +// @flow +import type { Api, Files } from './apiType'; + +const wait = () => { + return new Promise((resolve, reject) => { + setTimeout(() => resolve(), 500); + }) +} + +const apiDev: Api = { + async submitFiles(files: Files) { + // does some stuff + await wait(); + return; + } +} + + diff --git a/api/apiServer.js b/api/apiServer.js new file mode 100644 index 00000000..ee165f40 --- /dev/null +++ b/api/apiServer.js @@ -0,0 +1,2 @@ +// @flow + diff --git a/api/apiType.js b/api/apiType.js new file mode 100644 index 00000000..1d491efe --- /dev/null +++ b/api/apiType.js @@ -0,0 +1,10 @@ +// @flow + +export type Files = { + [fileName: string]: File +} + +export type Api = { + submitFiles: (files: File) => Promise +} + diff --git a/components/UploadModal/UploadModal.js b/components/UploadModal/UploadModal.js index 17a88169..1dcba64d 100644 --- a/components/UploadModal/UploadModal.js +++ b/components/UploadModal/UploadModal.js @@ -96,7 +96,7 @@ class UploadModal extends React.Component { render() { return ( - + Date: Thu, 3 May 2018 15:15:08 -0700 Subject: [PATCH 06/13] remove console.log --- components/SnowflakeApp.js | 1 - 1 file changed, 1 deletion(-) diff --git a/components/SnowflakeApp.js b/components/SnowflakeApp.js index a786e5ab..0e10e157 100644 --- a/components/SnowflakeApp.js +++ b/components/SnowflakeApp.js @@ -130,7 +130,6 @@ class SnowflakeApp extends React.Component { } toggleUploadModal = () => { - console.log('called'); this.setState({ isUploadModalOpen: !this.state.isUploadModalOpen From ec123f08d845b703a398e0212a1c5e768e225809 Mon Sep 17 00:00:00 2001 From: Daniel Wong Date: Thu, 3 May 2018 16:50:47 -0700 Subject: [PATCH 07/13] migrate NightingaleChart off constants --- api/api.js | 3 ++- api/apiDev.js | 6 ++++- api/apiServer.js | 1 + api/apiType.js | 4 ++- components/NightingaleChart.js | 12 ++++++--- components/SnowflakeApp.js | 27 +++++++++++++++----- components/Track.js | 4 ++- constants.js | 45 ++++++---------------------------- 8 files changed, 50 insertions(+), 52 deletions(-) diff --git a/api/api.js b/api/api.js index 0f2a1c28..01dda909 100644 --- a/api/api.js +++ b/api/api.js @@ -1,9 +1,10 @@ // @flow +import type { Api } from './apiType' import apiDev from './apiDev'; import apiServer from './apiServer'; const isProd = false; -const api = isProd ? apiServer : apiDev +const api: Api = isProd ? apiDev : apiDev export default api; \ No newline at end of file diff --git a/api/apiDev.js b/api/apiDev.js index bd925703..ec533fa3 100644 --- a/api/apiDev.js +++ b/api/apiDev.js @@ -1,5 +1,6 @@ // @flow import type { Api, Files } from './apiType'; +import { tracks } from '../constants' const wait = () => { return new Promise((resolve, reject) => { @@ -12,7 +13,10 @@ const apiDev: Api = { // does some stuff await wait(); return; + }, + async getMasterConfig(department: string) { + return tracks; } } - +export default apiDev; \ No newline at end of file diff --git a/api/apiServer.js b/api/apiServer.js index ee165f40..10497787 100644 --- a/api/apiServer.js +++ b/api/apiServer.js @@ -1,2 +1,3 @@ // @flow + diff --git a/api/apiType.js b/api/apiType.js index 1d491efe..13ecad7a 100644 --- a/api/apiType.js +++ b/api/apiType.js @@ -1,10 +1,12 @@ // @flow +import type { Tracks } from '../constants' export type Files = { [fileName: string]: File } export type Api = { - submitFiles: (files: File) => Promise + submitFiles: (files: File) => Promise, + getMasterConfig: (dept: string) => Promise } diff --git a/components/NightingaleChart.js b/components/NightingaleChart.js index acbc28f7..e37d3443 100644 --- a/components/NightingaleChart.js +++ b/components/NightingaleChart.js @@ -2,16 +2,19 @@ import React from 'react' import * as d3 from 'd3' -import { trackIds, milestones, tracks, categoryColorScale } from '../constants' +import { milestones, categoryColorScale } from '../constants' +import type { Tracks } from '../constants' import type { TrackId, Milestone, MilestoneMap } from '../constants' const width = 400 const arcMilestones = milestones.slice(1) // we'll draw the '0' milestone with a circle, not an arc. type Props = { + tracks: Tracks, milestoneByTrack: MilestoneMap, focusedTrackId: TrackId, - handleTrackMilestoneChangeFn: (TrackId, Milestone) => void + handleTrackMilestoneChangeFn: (TrackId, Milestone) => void, + trackIds: Array } class NightingaleChart extends React.Component { @@ -33,14 +36,15 @@ class NightingaleChart extends React.Component { this.arcFn = d3.arc() .innerRadius(milestone => this.radiusScale(milestone)) .outerRadius(milestone => this.radiusScale(milestone) + this.radiusScale.bandwidth()) - .startAngle(- Math.PI / trackIds.length) - .endAngle(Math.PI / trackIds.length) + .startAngle(- Math.PI / this.props.trackIds.length) + .endAngle(Math.PI / this.props.trackIds.length) .padAngle(Math.PI / 200) .padRadius(.45 * width) .cornerRadius(2) } render() { + const { trackIds, tracks } = this.props; const currentMilestoneId = this.props.milestoneByTrack[this.props.focusedTrackId] return (
diff --git a/components/SnowflakeApp.js b/components/SnowflakeApp.js index 0e10e157..abfcc811 100644 --- a/components/SnowflakeApp.js +++ b/components/SnowflakeApp.js @@ -6,19 +6,22 @@ import KeyboardListener from '../components/KeyboardListener' import Track from '../components/Track' import Wordmark from '../components/Wordmark' import LevelThermometer from '../components/LevelThermometer' -import { eligibleTitles, trackIds, milestones, milestoneToPoints } from '../constants' +import { eligibleTitles, trackIds, milestones, milestoneToPoints, departments } from '../constants' +import type { Tracks } from '../constants' import PointSummaries from '../components/PointSummaries' import type { Milestone, MilestoneMap, TrackId } from '../constants' import React from 'react' import Modal from 'react-modal' import UploadModal from './UploadModal/UploadModal' +import api from '../api/api' type SnowflakeAppState = { milestoneByTrack: MilestoneMap, name: string, title: string, focusedTrackId: TrackId, - isUploadModalOpen: boolean + isUploadModalOpen: boolean, + tracks?: Tracks } const hashToState = (hash: String): ?SnowflakeAppState => { @@ -121,6 +124,14 @@ class SnowflakeApp extends React.Component { } componentDidMount() { + // request for the the initial constants - the defualt will be engineering masterconfig + api.getMasterConfig(departments[0]) + .then(tracks => { + this.setState({ + tracks + }) + }) + const state = hashToState(window.location.hash) if (state) { this.setState(state) @@ -137,6 +148,8 @@ class SnowflakeApp extends React.Component { } render() { + if (!this.state.tracks) return null; + return (