├── .babelrc ├── .editorconfig ├── .eslintignore ├── .eslintrc ├── .gitignore ├── .stylelintrc ├── .travis.yml ├── README.md ├── browserslist ├── build ├── assets │ ├── fonts │ │ ├── font-awesome.woff │ │ ├── source-sans-pro-extra-light.woff │ │ ├── source-sans-pro-light.woff │ │ └── source-sans-pro-regular.woff │ └── images │ │ ├── android-chrome-192x192.png │ │ ├── apple-touch-icon-152x152.png │ │ ├── apple-touch-icon-180x180.png │ │ ├── augur-tile-large.png │ │ ├── augur-tile-medium.png │ │ ├── augur-tile-small.png │ │ ├── augur-tile-wide.png │ │ ├── favicon-16x16.png │ │ ├── favicon-32x32.png │ │ └── safari-pinned-tab.svg ├── components.jsx └── styles.css ├── docs └── conventions.md ├── firebase.json ├── hooks └── pre-push.sh ├── lib └── assertions.js ├── package.json ├── src ├── assertions.js ├── assets │ ├── fonts │ │ ├── font-awesome.woff │ │ ├── source-sans-pro-extra-light.woff │ │ ├── source-sans-pro-light.woff │ │ └── source-sans-pro-regular.woff │ └── images │ │ ├── android-chrome-192x192.png │ │ ├── apple-touch-icon-152x152.png │ │ ├── apple-touch-icon-180x180.png │ │ ├── augur-tile-large.png │ │ ├── augur-tile-medium.png │ │ ├── augur-tile-small.png │ │ ├── augur-tile-wide.png │ │ ├── favicon-16x16.png │ │ ├── favicon-32x32.png │ │ └── safari-pinned-tab.svg ├── components.jsx ├── index.html ├── index.js ├── modules │ ├── account │ │ ├── components │ │ │ └── account-view.jsx │ │ └── less │ │ │ └── account.less │ ├── app │ │ ├── components │ │ │ ├── app.jsx │ │ │ ├── core-stats.jsx │ │ │ ├── footer.jsx │ │ │ ├── header.jsx │ │ │ ├── nav.jsx │ │ │ ├── routes.jsx │ │ │ └── side-bar.jsx │ │ ├── constants │ │ │ └── views.js │ │ └── less │ │ │ ├── animations.less │ │ │ ├── app.less │ │ │ ├── arrangement.less │ │ │ ├── borders.less │ │ │ ├── box-shadow.less │ │ │ ├── colors.less │ │ │ ├── common.less │ │ │ ├── core-stats.less │ │ │ ├── footer.less │ │ │ ├── header.less │ │ │ ├── layout.less │ │ │ ├── nav.less │ │ │ ├── responsive.less │ │ │ ├── side-bar.less │ │ │ ├── tables.less │ │ │ ├── typography.less │ │ │ └── view-header.less │ ├── auth │ │ ├── components │ │ │ ├── auth-form.jsx │ │ │ └── auth-view.jsx │ │ ├── constants │ │ │ └── auth-types.js │ │ └── less │ │ │ └── auth.less │ ├── bids-asks │ │ ├── components │ │ │ ├── bids-asks.jsx │ │ │ └── order-book.jsx │ │ └── less │ │ │ ├── bids-asks.less │ │ │ └── order-book.less │ ├── branch │ │ ├── components │ │ │ └── branch.jsx │ │ └── less │ │ │ └── branch.less │ ├── chat │ │ ├── components │ │ │ └── chat-view.jsx │ │ └── less │ │ │ └── chat.less │ ├── common │ │ ├── components │ │ │ ├── augur-logo-full.jsx │ │ │ ├── augur-logo-icon.jsx │ │ │ ├── bullet.jsx │ │ │ ├── checkbox.jsx │ │ │ ├── collapse.jsx │ │ │ ├── component-nav.jsx │ │ │ ├── datepicker.jsx │ │ │ ├── dropdown.jsx │ │ │ ├── em-dash.jsx │ │ │ ├── input-list.jsx │ │ │ ├── input.jsx │ │ │ ├── null-state-message.jsx │ │ │ ├── side-bar-mask.jsx │ │ │ ├── tab-navigation.jsx │ │ │ ├── toggler.jsx │ │ │ ├── value-date.jsx │ │ │ ├── value-denomination.jsx │ │ │ └── value-timestamp.jsx │ │ └── less │ │ │ ├── buttons.less │ │ │ ├── checkbox.less │ │ │ ├── component-nav.less │ │ │ ├── datepicker.less │ │ │ ├── dropdown.less │ │ │ ├── input.less │ │ │ ├── null-state-message.less │ │ │ ├── page.less │ │ │ ├── panel-sideways.less │ │ │ ├── side-bar-mask.less │ │ │ ├── tab-navigation.less │ │ │ └── value-denomination.less │ ├── create-market │ │ ├── components │ │ │ ├── create-market-form-1.jsx │ │ │ ├── create-market-form-2-categorical.jsx │ │ │ ├── create-market-form-2-scalar.jsx │ │ │ ├── create-market-form-2.jsx │ │ │ ├── create-market-form-3.jsx │ │ │ ├── create-market-form-4.jsx │ │ │ ├── create-market-form-5.jsx │ │ │ ├── create-market-form-buttons.jsx │ │ │ ├── create-market-form.jsx │ │ │ └── create-market-view.jsx │ │ └── less │ │ │ └── create-market.less │ ├── link │ │ └── components │ │ │ └── link.jsx │ ├── login-message │ │ ├── components │ │ │ └── login-message-view.jsx │ │ └── less │ │ │ └── login-message.less │ ├── market │ │ ├── components │ │ │ ├── market-active.jsx │ │ │ ├── market-basics.jsx │ │ │ ├── market-chart.jsx │ │ │ ├── market-data.jsx │ │ │ ├── market-details.jsx │ │ │ ├── market-header.jsx │ │ │ ├── market-open-orders-group.jsx │ │ │ ├── market-open-orders-row.jsx │ │ │ ├── market-open-orders.jsx │ │ │ ├── market-positions-row.jsx │ │ │ ├── market-positions.jsx │ │ │ ├── market-preview-outcomes.jsx │ │ │ ├── market-preview.jsx │ │ │ ├── market-properties.jsx │ │ │ ├── market-reported.jsx │ │ │ ├── market-reporting.jsx │ │ │ ├── market-summary.jsx │ │ │ ├── market-user-data.jsx │ │ │ └── market-view.jsx │ │ ├── constants │ │ │ └── share-denominations.js │ │ └── less │ │ │ ├── basics-advanced.less │ │ │ ├── market-active.less │ │ │ ├── market-basics.less │ │ │ ├── market-details.less │ │ │ ├── market-header.less │ │ │ ├── market-item.less │ │ │ ├── market-open-orders-group.less │ │ │ ├── market-open-orders-row.less │ │ │ ├── market-open-orders.less │ │ │ ├── market-positions.less │ │ │ ├── market-preview-outcomes.less │ │ │ ├── market-preview.less │ │ │ ├── market-properties.less │ │ │ ├── market-user-data.less │ │ │ └── market.less │ ├── markets │ │ ├── components │ │ │ ├── markets-filter-sort.jsx │ │ │ ├── markets-headers.jsx │ │ │ ├── markets-list.jsx │ │ │ ├── markets-pagination.jsx │ │ │ ├── markets-search.jsx │ │ │ ├── markets-tags.jsx │ │ │ └── markets-view.jsx │ │ ├── constants │ │ │ ├── market-types.js │ │ │ └── markets-headers.js │ │ └── less │ │ │ ├── markets-filter-sort.less │ │ │ ├── markets-pagination.less │ │ │ └── markets-search.less │ ├── my-markets │ │ ├── components │ │ │ ├── my-market-summary-header.jsx │ │ │ └── my-market.jsx │ │ └── less │ │ │ └── my-markets.less │ ├── my-positions │ │ ├── components │ │ │ ├── my-position.jsx │ │ │ ├── my-positions-market-overview.jsx │ │ │ ├── my-positions-summary.jsx │ │ │ └── my-positions.jsx │ │ └── less │ │ │ └── my-positions.less │ ├── my-reports │ │ ├── components │ │ │ └── my-report.jsx │ │ └── less │ │ │ └── my-reports.less │ ├── open-orders │ │ ├── components │ │ │ ├── open-order.jsx │ │ │ └── open-orders-group.jsx │ │ └── less │ │ │ └── open-order.less │ ├── order-book │ │ ├── components │ │ │ ├── order-book-header.jsx │ │ │ ├── order-book-row-side.jsx │ │ │ ├── order-book-rows.jsx │ │ │ └── order-book.jsx │ │ ├── constants │ │ │ └── order-book-value-types.js │ │ └── less │ │ │ ├── order-book-header.less │ │ │ ├── order-book-row-side.less │ │ │ ├── order-book-rows.less │ │ │ └── order-book.less │ ├── outcomes │ │ ├── components │ │ │ ├── outcome-trade-action.jsx │ │ │ ├── outcome-trade-summary.jsx │ │ │ ├── outcome-trade.jsx │ │ │ ├── outcome.jsx │ │ │ └── outcomes.jsx │ │ ├── constants │ │ │ └── trade-types.js │ │ └── less │ │ │ ├── outcome-trade-action.less │ │ │ ├── outcome-trade-summary.less │ │ │ ├── outcome-trade.less │ │ │ ├── outcome.less │ │ │ └── outcomes.less │ ├── portfolio │ │ ├── components │ │ │ ├── markets.jsx │ │ │ ├── portfolio-view.jsx │ │ │ ├── positions.jsx │ │ │ └── reports.jsx │ │ └── less │ │ │ └── portfolio-page.less │ ├── reports │ │ ├── components │ │ │ ├── report-form.jsx │ │ │ └── report-panel.jsx │ │ └── less │ │ │ └── report-form.less │ └── transactions │ │ ├── components │ │ ├── transaction.jsx │ │ ├── transactions-view.jsx │ │ └── transactions.jsx │ │ ├── constants │ │ └── types.js │ │ └── less │ │ └── transactions.less ├── selectors.js ├── selectors │ ├── active-view.js │ ├── auth-form.js │ ├── bids-asks │ │ └── select-bids-asks.js │ ├── chat.js │ ├── core-stats.js │ ├── create-market-form.js │ ├── filter-sort.js │ ├── is-transactions-working.js │ ├── keywords.js │ ├── links.js │ ├── login-account-markets.js │ ├── login-account-positions.js │ ├── login-account-reports.js │ ├── login-account.js │ ├── market-data-age.js │ ├── market-data-nav-items.js │ ├── market-data-updater.js │ ├── market-reporting-nav-items.js │ ├── market-user-data-nav-items.js │ ├── market.js │ ├── markets-header.js │ ├── markets-totals.js │ ├── markets.js │ ├── my-markets-summary.js │ ├── my-markets.js │ ├── my-reports-summary.js │ ├── my-reports.js │ ├── order-cancellation.js │ ├── outcome-trade-nav-items.js │ ├── pagination.js │ ├── portfolio-nav-items.js │ ├── portfolio-totals.js │ ├── portfolio.js │ ├── positions-markets.js │ ├── positions-summary.js │ ├── reportable-outcomes.js │ ├── scalar-share-denomination.js │ ├── search.js │ ├── selected-outcome.js │ ├── settings.js │ ├── shares-purchased.js │ ├── tags.js │ ├── trade-commit-lock.js │ ├── transactions-totals.js │ ├── transactions.js │ └── url.js ├── styles.less └── utils │ ├── add-commas-to-number.js │ ├── debounce.js │ ├── empty-number.js │ ├── get-value.js │ ├── make-date.js │ ├── make-number.js │ ├── random-number.js │ ├── scroll-top-on-change.js │ ├── set-share-denomination.js │ ├── share-denomination-label.js │ └── should-component-update-pure.js └── test ├── assertions ├── active-view.js ├── auth-form.js ├── chat.js ├── common │ ├── component-nav.js │ ├── formatted-date.js │ ├── formatted-number.js │ ├── initial-fair-prices.js │ ├── link.js │ ├── market-link.js │ └── nav-item.js ├── core-stats.js ├── create-market-form.js ├── favorite-markets.js ├── filter-sort.js ├── is-transactions-working.js ├── keywords.js ├── links.js ├── login-account-markets.js ├── login-account-positions.js ├── login-account-reports.js ├── login-account.js ├── market-data-age.js ├── market-data-nav-items.js ├── market-data-updater.js ├── market-reporting-nav-items.js ├── market-user-data-nav-items.js ├── market.js ├── markets-header.js ├── markets-totals.js ├── markets.js ├── my-markets-summary.js ├── my-markets.js ├── my-reports-summary.js ├── my-reports.js ├── order-cancellation.js ├── outcome-trade-nav-items.js ├── pagination.js ├── portfolio-nav-items.js ├── portfolio-summaries.js ├── portfolio-totals.js ├── portfolio.js ├── positions-markets.js ├── positions-summary.js ├── reportable-outcomes.js ├── scalar-share-denomination.js ├── search-sort.js ├── selected-outcome.js ├── selected-user-open-orders-group.js ├── settings.js ├── site-header.js ├── tags.js ├── trade-commit-lock.js ├── transactions-totals.js ├── transactions.js └── url.js ├── mocha.opts └── selectors-test.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "test": { 4 | "presets": ["es2015", "stage-0", "react"] 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # AURC Editor Configuration 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | end_of_line = lf 7 | trim_trailing_whitespace = true 8 | insert_final_newline = true 9 | indent_style = tab 10 | tab_width = 2 11 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | .git 2 | build 3 | node_modules 4 | test 5 | scratch 6 | src/styles.less 7 | src/dummy.js 8 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true 4 | }, 5 | "extends": ["eslint:recommended", "plugin:react/recommended", "airbnb"], 6 | "parser": "babel-eslint", 7 | "parserOptions": { 8 | "ecmaFeatures": { 9 | "jsx": true 10 | } 11 | }, 12 | "plugins": [ 13 | "react" 14 | ], 15 | "rules": { # 0 = disabled, 1 = warn, 2 = error 16 | # Disabled 17 | "comma-dangle": 0, 18 | "no-eq-null": 0, 19 | "no-console": 0, 20 | "no-tabs": 0, 21 | "consistent-return": 0, 22 | "global-require": 0, 23 | "no-use-before-define": 0, 24 | "max-len": 0, 25 | "no-shadow": 0, 26 | "padded-blocks": 0, 27 | "react/no-string-refs": 0, // NOTE -- Temporarily disabled -- utilization of string refs should be refactored to utilize state 28 | "react/no-unused-prop-types": 0, // NOTE -- Temporarily disabled -- all passed props should be specific, utilized, and verified 29 | "react/forbid-prop-types": 0, // NOTE -- TODO: Temporarily disabled...all props need to be specific + valid + will remove the necessity for separate 'shape' tests once merged into Augur 30 | # Errors 31 | "eqeqeq": [2, "allow-null"], 32 | "indent": [2, "tab", { "SwitchCase": 1 }], 33 | "no-unused-expressions": [2, { "allowShortCircuit": true }], 34 | "no-unused-vars": [2, { "vars": "all", "args": "none" }], 35 | "no-param-reassign": [2, { "props": false }], 36 | "no-underscore-dangle": [2, { "allow": ["_id"] }], 37 | "react/jsx-indent": [2, "tab"], 38 | "react/jsx-indent-props": [2, "tab"], 39 | "no-plusplus": [2, { "allowForLoopAfterthoughts": true }], 40 | "no-useless-rename": 2, 41 | "quotes": [2, "single", { "avoidEscape": true, "allowTemplateLiterals": true}] 42 | }, 43 | "settings": { 44 | "import/resolver": { 45 | "node": { 46 | extensions: [ 47 | "", 48 | ".js", 49 | ".jsx" 50 | ], 51 | "moduleDirectory": [ 52 | "node_modules", 53 | "src" # prevents linting issues w/ aliased paths 54 | ] 55 | } 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /demo 2 | 3 | # Logs 4 | logs 5 | *.log 6 | npm-debug.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | 13 | # Directory for instrumented libs generated by jscoverage/JSCover 14 | lib-cov 15 | 16 | # Coverage directory used by tools like istanbul 17 | coverage 18 | 19 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 20 | .grunt 21 | 22 | # node-waf configuration 23 | .lock-wscript 24 | 25 | # Compiled binary addons (http://nodejs.org/api/addons.html) 26 | build/Release 27 | 28 | # Dependency directory 29 | node_modules 30 | 31 | # Optional npm cache directory 32 | .npm 33 | 34 | # Optional REPL history 35 | .node_repl_history 36 | 37 | # IDEs 38 | .idea 39 | *.iml -------------------------------------------------------------------------------- /.stylelintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "stylelint-config-standard", 3 | "rules": { 4 | "indentation": "tab", 5 | "color-hex-length": "long", 6 | "declaration-block-properties-order": "alphabetical", 7 | "function-url-quotes": "always", 8 | "property-no-vendor-prefix": true, 9 | "value-no-vendor-prefix": true, 10 | "declaration-block-no-duplicate-properties": true, 11 | "no-duplicate-selectors": true, 12 | "no-browser-hacks": true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | 3 | language: node_js 4 | 5 | env: 6 | - CXX=g++-4.8 7 | 8 | node_js: 9 | - "6" 10 | - "5" 11 | - "4" 12 | 13 | addons: 14 | apt: 15 | sources: 16 | - ubuntu-toolchain-r-test 17 | packages: 18 | - gcc-4.8 19 | - g++-4.8 20 | 21 | before_script: 22 | - npm install 23 | 24 | script: 25 | - npm run lint 26 | - npm run test 27 | - npm run coverage 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # augur-ui-react-components 2 | [![Build Status](https://travis-ci.org/AugurProject/augur-ui-react-components.svg?branch=master)](https://travis-ci.org/AugurProject/augur-ui-react-components) 3 | [![Coverage Status](https://coveralls.io/repos/github/AugurProject/augur-ui-react-components/badge.svg?branch=master)](https://coveralls.io/github/AugurProject/augur-ui-react-components?branch=master) 4 | 5 | ## Documentation 6 | [Conventions](docs/conventions.md) 7 | -------------------------------------------------------------------------------- /browserslist: -------------------------------------------------------------------------------- 1 | # Officially Supported Browsers 2 | # NOTE -- referenced by `autoprefixer` during build 3 | 4 | last 2 Chrome versions 5 | last 2 Firefox versions 6 | last 2 Safari versions 7 | last 1 Edge versions 8 | last 2 iOS versions 9 | last 2 Android versions 10 | last 2 ChromeAndroid versions -------------------------------------------------------------------------------- /build/assets/fonts/font-awesome.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinybike/augur-ui-react-components/742bdb50af36d36045678a2610d4b68e44638db6/build/assets/fonts/font-awesome.woff -------------------------------------------------------------------------------- /build/assets/fonts/source-sans-pro-extra-light.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinybike/augur-ui-react-components/742bdb50af36d36045678a2610d4b68e44638db6/build/assets/fonts/source-sans-pro-extra-light.woff -------------------------------------------------------------------------------- /build/assets/fonts/source-sans-pro-light.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinybike/augur-ui-react-components/742bdb50af36d36045678a2610d4b68e44638db6/build/assets/fonts/source-sans-pro-light.woff -------------------------------------------------------------------------------- /build/assets/fonts/source-sans-pro-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinybike/augur-ui-react-components/742bdb50af36d36045678a2610d4b68e44638db6/build/assets/fonts/source-sans-pro-regular.woff -------------------------------------------------------------------------------- /build/assets/images/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinybike/augur-ui-react-components/742bdb50af36d36045678a2610d4b68e44638db6/build/assets/images/android-chrome-192x192.png -------------------------------------------------------------------------------- /build/assets/images/apple-touch-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinybike/augur-ui-react-components/742bdb50af36d36045678a2610d4b68e44638db6/build/assets/images/apple-touch-icon-152x152.png -------------------------------------------------------------------------------- /build/assets/images/apple-touch-icon-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinybike/augur-ui-react-components/742bdb50af36d36045678a2610d4b68e44638db6/build/assets/images/apple-touch-icon-180x180.png -------------------------------------------------------------------------------- /build/assets/images/augur-tile-large.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinybike/augur-ui-react-components/742bdb50af36d36045678a2610d4b68e44638db6/build/assets/images/augur-tile-large.png -------------------------------------------------------------------------------- /build/assets/images/augur-tile-medium.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinybike/augur-ui-react-components/742bdb50af36d36045678a2610d4b68e44638db6/build/assets/images/augur-tile-medium.png -------------------------------------------------------------------------------- /build/assets/images/augur-tile-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinybike/augur-ui-react-components/742bdb50af36d36045678a2610d4b68e44638db6/build/assets/images/augur-tile-small.png -------------------------------------------------------------------------------- /build/assets/images/augur-tile-wide.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinybike/augur-ui-react-components/742bdb50af36d36045678a2610d4b68e44638db6/build/assets/images/augur-tile-wide.png -------------------------------------------------------------------------------- /build/assets/images/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinybike/augur-ui-react-components/742bdb50af36d36045678a2610d4b68e44638db6/build/assets/images/favicon-16x16.png -------------------------------------------------------------------------------- /build/assets/images/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinybike/augur-ui-react-components/742bdb50af36d36045678a2610d4b68e44638db6/build/assets/images/favicon-32x32.png -------------------------------------------------------------------------------- /build/assets/images/safari-pinned-tab.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | Created by potrace 1.11, written by Peter Selinger 2001-2013 9 | 10 | 12 | 16 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /firebase.json: -------------------------------------------------------------------------------- 1 | { 2 | "firebase": "augur", 3 | "public": "./demo", 4 | "ignore": [ 5 | "firebase.json", 6 | "**/.*", 7 | "**/node_modules/**" 8 | ], 9 | "rewrites": [ 10 | { 11 | "source": "**", 12 | "destination": "/index.html" 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /hooks/pre-push.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #you can bypass this hook by `git commit --no-verify` 4 | 5 | set -e #exit immediately on `exit status > 0` of any command 6 | set -o pipefail #exit immediately on `exit status > 0` for pipes 7 | 8 | npm run lint --silent 9 | npm run test --silent -- --reporter min 10 | -------------------------------------------------------------------------------- /src/assets/fonts/font-awesome.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinybike/augur-ui-react-components/742bdb50af36d36045678a2610d4b68e44638db6/src/assets/fonts/font-awesome.woff -------------------------------------------------------------------------------- /src/assets/fonts/source-sans-pro-extra-light.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinybike/augur-ui-react-components/742bdb50af36d36045678a2610d4b68e44638db6/src/assets/fonts/source-sans-pro-extra-light.woff -------------------------------------------------------------------------------- /src/assets/fonts/source-sans-pro-light.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinybike/augur-ui-react-components/742bdb50af36d36045678a2610d4b68e44638db6/src/assets/fonts/source-sans-pro-light.woff -------------------------------------------------------------------------------- /src/assets/fonts/source-sans-pro-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinybike/augur-ui-react-components/742bdb50af36d36045678a2610d4b68e44638db6/src/assets/fonts/source-sans-pro-regular.woff -------------------------------------------------------------------------------- /src/assets/images/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinybike/augur-ui-react-components/742bdb50af36d36045678a2610d4b68e44638db6/src/assets/images/android-chrome-192x192.png -------------------------------------------------------------------------------- /src/assets/images/apple-touch-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinybike/augur-ui-react-components/742bdb50af36d36045678a2610d4b68e44638db6/src/assets/images/apple-touch-icon-152x152.png -------------------------------------------------------------------------------- /src/assets/images/apple-touch-icon-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinybike/augur-ui-react-components/742bdb50af36d36045678a2610d4b68e44638db6/src/assets/images/apple-touch-icon-180x180.png -------------------------------------------------------------------------------- /src/assets/images/augur-tile-large.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinybike/augur-ui-react-components/742bdb50af36d36045678a2610d4b68e44638db6/src/assets/images/augur-tile-large.png -------------------------------------------------------------------------------- /src/assets/images/augur-tile-medium.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinybike/augur-ui-react-components/742bdb50af36d36045678a2610d4b68e44638db6/src/assets/images/augur-tile-medium.png -------------------------------------------------------------------------------- /src/assets/images/augur-tile-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinybike/augur-ui-react-components/742bdb50af36d36045678a2610d4b68e44638db6/src/assets/images/augur-tile-small.png -------------------------------------------------------------------------------- /src/assets/images/augur-tile-wide.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinybike/augur-ui-react-components/742bdb50af36d36045678a2610d4b68e44638db6/src/assets/images/augur-tile-wide.png -------------------------------------------------------------------------------- /src/assets/images/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinybike/augur-ui-react-components/742bdb50af36d36045678a2610d4b68e44638db6/src/assets/images/favicon-16x16.png -------------------------------------------------------------------------------- /src/assets/images/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinybike/augur-ui-react-components/742bdb50af36d36045678a2610d4b68e44638db6/src/assets/images/favicon-32x32.png -------------------------------------------------------------------------------- /src/assets/images/safari-pinned-tab.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | Created by potrace 1.11, written by Peter Selinger 2001-2013 9 | 10 | 12 | 16 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /src/components.jsx: -------------------------------------------------------------------------------- 1 | import App from 'modules/app/components/app'; 2 | import * as VIEWS from 'modules/app/constants/views'; 3 | import * as AUTH_TYPES from 'modules/auth/constants/auth-types'; 4 | import * as TRANSACTION_TYPES from 'modules/transactions/constants/types'; 5 | 6 | const constants = { 7 | VIEWS, 8 | AUTH_TYPES, 9 | TRANSACTION_TYPES 10 | }; 11 | 12 | const components = { 13 | App, 14 | constants 15 | }; 16 | export default components; 17 | 18 | // also adding this notation to allow for importing specific pieces: import { App } from '...'; 19 | export { 20 | App, 21 | constants 22 | }; 23 | -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import { App } from './components'; 2 | import selectors from './selectors'; 3 | 4 | const appElement = document.getElementById('app'); 5 | 6 | window.selectors = selectors; 7 | console.log('********************************************* \n DEVELOPMENT MODE \n window.selectors available \n ********************************************* \n'); 8 | 9 | selectors.render = () => App(appElement, selectors); // eslint-disable-line new-cap 10 | selectors.render(); 11 | -------------------------------------------------------------------------------- /src/modules/app/components/core-stats.jsx: -------------------------------------------------------------------------------- 1 | import React, { PropTypes } from 'react'; 2 | import ValueDenomination from 'modules/common/components/value-denomination'; 3 | 4 | const CoreStats = p => ( 5 |
6 | {p.coreStats && p.coreStats.map((statGroup, i) => ( 7 |
11 | {Object.keys(p.coreStats[i]).map(stat => ( 12 |
16 | 20 | {p.coreStats[i][stat].label}: 21 | 22 | {p.coreStats[i][stat].value && p.coreStats[i][stat].value.value ? 23 | : 27 | 28 | } 29 | 30 |
31 | ))} 32 |
33 | ))} 34 |
35 | ); 36 | 37 | CoreStats.propTypes = { 38 | coreStats: PropTypes.array 39 | }; 40 | 41 | export default CoreStats; 42 | -------------------------------------------------------------------------------- /src/modules/app/components/header.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component, PropTypes } from 'react'; 2 | 3 | import Nav from 'modules/app/components/nav'; 4 | 5 | import debounce from 'utils/debounce'; 6 | 7 | export default class Header extends Component { 8 | constructor(props) { 9 | super(props); 10 | 11 | this.state = { 12 | headerHeight: 0 13 | }; 14 | 15 | this.setHeaderHeight = debounce(this.setHeaderHeight.bind(this)); 16 | } 17 | 18 | componentDidMount() { 19 | this.setHeaderHeight(); 20 | window.addEventListener('resize', this.setHeaderHeight); 21 | } 22 | 23 | componentDidUpdate(pP, pS) { 24 | if (pS.headerHeight !== this.state.headerHeight && this.props.updateHeaderHeight) { 25 | this.props.updateHeaderHeight(this.state.headerHeight); 26 | } 27 | } 28 | 29 | setHeaderHeight() { 30 | const headerHeight = this.navRef.offsetHeight; 31 | 32 | this.setState({ headerHeight }); 33 | } 34 | 35 | render() { 36 | const p = this.props; 37 | 38 | return ( 39 |
40 |
46 | ); 47 | } 48 | } 49 | 50 | Header.propTypes = { 51 | updateHeaderHeight: PropTypes.func 52 | }; 53 | -------------------------------------------------------------------------------- /src/modules/app/components/side-bar.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import Checkbox from 'modules/common/components/checkbox'; 4 | import NullStateMessage from 'modules/common/components/null-state-message'; 5 | 6 | const SideBar = (p) => { 7 | const nullMessage = 'No Tags Available'; 8 | 9 | return ( 10 | 32 | ); 33 | }; 34 | 35 | export default SideBar; 36 | 37 | 38 | // TODO -- Prop Validations 39 | // SideBar.propTypes = { 40 | // filters: React.PropTypes.array 41 | // }; 42 | -------------------------------------------------------------------------------- /src/modules/app/constants/views.js: -------------------------------------------------------------------------------- 1 | // Main Views 2 | export const DEFAULT_PAGE = MARKETS; 3 | export const MARKETS = 'markets'; 4 | export const MAKE = 'make'; 5 | export const TRANSACTIONS = 'transactions'; 6 | export const M = 'm'; 7 | export const ACCOUNT = 'account'; 8 | export const LOGIN_MESSAGE = 'login-message'; 9 | 10 | // Internal Navigation 11 | export const MY_POSITIONS = 'my-positions'; 12 | export const MY_MARKETS = 'my-markets'; 13 | export const MY_REPORTS = 'my-reports'; 14 | export const MARKET_DATA_NAV_OUTCOMES = 'outcomes'; 15 | export const MARKET_DATA_ORDERS = 'orders'; 16 | export const MARKET_DATA_NAV_CHARTS = 'charts'; 17 | export const MARKET_DATA_NAV_DETAILS = 'details'; 18 | export const MARKET_USER_DATA_NAV_POSITIONS = 'positions'; 19 | export const MARKET_USER_DATA_NAV_OPEN_ORDERS = 'open-orders'; 20 | export const MARKET_REPORTING_NAV_REPORT = 'report'; 21 | export const MARKET_REPORTING_NAV_DETAILS = 'details'; 22 | -------------------------------------------------------------------------------- /src/modules/app/less/animations.less: -------------------------------------------------------------------------------- 1 | // ANIMATIONS 2 | // shared animations 3 | // all mixins are pre-pended with `animation` 4 | // animations are assumed to be infinitely looped 5 | // appended `-` denotes finite iteration 6 | 7 | // Default Animation Values 8 | @animation-speed-slow: 700ms; 9 | @animation-speed-normal: 500ms; 10 | @animation-speed-fast: 300ms; 11 | @animation-speed-very-fast: 200ms; 12 | 13 | @animation-direction-up: 'up'; 14 | @animation-direction-right: 'right'; 15 | @animation-direction-down: 'down'; 16 | @animation-direction-left: 'left'; 17 | 18 | @animation-default-type: ease-in-out; 19 | 20 | // Notifications 21 | .animation-flash-slow(@color) { 22 | .animation(flash-slow @animation-speed-slow @animation-default-type infinite alternate); 23 | 24 | .keyframes(flash-slow, { 25 | 0% { background: fade(@color, @amount-subtle) } 26 | 100% { background: fade(@color, @amount-light) } 27 | }); 28 | } 29 | 30 | // Transitions 31 | // Don't pass `all`. Can potentially cause performance issues. 32 | // Instead, pass a comma separated list of property/timing/easing to watch for changes with a `;` at the end 33 | .transition(...) { 34 | transition: @arguments; 35 | } 36 | 37 | // Helpers 38 | .animation(@args) { 39 | animation: @args; 40 | } 41 | 42 | .keyframes(@name; @args) { 43 | @keyframes @name { @args(); } 44 | } 45 | -------------------------------------------------------------------------------- /src/modules/app/less/app.less: -------------------------------------------------------------------------------- 1 | #main_responsive_state { 2 | @media @breakpoint-mobile { 3 | & { 4 | will-change: contents; // This gets read in app.jsx on mount + reset to auto 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/modules/app/less/arrangement.less: -------------------------------------------------------------------------------- 1 | // ARRANGEMENT 2 | // styles for the layering of the elements 3 | 4 | // Vars 5 | // these are intended for use with `z-index` 6 | // so will ultimately be applied within the respective stacking context. 7 | 8 | // Above Content 9 | @above-all-content: 1000; 10 | 11 | // Masking 12 | @mask: 2000; 13 | @mask-above: 3000; 14 | -------------------------------------------------------------------------------- /src/modules/app/less/borders.less: -------------------------------------------------------------------------------- 1 | // BORDERS 2 | // Constants 3 | // Defaults 4 | @border-all: 'all sides'; 5 | @border-default-chroma: @border-muted; 6 | @border-default-width: 1px; 7 | 8 | // Sides 9 | @border-top: border-top; 10 | @border-right: border-right; 11 | @border-bottom: border-bottom; 12 | @border-left: border-left; 13 | 14 | // Chroma 15 | @border-muted: @color-border-muted; 16 | @border-light: @color-border-light; 17 | 18 | // Width 19 | @border-width-2: 2px; 20 | @border-width-3: 3px; 21 | 22 | .border(@side: false; @property: @border-all; @chroma: @border-default-chroma; @width: @border-default-width) { 23 | & when (@side) { 24 | & when (@property = @border-all) { 25 | border: @width solid @chroma; 26 | } 27 | 28 | @{property}: @width solid @chroma; 29 | } 30 | 31 | & when not (@side) { 32 | border: none; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/modules/app/less/box-shadow.less: -------------------------------------------------------------------------------- 1 | // TODO -- there are a few occurances of box shadow 2 | // For consistency, need to build up a mixin 3 | -------------------------------------------------------------------------------- /src/modules/app/less/core-stats.less: -------------------------------------------------------------------------------- 1 | .core-stats { 2 | 3 | .border(true, @border-right); 4 | .border(true, @border-bottom); 5 | .border(true, @border-left); 6 | 7 | background-color: @color-white; 8 | box-shadow: 0 0 5px 1px rgba(0, 0, 0, 0.2); 9 | display: flex; 10 | flex: 1; 11 | flex-wrap: wrap; 12 | justify-content: space-around; 13 | 14 | .core-stats-group { 15 | align-items: center; 16 | display: flex; 17 | flex: 1; 18 | justify-content: center; 19 | margin: 0 1em; 20 | 21 | &:first-child { 22 | justify-content: flex-start; 23 | } 24 | 25 | &:last-child { 26 | justify-content: flex-end; 27 | } 28 | 29 | @media @breakpoint-mobile { 30 | &:first-child, 31 | &:last-child { 32 | justify-content: center; 33 | } 34 | } 35 | 36 | .core-stat { 37 | padding: 1em; 38 | 39 | .core-stat-label { 40 | margin-right: 0.4em; 41 | white-space: nowrap; 42 | } 43 | 44 | .core-stat-value { 45 | .font-weight-normal(); 46 | } 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/modules/app/less/footer.less: -------------------------------------------------------------------------------- 1 | footer { 2 | 3 | .border(true, @border-top); 4 | .transition(bottom @animation-speed-very-fast); 5 | 6 | background-color: @color-footer-background; 7 | display: flex; 8 | width: 100vw; 9 | z-index: @mask-above; 10 | 11 | @media @breakpoint-mobile { 12 | 13 | .border(false); 14 | 15 | background-color: transparent; 16 | flex-direction: column; 17 | position: fixed; 18 | } 19 | 20 | .nav-toggler { 21 | align-self: center; // Mobile Safari bugfix 22 | display: none; 23 | flex: 1; 24 | justify-content: center; 25 | 26 | @media @breakpoint-mobile { 27 | display: flex; 28 | } 29 | 30 | .nav-toggler-button { 31 | 32 | .font-color-light(); 33 | 34 | background-color: @color-nav-background; 35 | border-radius: 1.75em 1.75em 0 0; 36 | height: 1.75em; 37 | position: relative; 38 | top: 0.3em; 39 | width: 3.5em; 40 | 41 | i { 42 | .font-size-large(); 43 | } 44 | } 45 | } 46 | 47 | #footer_content { 48 | 49 | .contained(); 50 | .font-size-medium(); 51 | 52 | display: flex; 53 | justify-content: center; 54 | 55 | @media @breakpoint-mobile { 56 | 57 | .font-color-light; 58 | 59 | background-color: @color-nav-background; 60 | margin: 0; 61 | } 62 | 63 | .link { 64 | padding: 1.5em; 65 | 66 | &:hover, 67 | &:active, 68 | &:focus { 69 | text-decoration: underline; 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/modules/app/less/header.less: -------------------------------------------------------------------------------- 1 | .app-header { 2 | 3 | .font-size-medium(); 4 | .font-weight-extra-light(); 5 | 6 | background: @color-nav-background; 7 | color: @color-text-light-muted; 8 | } 9 | -------------------------------------------------------------------------------- /src/modules/app/less/responsive.less: -------------------------------------------------------------------------------- 1 | // RESPONSIVE 2 | // These are determined largely by the content being displayed NOT the device displaying the content. 3 | // This allows for the most optimal presentation regardless of the device. 4 | 5 | // Maximum app width 6 | // .contained elements will max at this width, elements without that style will flow to full window width 7 | @max-app-width: 1800px; 8 | 9 | // Raw Break Points 10 | // The breakpoints encompass: 11 | // Steps (1, 2, etc.) -- Account for large structural view reflows that may need to occur (Ascending in px) 12 | // Sub-Steps (1-1, 2-1, etc.) -- Account for fine styling adjustments between steps (Descending in px) 13 | 14 | // STEP 1 15 | // Smallest layout @ < 600px 16 | // Step 17 | @step-1: 600px; 18 | // Rules 19 | @breakpoint-1: ~"all and (max-width: @{step-1})"; 20 | 21 | // STEP 2 22 | // Medium layout @ > 600px && <= 1200px 23 | // Steps 24 | @step-2: 1200px; 25 | // Sub-Steps 26 | @step-2-1: 1050px; 27 | @step-2-2: 900px; // Mobile tipping point 28 | @step-2-3: 750px; 29 | // Rules 30 | @breakpoint-2: ~"all and (min-width: @{step-1}) and (max-width: @{step-2})"; 31 | @breakpoint-2-1: ~"all and (min-width: @{step-1}) and (max-width: @{step-2-1})"; 32 | @breakpoint-2-2: ~"all and (min-width: @{step-1}) and (max-width: @{step-2-2})"; // Mobile tipping point 33 | @breakpoint-2-3: ~"all and (min-width: @{step-1}) and (max-width: @{step-2-3})"; 34 | 35 | // STEP 3 36 | // Full layout @ > 1200px 37 | // Step 38 | // Explicit declaration of step not necessary here 39 | // Rules 40 | @breakpoint-3: ~"all and (min-width: @{step-2})"; 41 | 42 | // Helper Breakpoints 43 | // Mobile (up to step-2-2) 44 | @breakpoint-mobile: ~"all and (max-width: @{step-2-2})"; 45 | -------------------------------------------------------------------------------- /src/modules/app/less/side-bar.less: -------------------------------------------------------------------------------- 1 | // NOTE -- additional styles located in app/less/layout.less 2 | .side-bar { 3 | 4 | .transition(bottom @animation-speed-very-fast); 5 | 6 | background-color: @color-side-bar-background; 7 | color: @color-text-light-muted; 8 | flex: 1; 9 | 10 | @media @breakpoint-mobile { 11 | overflow-y: auto; 12 | position: fixed; 13 | } 14 | 15 | footer { 16 | display: none; 17 | 18 | @media @breakpoint-mobile { 19 | display: flex; 20 | visibility: hidden; 21 | } 22 | } 23 | 24 | h3 { 25 | 26 | .border(true, @border-bottom); 27 | .font-weight-light(); 28 | .font-size-medium(); 29 | 30 | color: @color-text-light; 31 | margin: 0 2rem; 32 | padding: 1rem 0; 33 | } 34 | 35 | .tags { 36 | display: flex; 37 | flex: 1; 38 | flex-direction: column; 39 | padding: 0.5rem 0; 40 | 41 | .null-state { 42 | align-self: center; 43 | position: fixed; // Simply for the case where tags are failing to load, scrolling won't cause this to go out of view 44 | } 45 | 46 | .checkbox.tag { 47 | 48 | .transition(background-color @animation-speed-very-fast, color @animation-speed-very-fast;); 49 | 50 | padding: 1em 2rem; 51 | text-align: left; 52 | 53 | &:hover, 54 | &.checked { 55 | background-color: @color-side-bar-background-active; 56 | color: @color-text-dark; 57 | } 58 | 59 | .checkbox-box { 60 | display: none; 61 | } 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/modules/app/less/tables.less: -------------------------------------------------------------------------------- 1 | // TABLES 2 | // Styles + mixins for the display of tables 3 | 4 | .table-cell-spacing { 5 | padding: 0.8em 0; 6 | 7 | @media @breakpoint-mobile { 8 | padding: 1.5em 0; 9 | } 10 | } 11 | 12 | .table { 13 | display: flex; 14 | flex-direction: column; 15 | 16 | .value-denomination, 17 | .value-date { 18 | &, 19 | * { 20 | 21 | .font-weight-extra-light(); 22 | } 23 | 24 | &.emphasized { 25 | * { 26 | 27 | .font-weight-normal(); 28 | } 29 | } 30 | } 31 | } 32 | 33 | .table-header { 34 | display: flex; 35 | flex: 1; 36 | 37 | .font-weight-normal(); 38 | 39 | & > * { 40 | 41 | .table-cell-spacing(); 42 | } 43 | } 44 | 45 | .table-row { 46 | 47 | .border(true, @border-top, @border-light); 48 | 49 | display: flex; 50 | flex: 1; 51 | 52 | & > * { 53 | 54 | .table-cell-spacing(); 55 | 56 | &:not(:first-child) { 57 | .border(true, @border-left, @border-light); 58 | } 59 | } 60 | 61 | &.selected { 62 | 63 | .border(true, @border-top, @color-blue-light); 64 | .border(true, @border-right, @color-blue-light); 65 | .border(true, @border-bottom, @color-blue-light); 66 | .border(true, @border-left, @color-blue, @border-width-3); 67 | 68 | background-color: @color-blue-extra-light; 69 | } 70 | 71 | &:hover, 72 | &:active { 73 | background-color: @color-blue-extra-light; 74 | } 75 | 76 | &.not-selectable:hover { 77 | background-color: @color-gray-light; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/modules/app/less/view-header.less: -------------------------------------------------------------------------------- 1 | // NOTE -- additional styles located in common/less/layout.less 2 | .view-header { 3 | 4 | .font-size-medium(); 5 | 6 | color: @color-text-dark; 7 | display: flex; 8 | flex-wrap: wrap-reverse; 9 | 10 | .view-header-group { 11 | display: flex; 12 | flex: 1; 13 | justify-content: flex-start; 14 | margin: 0 1em 1em 0; 15 | } 16 | 17 | .view-header-group:not(:first-child) { 18 | display: flex; 19 | flex: 1; 20 | justify-content: flex-end; 21 | } 22 | 23 | .view-header-group:last-child { 24 | margin: 0 0 1em; 25 | } 26 | 27 | h2 { 28 | 29 | .font-size-extra-large(); 30 | .font-weight-normal(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/modules/auth/components/auth-view.jsx: -------------------------------------------------------------------------------- 1 | import React, { PropTypes } from 'react'; 2 | import classnames from 'classnames'; 3 | import AuthForm from 'modules/auth/components/auth-form'; 4 | import Link from 'modules/link/components/link'; 5 | 6 | class AuthPage extends React.Component { 7 | componentDidMount() { 8 | this.props.authForm.airbitzOnLoad.onLoad(); 9 | } 10 | 11 | render() { 12 | const p = this.props; 13 | return ( 14 |
15 |
16 | Augur is a completely decentralized system including user accounts. 17 | Your credentials never leave the browser, and you are responsible for keeping them safe. 18 |
19 | 20 | 21 | It is impossible to recover your account if your credentials get lost! 22 | 23 |
24 | Click  25 | 29 | {p.authForm.airbitzLinkText} 30 | 31 |  to create an encrypted and backed up account using a simple username and password. 32 |
33 | 34 |
35 | ); 36 | } 37 | } 38 | 39 | AuthPage.propTypes = { 40 | className: PropTypes.string, 41 | authForm: PropTypes.object 42 | }; 43 | 44 | export default AuthPage; 45 | -------------------------------------------------------------------------------- /src/modules/auth/constants/auth-types.js: -------------------------------------------------------------------------------- 1 | export const REGISTER = 'register'; 2 | export const LOGIN = 'login'; 3 | export const LOGOUT = 'logout'; 4 | export const IMPORT = 'import'; 5 | export const FUND_ACCOUNT = 'fund_account'; 6 | 7 | export const AUTH_TYPES = { 8 | [REGISTER]: REGISTER, 9 | [LOGIN]: LOGIN, 10 | [IMPORT]: IMPORT, 11 | [LOGOUT]: LOGOUT 12 | }; 13 | 14 | export const DEFAULT_AUTH_TYPE = REGISTER; 15 | -------------------------------------------------------------------------------- /src/modules/bids-asks/components/bids-asks.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import OrderBook from 'modules/bids-asks/components/order-book'; 3 | 4 | const BidsAsks = p => ( 5 |
6 | { 7 | p.market.outcomes.map(outcome => 8 | ( 9 | 15 | ) 16 | ) 17 | } 18 |
19 | ); 20 | 21 | // TODO -- Prop Validations 22 | // BidsAsks.propTypes = { 23 | // market: PropTypes.object 24 | // }; 25 | 26 | export default BidsAsks; 27 | -------------------------------------------------------------------------------- /src/modules/bids-asks/components/order-book.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ValueDenomination from 'modules/common/components/value-denomination'; 3 | 4 | const OrderBook = p => ( 5 |
6 |
7 | {p.bids.map((bid, i) => { 8 | if (i !== 0) { 9 | return ( 10 |
11 | 12 | 13 |
14 | ); 15 | } 16 | return null; 17 | })} 18 | {!p.bids.length && 19 |
20 | 21 | 22 |
23 | } 24 |
25 |
26 | {p.asks.map((ask, i) => { 27 | if (i !== 0) { 28 | return ( 29 |
30 | 31 | 32 |
33 | ); 34 | } 35 | return null; 36 | })} 37 | {!p.asks.length && 38 |
39 | 40 | 41 |
42 | } 43 |
44 |
45 | ); 46 | 47 | // TODO -- Prop Validations 48 | // OrderBook.propTypes = { 49 | // outcome: PropTypes.object, 50 | // bids: PropTypes.array, 51 | // asks: PropTypes.array 52 | // }; 53 | 54 | export default OrderBook; 55 | -------------------------------------------------------------------------------- /src/modules/bids-asks/less/bids-asks.less: -------------------------------------------------------------------------------- 1 | .bids-asks { 2 | display: flex; 3 | flex-wrap: wrap; 4 | font-size: 1.7vmin; 5 | justify-content: center; 6 | padding: 0.5rem 0 3rem; 7 | text-align: center; 8 | 9 | .order-book { 10 | flex: 0 1; 11 | 12 | .order-book(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/modules/bids-asks/less/order-book.less: -------------------------------------------------------------------------------- 1 | .order-book() { 2 | background: white; 3 | border-radius: 1px; 4 | margin: 0.25rem; 5 | min-width: 400px; 6 | 7 | h5 { 8 | border-bottom: 1px solid @color-border; 9 | font-size: 1.3em; 10 | font-weight: 700; 11 | margin-bottom: 0.5em; 12 | text-align: center; 13 | text-transform: uppercase; 14 | 15 | .name-header { 16 | display: inline-block; 17 | } 18 | 19 | .bids-header { 20 | display: inline-block; 21 | font-size: 0.65em; 22 | font-weight: 400; 23 | padding-right: 2rem; 24 | text-align: right; 25 | } 26 | 27 | .asks-header { 28 | display: inline-block; 29 | font-size: 0.65em; 30 | font-weight: 400; 31 | padding-left: 2rem; 32 | text-align: left; 33 | } 34 | } 35 | 36 | .bids { 37 | border-right: 1px solid @color-border; 38 | display: inline-block; 39 | padding-right: 0.5em; 40 | text-align: right; 41 | vertical-align: top; 42 | 43 | .bid { 44 | .value-denomination.price { 45 | margin-left: 1em; 46 | } 47 | } 48 | } 49 | 50 | .asks { 51 | border-left: 1px solid @color-border; 52 | display: inline-block; 53 | padding-left: 0.5em; 54 | text-align: left; 55 | vertical-align: top; 56 | 57 | .ask { 58 | .value-denomination.price { 59 | margin-right: 1em; 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/modules/branch/components/branch.jsx: -------------------------------------------------------------------------------- 1 | import React, { PropTypes } from 'react'; 2 | import ReactTooltip from 'react-tooltip'; 3 | import { Line } from 'rc-progress'; 4 | 5 | import Bullet from 'modules/common/components/bullet'; 6 | 7 | const Branch = p => ( 8 |
9 | 14 | 15 | Reporting Cycle {p.reportPeriod} {Math.round(p.currentPeriodProgress)}% complete {p.phaseLabel} phase ends {p.phaseTimeRemaining} 16 | 17 | 23 | {p.description} {p.periodLength / 3600} hours per cycle 24 | 25 | 32 | 33 | Branch ID: {p.id} 34 | 35 | 36 |
37 | ); 38 | 39 | Branch.propTypes = { 40 | className: PropTypes.string, 41 | description: PropTypes.string, 42 | id: PropTypes.string, 43 | periodLength: PropTypes.number, 44 | phaseLabel: PropTypes.string, 45 | phaseTimeRemaining: PropTypes.string, 46 | currentPeriodProgress: PropTypes.number 47 | }; 48 | 49 | export default Branch; 50 | -------------------------------------------------------------------------------- /src/modules/branch/less/branch.less: -------------------------------------------------------------------------------- 1 | .branch-info { 2 | display: flex; 3 | flex-direction: column; 4 | 5 | & > *:first-child { 6 | margin-bottom: 0.5em; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/modules/chat/less/chat.less: -------------------------------------------------------------------------------- 1 | .chat { 2 | border-left: 1px solid #c8c8c8; 3 | border-right: 1px solid #c8c8c8; 4 | border-top: 1px solid #c8c8c8; 5 | bottom: 0; 6 | box-shadow: 5px 1px 0 0 rgba(0, 0, 0, 0.2); 7 | left: 0; 8 | position: fixed; 9 | width: 100%; 10 | z-index: 101; 11 | } 12 | 13 | .chat-inputs { 14 | width: 100%; 15 | } 16 | 17 | .chat-message-wrapper { 18 | border: 1px solid #000000; 19 | display: inline-block; 20 | width: 100%; 21 | } 22 | 23 | .close-chat-button { 24 | color: @color-nav-background !important; 25 | cursor: pointer; 26 | float: right; 27 | width: 100%; 28 | } 29 | 30 | .chat-message-input { 31 | border: 0; 32 | width: 80%; 33 | word-break: break-word; 34 | } 35 | 36 | .chat-message-button { 37 | background-color: @color-nav-background; 38 | border: 0; 39 | bottom: 0; 40 | min-width: 80px; 41 | position: fixed; 42 | right: 0; 43 | width: 20%; 44 | } 45 | 46 | // @media screen and (max-width: @media-mobile-width) { 47 | // .chat-message-input { 48 | // width: 100%; 49 | // } 50 | // 51 | // .chat-message-button { 52 | // clear: both; 53 | // position: relative; 54 | // width: 100%; 55 | // } 56 | // } 57 | 58 | #chatbox { 59 | background-color: #f9f9f9; 60 | height: 250px; 61 | overflow: auto; 62 | width: 100%; 63 | word-wrap: break-word; 64 | } 65 | 66 | #babble { 67 | font-family: 'Source Sans Pro', 'Helvetica Neue', Arial, 'Open Sans', sans-serif; 68 | font-size: 11pt; 69 | font-weight: 500; 70 | line-height: 18pt; 71 | padding: 10px; 72 | text-align: left; 73 | } 74 | 75 | #chat-button { 76 | background: @color-nav-background; 77 | border: 0; 78 | border-radius: 5px 5px 0 0; 79 | bottom: 0; 80 | color: #ffffff; 81 | cursor: pointer; 82 | font-size: 14px; 83 | margin: 0; 84 | padding: 10px 20px; 85 | position: fixed; 86 | right: 5%; 87 | visibility: visible !important; 88 | width: auto; 89 | z-index: 100; 90 | } 91 | 92 | #doorbell-button { 93 | left: 5% !important; 94 | } 95 | -------------------------------------------------------------------------------- /src/modules/common/components/bullet.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const Bullet = () => ·; 4 | 5 | export default Bullet; 6 | -------------------------------------------------------------------------------- /src/modules/common/components/checkbox.jsx: -------------------------------------------------------------------------------- 1 | import React, { PropTypes } from 'react'; 2 | import ReactTooltip from 'react-tooltip'; 3 | import classnames from 'classnames'; 4 | 5 | const Checkbox = p => ( 6 |
7 | 23 | 24 |
25 | ); 26 | 27 | Checkbox.propTypes = { 28 | className: PropTypes.string, 29 | title: PropTypes.string, 30 | text: PropTypes.string, 31 | text2: PropTypes.string, 32 | isChecked: PropTypes.bool, 33 | tabIndex: PropTypes.number, 34 | onClick: PropTypes.func 35 | }; 36 | 37 | export default Checkbox; 38 | -------------------------------------------------------------------------------- /src/modules/common/components/collapse.jsx: -------------------------------------------------------------------------------- 1 | // Provides collapsible wrapper (default is div) 2 | import React, { PropTypes } from 'react'; 3 | import classnames from 'classnames'; 4 | 5 | const Collapse = p => ( 6 |
7 | {p.children} 8 |
9 | ); 10 | 11 | Collapse.propTypes = { 12 | isOpen: PropTypes.bool, 13 | component: PropTypes.any, 14 | children: PropTypes.any 15 | }; 16 | 17 | export default Collapse; 18 | -------------------------------------------------------------------------------- /src/modules/common/components/component-nav.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import classNames from 'classnames'; 3 | 4 | import Link from 'modules/link/components/link'; 5 | 6 | const ComponentNav = p => ( 7 | 20 | ); 21 | 22 | export default ComponentNav; 23 | -------------------------------------------------------------------------------- /src/modules/common/components/datepicker.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Datetime from 'react-datetime'; 3 | 4 | const DatePicker = (p) => { 5 | const yesterday = Datetime.moment().subtract(1, 'day'); 6 | const valid = current => current.isAfter(yesterday); 7 | const defaultValue = p.endDate ? p.endDate : null; 8 | 9 | return ( 10 | p.onValuesUpdated({ endDate: new Date(date) })} 16 | open 17 | inputProps={{ placeholder: 'YYYY/MM/DD hh:mm:ss a' }} 18 | /> 19 | ); 20 | }; 21 | 22 | // TODO -- Prop Validations 23 | // DatePicker.propTypes = { 24 | // onValuesUpdated: PropTypes.func, 25 | // endDate: PropTypes.object 26 | // }; 27 | 28 | export default DatePicker; 29 | -------------------------------------------------------------------------------- /src/modules/common/components/dropdown.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const Dropdown = p => ( 4 |
5 | 18 | 19 |
20 | ); 21 | 22 | // TODO -- Prop Validations 23 | // Dropdown.propTypes = { 24 | // default: PropTypes.string, 25 | // options: PropTypes.array, 26 | // onChange: PropTypes.func 27 | // }; 28 | 29 | export default Dropdown; 30 | -------------------------------------------------------------------------------- /src/modules/common/components/em-dash.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const EmDash = () => ; 4 | 5 | export default EmDash; 6 | -------------------------------------------------------------------------------- /src/modules/common/components/null-state-message.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const NullStateMessage = p => ( 4 |
5 | {!p.message ? 6 | No Data Available : 7 | {p.message} 8 | } 9 |
10 | ); 11 | 12 | export default NullStateMessage; 13 | -------------------------------------------------------------------------------- /src/modules/common/components/side-bar-mask.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const SidebarMask = p => ( 4 |
8 | ); 9 | 10 | export default SidebarMask; 11 | -------------------------------------------------------------------------------- /src/modules/common/components/toggler.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import classnames from 'classnames'; 3 | 4 | const Toggler = p => ( 5 | 14 | ); 15 | 16 | const findNextOption = (selected, options) => { 17 | const currentSelectedIndex = options.indexOf(selected); 18 | let nextSelectedInex = currentSelectedIndex + 1; 19 | if (nextSelectedInex >= options.length) { 20 | nextSelectedInex = 0; 21 | } 22 | return options[nextSelectedInex]; 23 | }; 24 | 25 | // TODO -- Prop Validations 26 | // Toggler.propTypes = { 27 | // className: PropTypes.string, 28 | // selected: PropTypes.object, 29 | // options: PropTypes.array, 30 | // onClick: PropTypes.func 31 | // }; 32 | 33 | export default Toggler; 34 | -------------------------------------------------------------------------------- /src/modules/common/components/value-date.jsx: -------------------------------------------------------------------------------- 1 | import React, { PropTypes } from 'react'; 2 | import classnames from 'classnames'; 3 | 4 | const ValueDate = p => ( 5 | 6 | {p.formatted} 7 | 8 | ); 9 | 10 | ValueDate.propTypes = { 11 | className: PropTypes.string, 12 | value: PropTypes.object, 13 | formatted: PropTypes.string 14 | }; 15 | 16 | export default ValueDate; 17 | -------------------------------------------------------------------------------- /src/modules/common/components/value-denomination.jsx: -------------------------------------------------------------------------------- 1 | import React, { PropTypes } from 'react'; 2 | import ReactTooltip from 'react-tooltip'; 3 | import classnames from 'classnames'; 4 | 5 | import EmDash from 'modules/common/components/em-dash'; 6 | 7 | const ValueDenomination = p => ( 8 | 0, 11 | negative: p.formattedValue < 0 12 | })} 13 | > 14 | {p.prefix && 15 | {p.prefix} 16 | } 17 | {p.formatted && p.fullPrecision && 18 | 23 | {p.formatted} 24 | 25 | } 26 | {p.formatted && !p.fullPrecision && 27 | {p.formatted} 28 | } 29 | {p.denomination && 30 | {p.denomination} 31 | } 32 | {p.postfix && 33 | {p.postfix} 34 | } 35 | {!p.value && p.value !== 0 && !p.formatted && p.formatted !== '0' && // null/undefined state handler 36 | 37 | } 38 | 39 | 40 | ); 41 | 42 | ValueDenomination.propTypes = { 43 | className: PropTypes.string, 44 | value: PropTypes.number, 45 | formattedValue: PropTypes.number, 46 | formatted: PropTypes.string, 47 | fullPrecision: PropTypes.string, 48 | denomination: PropTypes.string, 49 | prefix: PropTypes.string, 50 | postfix: PropTypes.string 51 | }; 52 | 53 | export default ValueDenomination; 54 | -------------------------------------------------------------------------------- /src/modules/common/components/value-timestamp.jsx: -------------------------------------------------------------------------------- 1 | import React, { PropTypes } from 'react'; 2 | import classnames from 'classnames'; 3 | 4 | const ValueTimestamp = p => ( 5 | 6 | {p.full} 7 | 8 | ); 9 | 10 | ValueTimestamp.propTypes = { 11 | className: PropTypes.string, 12 | full: PropTypes.string 13 | }; 14 | 15 | export default ValueTimestamp; 16 | -------------------------------------------------------------------------------- /src/modules/common/less/checkbox.less: -------------------------------------------------------------------------------- 1 | .checkbox-container { 2 | display: flex; 3 | flex: 1; 4 | } 5 | 6 | .checkbox { 7 | cursor: default; 8 | flex: 1; 9 | 10 | &:disabled { 11 | opacity: 0.4; 12 | } 13 | 14 | &.checked { 15 | .checkbox-box::before { 16 | color: rgba(45, 45, 75, 1); 17 | content: '\f00c'; 18 | font-family: 'Font Awesome'; 19 | font-size: 1rem; 20 | font-weight: 500; 21 | left: 0; 22 | position: absolute; 23 | top: -0.2rem; 24 | } 25 | } 26 | 27 | .checkbox-box { 28 | 29 | .border(true); 30 | 31 | background: #fafafa; 32 | display: inline-block; 33 | height: 0.8rem; 34 | margin-right: 0.5rem; 35 | position: relative; 36 | vertical-align: middle; 37 | width: 0.8rem; 38 | } 39 | 40 | .checkbox-label, 41 | .checkbox-label2 { 42 | display: inline-block; 43 | margin-left: 0.25em; 44 | position: relative; 45 | vertical-align: middle; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/modules/common/less/component-nav.less: -------------------------------------------------------------------------------- 1 | .component-nav { 2 | 3 | .border(true, @border-bottom, @border-muted); 4 | 5 | display: flex; 6 | 7 | .link { 8 | cursor: default; 9 | 10 | &.mobile-only { 11 | display: none; 12 | 13 | @media @breakpoint-mobile { 14 | display: block; 15 | } 16 | } 17 | } 18 | 19 | li { 20 | margin: 0 1em -1px; // -1px pulls bottom `up` one pixel to stylistically overlap w/ component-nav bottom border 21 | padding: 1em 0 0.5em; 22 | 23 | // .transition(border-bottom @animation-speed-very-fast); // Not a great transition in testing...leaving for now 24 | 25 | &.selected { 26 | 27 | .border(true, @border-bottom, @color-purple, @border-width-3); 28 | } 29 | 30 | &:hover:not(.selected) { 31 | 32 | .border(true, @border-bottom, @color-purple, @border-width-2); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/modules/common/less/dropdown.less: -------------------------------------------------------------------------------- 1 | .dropdown { 2 | background-color: @color-white; 3 | border: 1px solid @color-border; 4 | display: flex; 5 | position: relative; 6 | 7 | select { 8 | appearance: none; 9 | background-color: transparent; 10 | border: none; 11 | padding: 1em 2.2em 1em 1em; 12 | } 13 | 14 | i { 15 | 16 | .font-size-medium(); 17 | 18 | cursor: default; 19 | pointer-events: none; 20 | position: absolute; 21 | right: 1em; 22 | top: 50%; 23 | transform: translateY(-50%); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/modules/common/less/input.less: -------------------------------------------------------------------------------- 1 | .input { 2 | .border(true); 3 | 4 | input { 5 | .border(false); 6 | } 7 | 8 | &.clearable { 9 | .box { 10 | padding-right: 2em; 11 | } 12 | } 13 | 14 | &.input-error { 15 | border-color: @color-red-light; 16 | } 17 | 18 | .box { 19 | font-size: inherit; 20 | height: 100%; 21 | padding: 0.5em; 22 | width: 100%; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/modules/common/less/null-state-message.less: -------------------------------------------------------------------------------- 1 | .null-state-message { 2 | 3 | .font-size-medium(); 4 | 5 | display: flex; 6 | flex: 1; 7 | justify-content: center; 8 | padding: 1em; 9 | } 10 | -------------------------------------------------------------------------------- /src/modules/common/less/page.less: -------------------------------------------------------------------------------- 1 | .page { 2 | display: flex; 3 | flex-direction: column; 4 | min-height: 100vh; 5 | } 6 | 7 | .page-header { 8 | background: @color-dark-hover; 9 | color: white; 10 | font-size: 3.4vmin; 11 | line-height: 2.2em; 12 | //margin-top: @site-header-height; 13 | padding: 3.5vmin 3rem 2.5vmin 2.9rem; 14 | 15 | .big-line { 16 | font-size: 1.3em; 17 | font-weight: 700; 18 | } 19 | } 20 | 21 | .page-content { 22 | color: @color-dark-active; 23 | flex: 1; 24 | padding: 0; 25 | } 26 | 27 | .site-header + .page-content { 28 | //margin-top: @site-header-height; 29 | } 30 | -------------------------------------------------------------------------------- /src/modules/common/less/panel-sideways.less: -------------------------------------------------------------------------------- 1 | .panel-sideways { 2 | background: fade(@color-plain-normal, 7%); 3 | 4 | .title { 5 | border: 1px solid @color-plain-normal; 6 | border-bottom: 0; 7 | border-left: 7px solid @color-plain-normal; 8 | color: black; 9 | font-size: 1.4rem; 10 | font-weight: 700; 11 | padding: 1.5rem 1rem 1rem; 12 | text-transform: uppercase; 13 | vertical-align: middle; 14 | } 15 | 16 | .content { 17 | border: 1px solid @color-border; 18 | border-left: 7px solid @color-plain-normal; 19 | border-top: 0; 20 | color: @color-dark-normal; 21 | font-size: 1.1rem; 22 | font-weight: 400; 23 | padding: 0.5rem 1rem 0.8rem; 24 | vertical-align: middle; 25 | } 26 | 27 | &.primary { 28 | background: fade(@color-primary-normal, 7%); 29 | 30 | .title, 31 | .content { 32 | border-color: fade(@color-primary-normal, 20%); 33 | border-left-color: @color-primary-normal; 34 | } 35 | } 36 | 37 | &.info { 38 | background: fade(@color-dark-normal, 7%); 39 | 40 | .title, 41 | .content { 42 | border-color: fade(@color-dark-normal, 20%); 43 | border-left-color: @color-dark-normal; 44 | } 45 | } 46 | 47 | &.success { 48 | background: fade(@color-success-normal, 7%); 49 | 50 | .title, 51 | .content { 52 | border-color: fade(@color-success-normal, 20%); 53 | border-left-color: @color-success-normal; 54 | } 55 | } 56 | 57 | &.warning { 58 | background: fade(@color-warning-normal, 7%); 59 | 60 | .title, 61 | .content { 62 | border-color: fade(@color-warning-normal, 20%); 63 | border-left-color: @color-warning-normal; 64 | } 65 | } 66 | 67 | &.danger { 68 | .title, 69 | .content { 70 | border-color: fade(@color-danger-normal, 20%); 71 | border-left-color: @color-danger-normal; 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/modules/common/less/side-bar-mask.less: -------------------------------------------------------------------------------- 1 | .side-bar-mask { 2 | 3 | .transition(bottom @animation-speed-very-fast); 4 | 5 | background-color: @color-mask-background; 6 | display: none; 7 | left: 0; 8 | position: fixed; 9 | right: 0; 10 | z-index: @mask; 11 | 12 | @media @breakpoint-mobile { 13 | display: block; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/modules/common/less/tab-navigation.less: -------------------------------------------------------------------------------- 1 | .tab-navigator { 2 | align-items: stretch; 3 | display: flex; 4 | font-size: 2vmin; 5 | width: 100%; 6 | 7 | .nav-item { 8 | align-items: center; 9 | background: white; 10 | border: 1px solid @color-border-dark; 11 | color: black; 12 | display: flex; 13 | flex: 1; 14 | flex-direction: column; 15 | line-height: 2em; 16 | 17 | &:hover, 18 | &:active { 19 | background: @color-light-hover; 20 | } 21 | 22 | &.active { 23 | background: @color-dark-hover; 24 | color: @color-light-normal; 25 | } 26 | 27 | &:not(:last-of-type) { 28 | border-right: none; 29 | } 30 | 31 | .nav-label { 32 | align-items: center; 33 | display: flex; 34 | flex: 5; 35 | font-size: 2.5vmin; 36 | justify-content: center; 37 | } 38 | 39 | .nav-values { 40 | align-items: center; 41 | border-top: 1px solid @color-border; 42 | display: flex; 43 | flex: 2; 44 | font-size: 1.6vmin; 45 | width: 100%; 46 | 47 | .value-denomination { 48 | align-items: center; 49 | border-right: 1px solid @color-border; 50 | display: flex; 51 | flex: 1; 52 | height: 100%; 53 | justify-content: center; 54 | 55 | &:last-of-type { 56 | border-right: none; 57 | padding-right: 0; 58 | } 59 | 60 | &.colorize { 61 | .colorize(); 62 | } 63 | } 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/modules/common/less/value-denomination.less: -------------------------------------------------------------------------------- 1 | .value-denomination { 2 | &.colorize { 3 | 4 | .colorize(); 5 | } 6 | 7 | .value { 8 | 9 | .font-weight-normal(); 10 | } 11 | 12 | .denomination { 13 | 14 | .font-weight-light(); 15 | 16 | margin-left: 0.2em; 17 | } 18 | 19 | .prefix { 20 | 21 | .font-weight-light(); 22 | 23 | margin-right: 0.3em; 24 | } 25 | 26 | .postfix { 27 | 28 | .font-weight-light(); 29 | 30 | margin-left: 0.3em; 31 | } 32 | } 33 | 34 | .value-date { 35 | 36 | .font-weight-normal(); 37 | } 38 | 39 | .value-timestamp { 40 | 41 | .font-weight-light(); 42 | } 43 | -------------------------------------------------------------------------------- /src/modules/create-market/components/create-market-form-1.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { BINARY, CATEGORICAL, SCALAR } from 'modules/markets/constants/market-types'; 3 | 4 | const CreateMarketForm1 = p => ( 5 |
6 |

Select the type of market you want to create

7 |
8 |
9 |
10 |

A market with a YES or NO outcome

11 | 14 |

Ask a question that has a simple YES or NO answer

15 |
16 |
17 |
18 |

A market with a MULTIPLE CHOICE outcome

19 | 22 |

Ask a question and provide a set of multiple choice answers

23 |
24 |
25 |
26 |

A market with a NUMERIC outcome

27 | 30 |

Ask a question that has an answer within a range of numbers

31 |
32 |
33 |
34 |
35 |

Important:

36 |

37 | There is a 30.00 ETH bond charged to your account when you create a new market. If the 38 | outcome of your market cannot be determined (and the market cannot be expired as a result) 39 | or if your market is ruled unethical, this bond will be forfeited. If your market is expired the 40 | bond will be returned to you in full. 41 |

42 |
43 |
44 | ); 45 | 46 | // TODO -- Prop Validations 47 | // CreateMarketForm1.propTypes = { 48 | // onValuesUpdated: PropTypes.func 49 | // }; 50 | 51 | export default CreateMarketForm1; 52 | -------------------------------------------------------------------------------- /src/modules/create-market/components/create-market-form-2-categorical.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import InputList from 'modules/common/components/input-list'; 3 | 4 | const CreateMarketForm2Categorical = p => ( 5 |
6 |

What are the possible answers to your question? (required)

7 |

8 | {`All possible outcomes to your question must be covered by these answers. You can add an 9 | "any other outcome" type answer at the end to ensure everything is covered.`} 10 |

11 | p.onValuesUpdated({ categoricalOutcomes: newOutcomes })} 19 | /> 20 |
21 | ); 22 | 23 | // TOOD -- Prop Validations 24 | // CreateMarketForm2Categorical.propTypes = { 25 | // categoricalOutcomes: PropTypes.array, 26 | // errors: PropTypes.object, 27 | // categoricalOutcomesMinNum: PropTypes.number, 28 | // categoricalOutcomesMaxNum: PropTypes.number, 29 | // categoricalOutcomeMaxLength: PropTypes.number, 30 | // onValuesUpdated: PropTypes.func 31 | // }; 32 | 33 | export default CreateMarketForm2Categorical; 34 | -------------------------------------------------------------------------------- /src/modules/create-market/components/create-market-form-2-scalar.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Input from 'modules/common/components/input'; 3 | 4 | const CreateMarketForm2Scalar = p => ( 5 |
6 |

What are the minimum and maximum values allowed when answering?

7 |

8 | The answer to your question must be a number that falls between the minimum and maximum 9 | values you're about to set. 10 |

11 | 12 |
13 | 18 | p.onValuesUpdated({ scalarSmallNum: value })} 25 | /> 26 | 27 | {p.errors.scalarSmallNum && 28 | {p.errors.scalarSmallNum} 29 | } 30 |
31 | 32 |
33 | 38 | p.onValuesUpdated({ scalarBigNum: value })} 45 | /> 46 | 47 | {p.errors.scalarBigNum && 48 | {p.errors.scalarBigNum} 49 | } 50 |
51 |
52 | ); 53 | 54 | // TOOD -- Prop Validations 55 | // CreateMarketForm2Scalar.propTypes = { 56 | // scalarSmallNum: PropTypes.string, 57 | // scalarBigNum: PropTypes.string, 58 | // onValuesUpdated: PropTypes.func 59 | // }; 60 | 61 | export default CreateMarketForm2Scalar; 62 | -------------------------------------------------------------------------------- /src/modules/create-market/components/create-market-form-5.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import MarketPreview from 'modules/market/components/market-preview'; 3 | import FormButtons from 'modules/create-market/components/create-market-form-buttons'; 4 | import ValueDenomination from 'modules/common/components/value-denomination'; 5 | 6 | const CreateMarketForm5 = p => ( 7 |
8 |

Review and submit your new market

9 | 10 | 11 |
12 | 13 |
14 | 15 |
16 | p.onValuesUpdated({ step: p.step - 1 })} 20 | /> 21 |
22 | ); 23 | 24 | // TOOD -- Prop Validations 25 | // CreateMarketForm5.propTypes = { 26 | // marketCreationFee: PropTypes.object, 27 | // gasCost: PropTypes.object, 28 | // eventBond: PropTypes.object, 29 | // onSubmit: PropTypes.func 30 | // }; 31 | 32 | export default CreateMarketForm5; 33 | -------------------------------------------------------------------------------- /src/modules/create-market/components/create-market-form-buttons.jsx: -------------------------------------------------------------------------------- 1 | import React, { PropTypes } from 'react'; 2 | 3 | const CreateMarketFormButtons = p => ( 4 |
5 | 12 | 13 | 21 |
22 | ); 23 | 24 | CreateMarketFormButtons.propTypes = { 25 | disabled: PropTypes.bool, 26 | nextLabel: PropTypes.string, 27 | prevLabel: PropTypes.string, 28 | onPrev: PropTypes.func, 29 | onNext: PropTypes.func 30 | }; 31 | 32 | export default CreateMarketFormButtons; 33 | -------------------------------------------------------------------------------- /src/modules/create-market/components/create-market-form.jsx: -------------------------------------------------------------------------------- 1 | import React, { PropTypes } from 'react'; 2 | import Form1 from 'modules/create-market/components/create-market-form-1'; 3 | import Form2 from 'modules/create-market/components/create-market-form-2'; 4 | import Form3 from 'modules/create-market/components/create-market-form-3'; 5 | import Form4 from 'modules/create-market/components/create-market-form-4'; 6 | import Form5 from 'modules/create-market/components/create-market-form-5'; 7 | 8 | import { SHARE } from 'modules/market/constants/share-denominations'; 9 | 10 | import getValue from 'utils/get-value'; 11 | 12 | const CreateMarketForm = (p) => { 13 | let form; 14 | 15 | const shareDenominations = getValue(p, 'scalarShareDenomination.denominations'); 16 | 17 | switch (p.step) { 18 | case 1: 19 | default: 20 | form = ; 21 | break; 22 | case 2: 23 | form = ; 24 | break; 25 | case 3: 26 | form = ; 27 | break; 28 | case 4: 29 | form = ; 30 | break; 31 | case 5: 32 | form = (); 37 | break; 38 | } 39 | 40 | return ( 41 |
42 | {form} 43 |
44 | ); 45 | }; 46 | 47 | CreateMarketForm.propTypes = { 48 | className: PropTypes.string, 49 | step: PropTypes.number 50 | }; 51 | 52 | export default CreateMarketForm; 53 | -------------------------------------------------------------------------------- /src/modules/create-market/components/create-market-view.jsx: -------------------------------------------------------------------------------- 1 | import React, { PropTypes } from 'react'; 2 | import CreateMarketForm from 'modules/create-market/components/create-market-form'; 3 | 4 | const CreateMarketPage = p => ( 5 |
6 |
7 | Be the market maker. 8 | Earn fees by making markets for people to trade. 9 | The more people trade your markets, the more fees you will make. 10 |
11 | 12 |
13 | 18 |
19 |
20 | ); 21 | 22 | CreateMarketPage.propTypes = { 23 | className: PropTypes.string, 24 | createMarketForm: PropTypes.object 25 | }; 26 | 27 | export default CreateMarketPage; 28 | -------------------------------------------------------------------------------- /src/modules/link/components/link.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component, PropTypes } from 'react'; 2 | 3 | export default class Link extends Component { 4 | 5 | // TODO -- Prop Validations 6 | static propTypes = { 7 | // className: PropTypes.string, 8 | href: PropTypes.string, 9 | target: PropTypes.string, 10 | onClick: PropTypes.func, 11 | disabled: PropTypes.bool 12 | }; 13 | 14 | constructor(props) { 15 | super(props); 16 | this.handleClick = this.handleClick.bind(this); 17 | } 18 | 19 | handleClick = (e) => { 20 | // if target is set (e.g. to "_blank"), let the browser handle it 21 | if (this.props.target || (this.props.href && this.props.href.indexOf('mailto:') === 0)) { 22 | return; 23 | } 24 | // if not a left click or is a special click, let the browser handle it 25 | if (e.button !== 0 || e.metaKey || e.altKey || e.ctrlKey || e.shiftKey) { 26 | return; 27 | } 28 | 29 | e.preventDefault(); 30 | if (this.props.onClick && !this.props.disabled) { 31 | this.props.onClick(this.props.href); 32 | } 33 | }; 34 | 35 | render() { 36 | const p = Object.keys(this.props).reduce((prev, key) => { // Strips certain invalid attrs for `a` tag 37 | if (key !== 'text') { 38 | return { 39 | ...prev, 40 | [key]: this.props[key] 41 | }; 42 | } 43 | return prev; 44 | }, {}); 45 | 46 | return ( 47 | 53 | {p.children} 54 | 55 | ); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/modules/login-message/less/login-message.less: -------------------------------------------------------------------------------- 1 | #login_message_view { 2 | .page-content { 3 | font-size: 1.4em; 4 | 5 | h1 { 6 | margin: 14px 0 8px; 7 | } 8 | 9 | h2 { 10 | margin: 10px 0 6px; 11 | } 12 | 13 | h3 { 14 | font-size: 1.4rem; 15 | font-weight: 500; 16 | } 17 | 18 | ol { 19 | padding-left: 40px; 20 | 21 | ul { 22 | list-style: disc; 23 | margin: 0.5em 1em; 24 | } 25 | } 26 | 27 | .contained { 28 | padding: 2em; 29 | } 30 | 31 | .link { 32 | color: @color-primary-active; 33 | 34 | &:hover, 35 | &:active, 36 | &:focus { 37 | color: @color-primary-hover; 38 | text-decoration: underline; 39 | } 40 | } 41 | 42 | .lets-do-this-button { 43 | background-color: #43505c; 44 | border: 0; 45 | border-radius: 1px; 46 | color: #ffffff; 47 | display: inline-block; 48 | font-size: 2vmin; 49 | height: 2.8em; 50 | line-height: 2.8em; 51 | margin-top: 1em; 52 | padding: 0 1em; 53 | text-align: center; 54 | text-transform: uppercase; 55 | white-space: nowrap; 56 | } 57 | 58 | .lets-do-this-button:hover { 59 | background-color: @color-dark-hover; 60 | color: #ffffff; 61 | text-decoration: none; 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/modules/market/components/market-chart.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component, PropTypes } from 'react'; 2 | import ReactHighcharts from 'react-highcharts'; 3 | 4 | import NullStateMessage from 'modules/common/components/null-state-message'; 5 | 6 | export default class MarketChart extends Component { 7 | static propTypes = { 8 | series: PropTypes.array 9 | }; 10 | 11 | shouldComponentUpdate(nextProps) { 12 | if (nextProps.series.length === this.props.series.length) return false; 13 | 14 | return true; 15 | } 16 | 17 | render() { 18 | const p = this.props; 19 | 20 | const config = { 21 | title: { 22 | text: '' 23 | }, 24 | rangeSelector: { selected: 1 }, 25 | xAxis: { 26 | type: 'datetime' 27 | }, 28 | yAxis: { 29 | title: { 30 | text: 'price' 31 | }, 32 | min: 0, 33 | max: 1 34 | }, 35 | legend: { 36 | enabled: true 37 | }, 38 | tooltip: { 39 | pointFormat: '{series.name}: {point.y}
', 40 | valueDecimals: 2 41 | }, 42 | series: p.series 43 | }; 44 | 45 | const nullMessage = 'No Completed Trades'; 46 | 47 | return ( 48 |
49 | {!p.series || !p.series.length ? 50 | : 51 | 52 | } 53 |
54 | ); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/modules/market/components/market-header.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import Dropdown from 'modules/common/components/dropdown'; 4 | import MarketProperties from 'modules/market/components/market-properties'; 5 | 6 | import { SCALAR } from 'modules/markets/constants/market-types'; 7 | 8 | const MarketDataHeader = p => ( 9 |
10 |
11 |

{p.description}

12 | 13 |
14 |
15 | {p.type === SCALAR && p.selectedShareDenomination && !p.isPendingReport && 16 | { p.updateSelectedShareDenomination(p.id, denomination); }} 20 | /> 21 | } 22 |
23 |
24 | ); 25 | 26 | export default MarketDataHeader; 27 | -------------------------------------------------------------------------------- /src/modules/market/components/market-open-orders-group.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import MarketOpenOrdersRow from 'modules/market/components/market-open-orders-row'; 4 | 5 | const MarketOpenOrdersGroup = p => ( 6 |
7 | {(p.userOpenOrders || []).map((order, i) => ( 8 | 22 | ))} 23 |
24 | ); 25 | 26 | export default MarketOpenOrdersGroup; 27 | -------------------------------------------------------------------------------- /src/modules/market/components/market-positions-row.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import ValueDenomination from 'modules/common/components/value-denomination'; 4 | 5 | import { SCALAR } from 'modules/markets/constants/market-types'; 6 | 7 | import getValue from 'utils/get-value'; 8 | import setShareDenomination from 'utils/set-share-denomination'; 9 | 10 | const MarketPositionsRow = (p) => { 11 | 12 | const quantityOfShares = setShareDenomination(getValue(p, 'outcome.position.qtyShares.formatted'), p.selectedShareDenomination); 13 | 14 | const outcomeName = getValue(p, 'outcome.name'); 15 | const lastPricePercent = getValue(p, 'outcome.lastPricePercent.rounded'); 16 | const purchasePrice = getValue(p, 'outcome.position.purchasePrice.formatted'); 17 | const lastPrice = getValue(p, 'outcome.lastPrice.formatted'); 18 | const realizedNet = getValue(p, 'outcome.position.realizedNet.formatted'); 19 | const unrealizedNet = getValue(p, 'outcome.position.unrealizedNet.formatted'); 20 | const totalNet = getValue(p, 'outcome.position.totalNet.formatted'); 21 | 22 | return ( 23 |
24 | {p.marketType === SCALAR ? 25 | : 26 | {outcomeName} 27 | } 28 | 29 | 30 | 31 | 32 | 33 | 34 |
35 | ); 36 | }; 37 | 38 | export default MarketPositionsRow; 39 | -------------------------------------------------------------------------------- /src/modules/market/components/market-positions.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import MarketPositionsRow from 'modules/market/components/market-positions-row'; 4 | import NullStateMessage from 'modules/common/components/null-state-message'; 5 | 6 | import { SCALAR } from 'modules/markets/constants/market-types'; 7 | 8 | import getValue from 'utils/get-value'; 9 | 10 | const MarketPositions = (p) => { 11 | const outcomePositions = getValue(p, 'market.myPositionOutcomes'); 12 | const nullMessage = 'No Current Positions'; 13 | 14 | return ( 15 |
16 | {!outcomePositions ? 17 | : 18 |
19 |
20 | {!p.marketType === SCALAR ? 'Outcomes' : 'Outcome'} 21 | Shares 22 | Avg Price 23 | Last Price 24 | Realized P/L 25 | Unrealized P/L 26 | Total P/L 27 |
28 |
29 | {(outcomePositions || []).map(outcome => 30 | 36 | )} 37 |
38 |
39 | } 40 |
41 | ); 42 | }; 43 | 44 | export default MarketPositions; 45 | -------------------------------------------------------------------------------- /src/modules/market/components/market-preview-outcomes.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ValueDenomination from 'modules/common/components/value-denomination'; 3 | 4 | const MarketOutcomes = p => ( 5 |
6 | {p.outcomes.map((outcome, i) => ( 7 |
11 | {!!outcome.lastPricePercent && 12 | 18 | } 19 | {outcome.name} 20 |
21 | ))} 22 |
23 | ); 24 | 25 | // TODO -- Prop Validations 26 | // MarketOutcomes.propTypes = { 27 | // outcomes: React.PropTypes.array 28 | // }; 29 | 30 | export default MarketOutcomes; 31 | -------------------------------------------------------------------------------- /src/modules/market/components/market-preview.jsx: -------------------------------------------------------------------------------- 1 | import React, { PropTypes } from 'react'; 2 | import classnames from 'classnames'; 3 | 4 | import MarketBasics from 'modules/market/components/market-basics'; 5 | import MarketPreviewOutcomes from 'modules/market/components/market-preview-outcomes'; 6 | import Link from 'modules/link/components/link'; 7 | 8 | const MarketPreview = p => ( 9 |
10 |
11 | 12 | 13 | {!!p.marketLink && 14 |
15 | 19 | {p.marketLink.text} 20 | 21 |
22 | } 23 |
24 | 25 | {p.outcomes && 26 |
27 | 28 |
29 | } 30 |
31 | ); 32 | 33 | MarketPreview.propTypes = { 34 | className: PropTypes.string, 35 | description: PropTypes.string, 36 | outcomes: PropTypes.array, 37 | isOpen: PropTypes.bool, 38 | isFavorite: PropTypes.bool, 39 | isPendingReport: PropTypes.bool, 40 | endDate: PropTypes.object, 41 | tradingFeePercent: PropTypes.object, 42 | volume: PropTypes.object, 43 | tags: PropTypes.array, 44 | marketLink: PropTypes.object, 45 | onClickToggleFavorite: PropTypes.func 46 | }; 47 | 48 | export default MarketPreview; 49 | -------------------------------------------------------------------------------- /src/modules/market/components/market-reported.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import MarketBasics from 'modules/market/components/market-basics'; 4 | import MarketDetails from 'modules/market/components/market-details'; 5 | 6 | const MarketReported = p => ( 7 |
8 |
9 |
10 | 17 | 18 |
19 |
20 |
21 | ); 22 | 23 | export default MarketReported; 24 | -------------------------------------------------------------------------------- /src/modules/market/components/market-reporting.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import ReportPanel from 'modules/reports/components/report-panel'; 4 | 5 | const MarketReporting = p => ( 6 |
7 |
8 | 9 |
10 |
11 | ); 12 | 13 | export default MarketReporting; 14 | -------------------------------------------------------------------------------- /src/modules/market/components/market-summary.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import shouldComponentUpdatePure from 'utils/should-component-update-pure'; 3 | import Market from 'modules/my-markets/components/my-market'; 4 | import MarketSummaryHeader from 'modules/my-markets/components/my-market-summary-header'; 5 | 6 | export default class MarketSummary extends Component { 7 | // TODO -- Prop Validations 8 | // static propTypes = { 9 | // marketSummary: PropTypes.object.isRequired 10 | // }; 11 | 12 | constructor(props) { 13 | super(props); 14 | this.shouldComponentUpdate = shouldComponentUpdatePure; 15 | } 16 | 17 | render() { 18 | const p = this.props; 19 | 20 | return ( 21 |
22 | 23 |
24 | 25 |
26 |
27 | ); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/modules/market/components/market-user-data.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | import ComponentNav from 'modules/common/components/component-nav'; 4 | import MarketPositions from 'modules/market/components/market-positions'; 5 | import MarketOpenOrders from 'modules/market/components/market-open-orders'; 6 | 7 | import { MARKET_USER_DATA_NAV_POSITIONS, MARKET_USER_DATA_NAV_OPEN_ORDERS } from 'modules/app/constants/views'; 8 | 9 | import getValue from 'utils/get-value'; 10 | 11 | export default class MarketUserData extends Component { 12 | constructor(props) { 13 | super(props); 14 | 15 | this.state = { 16 | selectedNav: MARKET_USER_DATA_NAV_POSITIONS 17 | }; 18 | 19 | this.updateSelectedNav = this.updateSelectedNav.bind(this); 20 | } 21 | 22 | updateSelectedNav(selectedNav) { 23 | this.setState({ selectedNav }); 24 | } 25 | 26 | render() { 27 | const p = this.props; 28 | const s = this.state; 29 | 30 | const outcomes = getValue(p, 'market.outcomes'); 31 | 32 | return ( 33 |
34 |

My Trading

35 | 40 | {s.selectedNav === MARKET_USER_DATA_NAV_POSITIONS && 41 | 46 | } 47 | {s.selectedNav === MARKET_USER_DATA_NAV_OPEN_ORDERS && 48 | 54 | } 55 |
56 | ); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/modules/market/components/market-view.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import MarketActive from 'modules/market/components/market-active'; 4 | import MarketReporting from 'modules/market/components/market-reporting'; 5 | import MarketReported from 'modules/market/components/market-reported'; 6 | import NullStateMessage from 'modules/common/components/null-state-message'; 7 | 8 | import getValue from 'utils/get-value'; 9 | 10 | const MarketView = (p) => { 11 | const nullMessage = 'No Market Data'; 12 | 13 | const isAvailable = getValue(p, 'market.id'); 14 | const isOpen = getValue(p, 'market.isOpen'); 15 | const isPendingReport = getValue(p, 'market.isPendingReport'); 16 | 17 | return ( 18 |
19 | {!isAvailable && } 20 | {isAvailable && isOpen && !isPendingReport && } 21 | {isAvailable && isPendingReport && } 22 | {isAvailable && !isOpen && !isPendingReport && } 23 |
24 | ); 25 | }; 26 | 27 | export default MarketView; 28 | -------------------------------------------------------------------------------- /src/modules/market/constants/share-denominations.js: -------------------------------------------------------------------------------- 1 | export const SHARE = 'share'; 2 | export const MILLI_SHARE = 'milli-share'; 3 | export const MICRO_SHARE = 'micro-share'; 4 | -------------------------------------------------------------------------------- /src/modules/market/less/basics-advanced.less: -------------------------------------------------------------------------------- 1 | .basics, 2 | .advanced { 3 | .description { 4 | display: block; 5 | font-size: 3.5vmin; 6 | font-weight: 400; 7 | line-height: 1.3em; 8 | overflow: hidden; 9 | text-overflow: ellipsis; 10 | } 11 | 12 | .properties { 13 | font-size: 1.2rem; 14 | line-height: 1em; 15 | margin: 0.5rem 0 0; 16 | 17 | .property { 18 | display: inline-block; 19 | margin: 0.5rem 2rem 0 0; 20 | 21 | .property-value { 22 | font-weight: 900; 23 | margin-left: 0.5rem; 24 | } 25 | } 26 | } 27 | 28 | .tags { 29 | line-height: 1em; 30 | margin: 0.5rem 0 0; 31 | 32 | .tag { 33 | display: inline-block; 34 | font-size: 1rem; 35 | padding: 0.5em 0; 36 | text-transform: uppercase; 37 | 38 | &:not(:last-child)::after { 39 | content: '>'; 40 | display: inline-block; 41 | margin: 0 0.5em; 42 | } 43 | 44 | &.link { 45 | cursor: pointer; 46 | 47 | &:hover, 48 | &:active, 49 | &:focus { 50 | text-decoration: underline; 51 | } 52 | } 53 | } 54 | } 55 | } 56 | 57 | .advanced { 58 | .properties { 59 | margin: 0; 60 | 61 | .property { 62 | vertical-align: top; 63 | 64 | .distinct { 65 | display: block; 66 | margin: 0.5rem 0 0; 67 | } 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/modules/market/less/market-active.less: -------------------------------------------------------------------------------- 1 | .market-active { 2 | display: flex; 3 | flex: 1; 4 | flex-direction: column; 5 | 6 | @media @breakpoint-mobile { 7 | .market-group:first-child > .order-book { 8 | display: none; 9 | } 10 | 11 | .market-group:last-child .outcome-trade { 12 | display: none; 13 | } 14 | 15 | .market-group { 16 | flex-direction: column; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/modules/market/less/market-basics.less: -------------------------------------------------------------------------------- 1 | .market-basics { 2 | display: flex; 3 | flex-direction: column; 4 | margin: 0 0 2em; 5 | 6 | .market-basics-header { 7 | display: flex; 8 | flex-direction: row; 9 | 10 | .market-basics-header-group-1 { 11 | flex: 4; 12 | 13 | .tags { 14 | color: @color-blue; 15 | display: flex; 16 | flex: 1; 17 | flex-direction: row; 18 | 19 | .tag { 20 | &:not(:last-of-type)::after { 21 | 22 | .fa(); 23 | 24 | content: ''; 25 | cursor: default; 26 | padding: 0 0.5em; 27 | } 28 | } 29 | } 30 | } 31 | 32 | .market-basics-header-group-2 { 33 | display: flex; 34 | flex: 1; 35 | justify-content: flex-end; 36 | } 37 | } 38 | 39 | .market-description { 40 | 41 | .font-size-large(); 42 | .font-weight-normal(); 43 | 44 | padding: 0.4em 0; 45 | } 46 | } 47 | 48 | .market-reported-details { 49 | .market-basics { 50 | margin: 1em 0 2em 1em; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/modules/market/less/market-details.less: -------------------------------------------------------------------------------- 1 | .market-details { 2 | display: flex; 3 | flex: 1; 4 | flex-direction: column; 5 | 6 | .properties { 7 | 8 | .table(); 9 | 10 | .property { 11 | 12 | .table-cell-spacing(); 13 | 14 | display: flex; 15 | flex: 1; 16 | 17 | .property-label { 18 | 19 | .font-weight-normal(); 20 | 21 | flex: 1; 22 | padding-left: 1em; 23 | } 24 | 25 | .property-value { 26 | flex: 5; 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/modules/market/less/market-header.less: -------------------------------------------------------------------------------- 1 | .market-header { 2 | display: flex; 3 | padding: 1em; 4 | 5 | @media @breakpoint-mobile { 6 | background-color: @color-app-background; 7 | padding: 2em 1em; 8 | } 9 | 10 | h3 { 11 | margin: 0 !important; 12 | } 13 | 14 | .market-header-actions { 15 | display: flex; 16 | flex: 1; 17 | justify-content: flex-end; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/modules/market/less/market-item.less: -------------------------------------------------------------------------------- 1 | .market-item { 2 | background: white; 3 | border-radius: 1px; 4 | margin: 1vmin 0 0 1vmin; 5 | padding: 1.5em 4.9vw 1.5em 2.8rem; 6 | 7 | .basics-container { 8 | display: inline-block; 9 | padding-right: 1em; 10 | vertical-align: middle; 11 | width: 70%; 12 | 13 | .basics { 14 | .description { 15 | color: black; 16 | margin: 0.5rem 2.5vw 0 0; 17 | width: 100%; 18 | } 19 | 20 | .properties { 21 | color: @color-dark-active; 22 | } 23 | } 24 | 25 | .buttons { 26 | margin: 2.5rem 0 1rem; 27 | 28 | .button { 29 | font-size: 1rem; 30 | font-weight: 700; 31 | height: 2.4em; 32 | line-height: 2.3em; 33 | margin: 0 1rem 0 0; 34 | padding: 0 0.75em; 35 | } 36 | } 37 | } 38 | 39 | .outcomes { 40 | display: inline-block; 41 | vertical-align: middle; 42 | width: 30%; 43 | 44 | .outcome { 45 | border-left: 4px solid @color-border-muted; 46 | display: flex; 47 | font-size: 1.3rem; 48 | font-weight: 700; 49 | line-height: 1.4em; 50 | margin-top: 0.1em; 51 | padding: 0.3em; 52 | 53 | .outcome-name { 54 | display: inline-block; 55 | text-align: left; 56 | width: 70%; 57 | } 58 | 59 | .outcome-price { 60 | display: inline-block; 61 | font-weight: 400; 62 | margin-right: 1em; 63 | overflow: hidden; 64 | text-align: right; 65 | text-overflow: ellipsis; 66 | white-space: nowrap; 67 | width: 30%; 68 | 69 | .colorize(); 70 | } 71 | } 72 | } 73 | 74 | .favorite-button { 75 | font-size: 1.8rem; 76 | position: absolute; 77 | right: 1.6rem; 78 | top: 1.6rem; 79 | 80 | &.on { 81 | font-size: 2rem; 82 | right: 1rem; 83 | top: 0.7rem; 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/modules/market/less/market-open-orders-group.less: -------------------------------------------------------------------------------- 1 | .market-open-orders-group { 2 | display: flex; 3 | flex-direction: column; 4 | 5 | &:hover { 6 | .market-open-orders-row { 7 | & > * { 8 | &:first-child { 9 | background-color: @color-gray-light; 10 | } 11 | } 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/modules/market/less/market-open-orders-row.less: -------------------------------------------------------------------------------- 1 | .market-open-orders-row { 2 | 3 | .table-row(); 4 | 5 | &:not(.isFirst) { 6 | 7 | .border(false); 8 | } 9 | 10 | &:last-child { 11 | & > * { 12 | 13 | .border(false); // Non-ideal...but the mixin needs some work to accomodate this scenario 14 | .border(true, @border-left, @border-light); 15 | } 16 | } 17 | 18 | & > * { 19 | 20 | .border(true, @border-bottom, @border-light); 21 | 22 | flex: 1; 23 | 24 | &:first-child { 25 | 26 | .border(false); 27 | 28 | flex: 2; 29 | padding-left: 1em; 30 | 31 | .value-denomination span { 32 | 33 | .font-weight-extra-light(); 34 | } 35 | } 36 | 37 | &:last-child { 38 | .cancel { 39 | color: @color-red; 40 | } 41 | 42 | .yes { 43 | color: @color-red; 44 | } 45 | 46 | .confirm { 47 | padding: 0 1em; 48 | } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/modules/market/less/market-open-orders.less: -------------------------------------------------------------------------------- 1 | .market-open-orders { 2 | .market-open-orders-header, 3 | .market-open-orders-row { 4 | span:not(:first-child) { 5 | text-align: center; 6 | } 7 | } 8 | 9 | .market-open-orders-header { 10 | 11 | .table-header(); 12 | 13 | & > * { 14 | flex: 1; 15 | margin-left: 1em; 16 | 17 | &:first-child { 18 | flex: 2; 19 | } 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/modules/market/less/market-positions.less: -------------------------------------------------------------------------------- 1 | .market-positions { 2 | 3 | .table(); 4 | 5 | .market-positions-header { 6 | 7 | .table-header(); 8 | } 9 | 10 | .market-positions-row { 11 | 12 | .table-row(); 13 | } 14 | 15 | .market-positions-header, 16 | .market-positions-row { 17 | & > * { 18 | &:first-child { 19 | flex: 3; 20 | margin-left: 1em; 21 | } 22 | 23 | flex: 1; 24 | } 25 | 26 | span:not(:first-child) { 27 | text-align: center; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/modules/market/less/market-preview-outcomes.less: -------------------------------------------------------------------------------- 1 | .market-preview-outcomes { 2 | display: flex; 3 | flex: 1; 4 | flex-direction: column; 5 | 6 | .outcome { 7 | 8 | .font-weight-normal(); 9 | 10 | display: flex; 11 | padding: 0.2em; 12 | 13 | .outcome-price { 14 | display: flex; 15 | flex: 1; 16 | justify-content: flex-end; 17 | 18 | .value:only-child { 19 | margin-right: @font-size-normal; 20 | } 21 | } 22 | 23 | .outcome-name { 24 | flex: 3; 25 | padding-left: 0.5em; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/modules/market/less/market-preview.less: -------------------------------------------------------------------------------- 1 | .market-preview { 2 | 3 | .border(true); 4 | 5 | background-color: @color-white; 6 | display: flex; 7 | flex: 1; 8 | margin: 2em 0; 9 | padding: 2em; 10 | 11 | .market-preview-group-1 { 12 | display: flex; 13 | flex: 4; 14 | flex-direction: column; 15 | padding-right: 2em; 16 | 17 | .market-link { 18 | display: flex; 19 | 20 | .button.trade { 21 | cursor: pointer; 22 | } 23 | } 24 | } 25 | 26 | .market-preview-group-2 { 27 | 28 | .border(true, @border-left); 29 | 30 | display: flex; 31 | flex: 1; 32 | padding-left: 2em; 33 | 34 | .outcome .outcome-price { 35 | color: @color-blue; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/modules/market/less/market-properties.less: -------------------------------------------------------------------------------- 1 | .market-properties { 2 | display: flex; 3 | flex-wrap: wrap; 4 | 5 | .property { 6 | .property-value { 7 | margin-left: 0.3em; 8 | } 9 | 10 | &:not(:last-of-type)::after { 11 | content: '•'; 12 | padding: 0 0.5em; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/modules/market/less/market-user-data.less: -------------------------------------------------------------------------------- 1 | .market-group .market-user-data { 2 | h3 { 3 | @media @breakpoint-mobile { 4 | background-color: @color-app-background; 5 | margin: 0; 6 | padding: 2em 1em; 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/modules/market/less/market.less: -------------------------------------------------------------------------------- 1 | #market_view { 2 | margin: 0; 3 | } 4 | 5 | .market-group { 6 | display: flex; 7 | flex: 1; 8 | 9 | & > article { 10 | 11 | .border(true); 12 | 13 | background-color: @color-white; 14 | display: flex; 15 | flex-direction: column; 16 | 17 | // Not the most ideal implementation, but we'd need to do a refactor of the overall layout to accomodate something like a flexed row height that doesn't exceed the window height 18 | .market-content-scrollable { 19 | max-height: 30rem; 20 | overflow-y: scroll; 21 | } 22 | 23 | h3 { 24 | margin-left: 1em; 25 | } 26 | 27 | &:first-child { 28 | flex: 3; 29 | margin: 1rem 0.5rem 0.5rem 1rem; 30 | 31 | @media @breakpoint-mobile { 32 | margin: 0; 33 | } 34 | 35 | & + article { 36 | flex: 1; 37 | margin: 1rem 1rem 0.5rem 0.5rem; 38 | } 39 | } 40 | } 41 | 42 | &:last-child { 43 | & > article { 44 | &:first-child { 45 | margin: 0.5rem 0.5rem 0.5rem 1rem; 46 | 47 | @media @breakpoint-mobile { 48 | 49 | .border(false); 50 | 51 | margin: 0; 52 | } 53 | 54 | & + article { 55 | margin: 0.5rem 1rem 0.5rem 0.5rem; 56 | } 57 | } 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/modules/markets/components/markets-filter-sort.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import Dropdown from 'modules/common/components/dropdown'; 4 | import MarketsSearch from 'modules/markets/components/markets-search'; 5 | 6 | const MarketsFilterSort = p => ( 7 |
8 |
9 | { p.onChange(type, null, null); }} 13 | 14 | /> 15 |
16 | { p.onChange(null, sort, null); }} 21 | /> 22 | 30 |
31 |
32 |
33 | 34 |
35 |
36 | ); 37 | 38 | 39 | // TODO -- Prop Validations 40 | // MarketsFilterSort.propTypes = { 41 | // className: PropTypes.string, 42 | // selectedFilterSort: PropTypes.object, 43 | // sorts: PropTypes.array, 44 | // types: PropTypes.array, 45 | // order: PropTypes.object, 46 | // onChange: PropTypes.func, 47 | // keywords: PropTypes.object 48 | // }; 49 | 50 | export default MarketsFilterSort; 51 | -------------------------------------------------------------------------------- /src/modules/markets/components/markets-headers.jsx: -------------------------------------------------------------------------------- 1 | import React, { PropTypes } from 'react'; 2 | import MarketsFilterSort from 'modules/markets/components/markets-filter-sort'; 3 | import Link from 'modules/link/components/link'; 4 | 5 | const MarketsHeaders = p => ( 6 |
7 |
8 |
9 |

Markets

10 |
11 |
12 | {p.loginAccount && p.loginAccount.address && 13 | 18 | + Create New Market 19 | 20 | } 21 |
22 |
23 | 27 |
28 | ); 29 | 30 | MarketsHeaders.propTypes = { 31 | className: PropTypes.string, 32 | createMarketLink: PropTypes.object, 33 | loginAccount: PropTypes.object, 34 | marketsHeader: PropTypes.object, 35 | filterSort: PropTypes.object, 36 | keywords: PropTypes.object 37 | }; 38 | 39 | export default MarketsHeaders; 40 | -------------------------------------------------------------------------------- /src/modules/markets/components/markets-list.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import MarketPreview from 'modules/market/components/market-preview'; 3 | import MarketsPagination from 'modules/markets/components/markets-pagination'; 4 | 5 | import getValue from 'utils/get-value'; 6 | 7 | const MarketsList = p => ( 8 |
9 | {(p.markets || []).map((market) => { 10 | const selectedShareDenomination = getValue(p, `scalarShareDenomination.markets.${market.id}`); 11 | const shareDenominations = getValue(p, 'scalarShareDenomination.denominations'); 12 | 13 | return ( 14 | 21 | ); 22 | })} 23 | {!!p.pagination && !!p.pagination.numUnpaginated && 24 | 25 | } 26 |
27 | ); 28 | 29 | // TODO -- Prop Validations 30 | // MarketsList.propTypes = { 31 | // markets: PropTypes.array, 32 | // pagination: PropTypes.object 33 | // }; 34 | 35 | export default MarketsList; 36 | -------------------------------------------------------------------------------- /src/modules/markets/components/markets-pagination.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Link from 'modules/link/components/link'; 3 | 4 | const MarketsPagination = p => ( 5 |
6 |
7 | {!!p.pagination && !!p.pagination.previousPageNum && 8 | 12 | 13 | 14 | } 15 |
16 | 17 |
18 | {`${p.pagination.startItemNum} - ${p.pagination.endItemNum}`} of {p.pagination.numUnpaginated} 19 |
20 | 21 |
22 | {!!p.pagination && !!p.pagination.nextPageNum && 23 | 27 | 28 | 29 | } 30 |
31 |
32 | ); 33 | 34 | export default MarketsPagination; 35 | -------------------------------------------------------------------------------- /src/modules/markets/components/markets-search.jsx: -------------------------------------------------------------------------------- 1 | import React, { PropTypes } from 'react'; 2 | import Input from 'modules/common/components/input'; 3 | 4 | const MarketsSearch = p => ( 5 |
6 | 7 | 13 |
14 | ); 15 | 16 | MarketsSearch.propTypes = { 17 | className: PropTypes.string, 18 | keywords: PropTypes.object 19 | }; 20 | 21 | export default MarketsSearch; 22 | -------------------------------------------------------------------------------- /src/modules/markets/components/markets-tags.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Checkbox from 'modules/common/components/checkbox'; 3 | 4 | const Filters = p => ( 5 |
6 | {p.filters.map(filter => 7 |
8 | {filter.title} 9 | {filter.options.map(option => 10 | 11 | )} 12 |
13 | )} 14 |
15 | ); 16 | 17 | // TOOD -- Prop Validations 18 | // Filters.propTypes = { 19 | // filters: PropTypes.array 20 | // }; 21 | 22 | export default Filters; 23 | -------------------------------------------------------------------------------- /src/modules/markets/components/markets-view.jsx: -------------------------------------------------------------------------------- 1 | import React, { PropTypes } from 'react'; 2 | 3 | import MarketsHeaders from 'modules/markets/components/markets-headers'; 4 | import MarketsList from 'modules/markets/components/markets-list'; 5 | import Branch from 'modules/branch/components/branch'; 6 | 7 | const MarketsView = p => ( 8 |
9 | {!!p.loginAccount.rep && !!p.loginAccount.rep.value && 10 | 11 | } 12 | 19 | 25 |
26 | ); 27 | 28 | MarketsView.propTypes = { 29 | className: PropTypes.string, 30 | filterSort: PropTypes.object, 31 | marketsHeader: PropTypes.object, 32 | markets: PropTypes.array, 33 | pagination: PropTypes.object, 34 | keywords: PropTypes.object, 35 | branch: PropTypes.object 36 | }; 37 | 38 | export default MarketsView; 39 | -------------------------------------------------------------------------------- /src/modules/markets/constants/market-types.js: -------------------------------------------------------------------------------- 1 | export const BINARY = 'binary'; 2 | export const CATEGORICAL = 'categorical'; 3 | export const SCALAR = 'scalar'; 4 | 5 | export const MARKET_TYPES = { 6 | [BINARY]: BINARY, 7 | [CATEGORICAL]: CATEGORICAL, 8 | [SCALAR]: SCALAR 9 | }; 10 | 11 | -------------------------------------------------------------------------------- /src/modules/markets/constants/markets-headers.js: -------------------------------------------------------------------------------- 1 | export const FAVORITES = 'favorites'; 2 | export const PENDING_REPORTS = 'pending reports'; 3 | -------------------------------------------------------------------------------- /src/modules/markets/less/markets-filter-sort.less: -------------------------------------------------------------------------------- 1 | .markets-filter-sort { 2 | .dropdown { 3 | &:not(:last-of-type) { 4 | margin-right: 1em; 5 | } 6 | } 7 | 8 | .companion-fields { 9 | display: flex; 10 | 11 | & > button { 12 | align-items: center; 13 | background-color: @color-white; 14 | border-bottom: 1px solid @color-border; 15 | border-right: 1px solid @color-border; 16 | border-top: 1px solid @color-border; 17 | cursor: default; 18 | display: flex; 19 | padding: 0 1em; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/modules/markets/less/markets-pagination.less: -------------------------------------------------------------------------------- 1 | .markets-pagination { 2 | 3 | .font-size-large(); 4 | 5 | align-items: center; 6 | display: flex; 7 | flex: 1; 8 | justify-content: space-around; 9 | 10 | & > div { 11 | flex: 1; 12 | } 13 | 14 | .markets-pagination-group-1 { 15 | margin-left: -1.5em; // Derived from the default padding applied to buttons 16 | } 17 | 18 | .markets-pagination-group-2 { 19 | display: flex; 20 | justify-content: center; 21 | } 22 | 23 | .markets-pagination-group-3 { 24 | display: flex; 25 | justify-content: flex-end; 26 | margin-right: -1.5em; // Derived from the default padding applied to buttons 27 | } 28 | 29 | .button { 30 | 31 | .font-size-extra-large(); 32 | 33 | background-color: @color-transparent; 34 | color: @color-text-dark; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/modules/markets/less/markets-search.less: -------------------------------------------------------------------------------- 1 | .search-input { 2 | 3 | .border(true); 4 | 5 | align-items: center; 6 | background-color: @color-white; 7 | display: flex; 8 | flex: 1; 9 | min-width: 22em; 10 | padding-left: 1em; 11 | 12 | .input { 13 | 14 | .border(false); 15 | 16 | display: flex; 17 | flex: 1; 18 | 19 | input { 20 | 21 | .border(false); 22 | } 23 | } 24 | 25 | input.box { 26 | 27 | .border(); 28 | 29 | background-color: @color-transparent; 30 | padding: 1em; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/modules/my-markets/components/my-market-summary-header.jsx: -------------------------------------------------------------------------------- 1 | import React, { PropTypes } from 'react'; 2 | import ValueDenomination from 'modules/common/components/value-denomination'; 3 | 4 | const MyMarketsSummary = p => ( 5 |
6 | My Markets 7 | {!!p.fees && 8 | 9 | } 10 |
11 | ); 12 | 13 | MyMarketsSummary.propTypes = { 14 | className: PropTypes.string.isRequired, 15 | fees: PropTypes.object.isRequired 16 | }; 17 | 18 | export default MyMarketsSummary; 19 | -------------------------------------------------------------------------------- /src/modules/my-markets/components/my-market.jsx: -------------------------------------------------------------------------------- 1 | import React, { PropTypes } from 'react'; 2 | import ValueDenomination from 'modules/common/components/value-denomination'; 3 | import ValueDate from 'modules/common/components/value-date'; 4 | 5 | const Market = p => ( 6 |
7 |
8 | ends: 9 | 10 |
11 |
12 |
13 | fees collected 14 | 18 |
19 |
20 | open volume 21 | 22 |
23 |
24 | volume 25 | 26 |
27 |
28 | # of trades 29 | 30 |
31 |
32 | avg trade size 33 | 34 |
35 |
36 |
37 | ); 38 | 39 | Market.propTypes = { 40 | endDate: PropTypes.object.isRequired, 41 | openVolume: PropTypes.object.isRequired, 42 | volume: PropTypes.object.isRequired, 43 | numberOfTrades: PropTypes.object.isRequired, 44 | averageTradeSize: PropTypes.object.isRequired, 45 | fees: PropTypes.object.isRequired 46 | }; 47 | 48 | export default Market; 49 | -------------------------------------------------------------------------------- /src/modules/my-markets/less/my-markets.less: -------------------------------------------------------------------------------- 1 | .portfolio-list { 2 | .portfolio-main-group { 3 | .market-main-group-title { 4 | margin-right: 0.4em; 5 | text-transform: uppercase; 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/modules/my-positions/components/my-position.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ValueDenomination from 'modules/common/components/value-denomination'; 3 | import { SCALAR } from 'modules/markets/constants/market-types'; 4 | 5 | const Position = p => ( 6 |
7 |
8 | {p.type === SCALAR ? 9 | {p.lastPricePercent.rounded} : 10 | {p.name} 11 | } 12 | 13 |
14 |
15 |
16 | average price of open position 17 | 18 |
19 |
20 | last trade price 21 | 22 |
23 |
24 |
25 |
26 | realized P/L 27 | 28 |
29 |
30 | unrealized P/L 31 | 32 |
33 |
34 | total P/L 35 | 36 |
37 |
38 |
39 | ); 40 | 41 | Position.propTypes = { 42 | name: React.PropTypes.string, 43 | type: React.PropTypes.string, 44 | qtyShares: React.PropTypes.object, 45 | gainPercent: React.PropTypes.object, 46 | lastPrice: React.PropTypes.object, 47 | lastPricePercent: React.PropTypes.object, 48 | purchasePrice: React.PropTypes.object, 49 | realizedNet: React.PropTypes.object, 50 | unrealizedNet: React.PropTypes.object, 51 | totalNet: React.PropTypes.object 52 | }; 53 | 54 | export default Position; 55 | -------------------------------------------------------------------------------- /src/modules/my-positions/components/my-positions-market-overview.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ValueDenomination from 'modules/common/components/value-denomination'; 3 | 4 | const PositionsMarketOverview = p => ( 5 |
6 |
7 | {p.description} 8 |
9 |
10 | total realized P/L 11 | 12 |
13 |
14 | total unrealized P/L 15 | 16 |
17 |
18 | total P/L 19 | 20 |
21 |
22 |
23 |
24 | ); 25 | 26 | PositionsMarketOverview.propTypes = { 27 | description: React.PropTypes.string.isRequired, 28 | unrealizedNet: React.PropTypes.object.isRequired, 29 | realizedNet: React.PropTypes.object.isRequired 30 | }; 31 | 32 | export default PositionsMarketOverview; 33 | -------------------------------------------------------------------------------- /src/modules/my-positions/components/my-positions-summary.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import classnames from 'classnames'; 3 | 4 | const PositionsSummary = p => ( 5 |
6 | {!!p.numPositions && 7 | Positions 8 | } 9 |
10 | ); 11 | 12 | PositionsSummary.propTypes = { 13 | className: React.PropTypes.string 14 | }; 15 | 16 | export default PositionsSummary; 17 | -------------------------------------------------------------------------------- /src/modules/my-positions/components/my-positions.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactTooltip from 'react-tooltip'; 3 | 4 | import Position from 'modules/my-positions/components/my-position'; 5 | import Link from 'modules/link/components/link'; 6 | 7 | const Positions = p => ( 8 |
9 | {p.marketLink && 10 | 11 | {(p.market.myPositionOutcomes || []).map(outcome => 12 | 18 | )} 19 | 20 | } 21 | {!p.marketLink && 22 | (p.market.myPositionOutcomes || []).map(outcome => 23 | 29 | ) 30 | } 31 | {!p.settings.autoSellCompleteSets && p.market.hasCompleteSet && 32 |
33 |
34 | 44 |
45 |
46 | } 47 | 48 |
49 | ); 50 | 51 | // TODO -- Prop Validations 52 | // Positions.propTypes = { 53 | // className: React.PropTypes.string, 54 | // market: React.PropTypes.object, 55 | // marketLink: React.PropTypes.object 56 | // }; 57 | 58 | export default Positions; 59 | -------------------------------------------------------------------------------- /src/modules/my-positions/less/my-positions.less: -------------------------------------------------------------------------------- 1 | .positions-market-overview, 2 | .positions-list { 3 | display: table; 4 | font-size: 1.2rem; 5 | line-height: 1.9rem; 6 | margin: 1vmin 0 0 4%; 7 | width: 92%; 8 | 9 | .complete-sets { 10 | .close-position-button { 11 | float: left; 12 | margin-top: 10px; 13 | } 14 | } 15 | 16 | .position { 17 | display: table-row; 18 | 19 | &:not(:first-child) { 20 | border-top: 1px solid @color-border; 21 | } 22 | 23 | .position-group { 24 | display: table-cell; 25 | padding: 0.5em 0; 26 | text-align: right; 27 | vertical-align: middle; 28 | 29 | .position-pair { 30 | display: inline-block; 31 | line-height: 1.1em; 32 | min-width: 7.8em; 33 | white-space: nowrap; 34 | 35 | &.realized-net, 36 | &.unrealized-net, 37 | &.total-net { 38 | .colorize(); 39 | } 40 | 41 | > * { 42 | display: block; 43 | margin-left: 0.5em; 44 | } 45 | 46 | .title { 47 | font-size: 0.8em; 48 | } 49 | } 50 | } 51 | 52 | .main-group { 53 | text-align: left; 54 | .colorize(); 55 | 56 | > * { 57 | display: inline-block; 58 | margin-right: 1em; 59 | vertical-align: middle; 60 | } 61 | 62 | .position-pair { 63 | white-space: nowrap; 64 | } 65 | 66 | .position-name { 67 | min-width: 4.5em; 68 | text-transform: uppercase; 69 | } 70 | } 71 | } 72 | } 73 | 74 | .positions-market-overview { 75 | .position { 76 | .description { 77 | padding-left: 0; 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/modules/my-reports/less/my-reports.less: -------------------------------------------------------------------------------- 1 | .portfolio-list { 2 | .portfolio-main-group { 3 | .report-main-group-title { 4 | margin-right: 0.4em; 5 | text-transform: uppercase; 6 | } 7 | 8 | .report-main-group-title-outcome { 9 | text-transform: none; 10 | 11 | .report-committed { 12 | color: @color-negative; 13 | } 14 | 15 | .fa { 16 | font-family: 'Font Awesome'; 17 | padding: 0 0.4rem; 18 | 19 | &.report-equal { 20 | color: @color-positive; 21 | } 22 | 23 | &.report-unequal { 24 | color: @color-negative; 25 | } 26 | 27 | &.report-unethical { 28 | color: @color-negative; 29 | } 30 | } 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/modules/open-orders/components/open-orders-group.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import OpenOrder from 'modules/open-orders/components/open-order'; 4 | 5 | const OpenOrdersGroup = (p) => { 6 | if (p.userOpenOrders == null || p.userOpenOrders.length === 0) { 7 | return null; 8 | } 9 | 10 | return ( 11 | 12 | {p.userOpenOrders.map((openOrder, index) => 13 | 24 | )} 25 | 26 | ); 27 | }; 28 | 29 | // TODO -- Prop Validations 30 | // OpenOrdersGroup.propTypes = { 31 | // userOpenOrders: React.PropTypes.arrayOf(React.PropTypes.object).isRequired, 32 | // name: React.PropTypes.string.isRequired, 33 | // orderCancellation: React.PropTypes.object.isRequired, 34 | // isFirst: React.PropTypes.bool.isRequired 35 | // }; 36 | 37 | export default OpenOrdersGroup; 38 | -------------------------------------------------------------------------------- /src/modules/open-orders/less/open-order.less: -------------------------------------------------------------------------------- 1 | .market-open-orders { 2 | .open-orders-list { 3 | font-size: 1.2rem; 4 | margin-left: 4%; 5 | width: 92%; 6 | 7 | .open-orders-group { 8 | width: 100%; 9 | 10 | td { 11 | box-sizing: border-box; // this should be done for * 12 | padding: 0.5em 0; 13 | } 14 | 15 | .outcome-name { 16 | min-width: 9rem; 17 | text-align: left; 18 | } 19 | 20 | .type { 21 | text-align: right; 22 | } 23 | 24 | .shares { 25 | text-align: right; 26 | } 27 | 28 | .price { 29 | text-align: right; 30 | } 31 | 32 | .cancel { 33 | text-align: right; 34 | width: 110px; // so there is enough space for different states 35 | 36 | .cancel-order-action { 37 | background: transparent; 38 | color: @color-danger-active; 39 | height: unset; 40 | line-height: unset; 41 | padding: 0; 42 | text-align: left; 43 | 44 | &::before { 45 | content: '\f00d'; 46 | display: inline-block; 47 | font-family: 'Font Awesome'; 48 | font-weight: 700; 49 | left: -0.2em; 50 | position: relative; 51 | } 52 | 53 | &:hover, 54 | &:active { 55 | font-weight: 900; 56 | } 57 | 58 | &[disabled] { 59 | background: transparent !important; 60 | color: @color-muted-active !important; 61 | } 62 | } 63 | 64 | .cancel-order-abort-confirmation { 65 | background-color: transparent; 66 | color: inherit; 67 | height: unset; 68 | line-height: unset; 69 | margin-right: 1.4em; 70 | padding: 0; 71 | text-align: left; 72 | 73 | &:hover { 74 | font-weight: 700; 75 | } 76 | } 77 | } 78 | 79 | .open-order { 80 | border-top: 1px solid @color-border; 81 | 82 | &.first { 83 | border-top: none; 84 | } 85 | 86 | .outcome-name { 87 | text-transform: uppercase; 88 | } 89 | 90 | &.is-disabled { 91 | text-decoration: line-through; 92 | } 93 | } 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/modules/order-book/components/order-book-header.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const OrderBookHeader = () => ( 4 |
5 | Bid Q. 6 | Bid 7 | Ask 8 | Ask Q. 9 |
10 | ); 11 | 12 | export default OrderBookHeader; 13 | -------------------------------------------------------------------------------- /src/modules/order-book/components/order-book-rows.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import OrderBookRowSide from 'modules/order-book/components/order-book-row-side'; 4 | 5 | import { BID } from 'modules/transactions/constants/types'; 6 | 7 | const OrderBookRows = p => ( 8 |
9 | 18 | 26 |
27 | ); 28 | 29 | export default OrderBookRows; 30 | -------------------------------------------------------------------------------- /src/modules/order-book/components/order-book.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import OrderBookHeader from 'modules/order-book/components/order-book-header'; 4 | import OrderBookRows from 'modules/order-book/components/order-book-rows'; 5 | import EmDash from 'modules/common/components/em-dash'; 6 | 7 | import { SCALAR } from 'modules/markets/constants/market-types'; 8 | 9 | // NOTE -- 10 | // Bids + Asks are rendered into individual row components -- flexbox is utilized for side-by-side layout 11 | const OrderBook = p => ( 12 |
13 | {p.marketType !== SCALAR ? 14 |

Order Book {p.outcome.name}

: 15 |

Order Book

16 | } 17 | 18 |
19 | 28 |
29 |
30 | ); 31 | 32 | export default OrderBook; 33 | -------------------------------------------------------------------------------- /src/modules/order-book/constants/order-book-value-types.js: -------------------------------------------------------------------------------- 1 | export const PRICE = 'price'; 2 | export const SHARE = 'share'; 3 | -------------------------------------------------------------------------------- /src/modules/order-book/less/order-book-header.less: -------------------------------------------------------------------------------- 1 | .order-book-header { 2 | 3 | .table-header(); 4 | 5 | flex: none; 6 | } 7 | -------------------------------------------------------------------------------- /src/modules/order-book/less/order-book-row-side.less: -------------------------------------------------------------------------------- 1 | .order-book-row-side { 2 | flex: 1; 3 | 4 | &:first-child { 5 | 6 | .border(true, @border-right, @border-light); 7 | } 8 | 9 | &.order-book-row-side-trading { 10 | background-color: @color-blue-extra-light; 11 | } 12 | 13 | .order-book-side-row { 14 | 15 | .border(true, @border-top, @border-light); 16 | .table-row(); 17 | 18 | display: flex; 19 | 20 | &.is-of-current-user { 21 | background-color: @color-green-extra-light; 22 | 23 | &:hover { 24 | background-color: @color-green-extra-light; 25 | } 26 | } 27 | 28 | & > * { 29 | 30 | .table-cell-spacing(); 31 | 32 | flex: 1; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/modules/order-book/less/order-book-rows.less: -------------------------------------------------------------------------------- 1 | .order-book-rows { 2 | display: flex; 3 | } 4 | -------------------------------------------------------------------------------- /src/modules/order-book/less/order-book.less: -------------------------------------------------------------------------------- 1 | .order-book { 2 | 3 | .table(); 4 | 5 | .order-book-header, 6 | .order-book-side-row { 7 | & > * { 8 | flex: 1; 9 | text-align: center; 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/modules/outcomes/components/outcome-trade-action.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | export default class OutcomeTradeAction extends Component { 4 | constructor(props) { 5 | super(props); 6 | 7 | this.state = { 8 | isConfirming: false 9 | }; 10 | } 11 | 12 | render() { 13 | const p = this.props; 14 | const s = this.state; 15 | 16 | return ( 17 |
18 | {!s.isConfirming && 19 | 27 | } 28 | {s.isConfirming && 29 |
30 | Are you sure? 31 |
32 | 40 | 47 |
48 |
49 | } 50 |
51 | ); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/modules/outcomes/components/outcome-trade-summary.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import ValueDenomination from 'modules/common/components/value-denomination'; 4 | 5 | import getValue from 'utils/get-value'; 6 | 7 | const OutcomeTradeSummary = (p) => { 8 | const tradingFees = getValue(p, 'tradeOrder.tradingFees'); 9 | const feePercent = getValue(p, 'tradeOrder.feePercent'); 10 | const gasFees = getValue(p, 'tradeOrder.gasFees'); 11 | const totalCost = getValue(p, 'trade.totalCost'); 12 | 13 | return ( 14 |
15 | {tradingFees && feePercent && 16 |
17 | Fees: 18 | ETH ({p.tradeOrder.feePercent.formatted}%) 19 |
20 | } 21 | {gasFees && 22 |
23 | Gas: 24 | ETH 25 |
26 | } 27 | {totalCost && 28 |
29 | Total: 30 | ETH 31 |
32 | } 33 |
34 | ); 35 | }; 36 | 37 | export default OutcomeTradeSummary; 38 | -------------------------------------------------------------------------------- /src/modules/outcomes/components/outcomes.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import Outcome from 'modules/outcomes/components/outcome'; 4 | 5 | import { SCALAR } from 'modules/markets/constants/market-types'; 6 | 7 | const Outcomes = p => ( 8 |
9 |
10 |
11 | Outcome{!p.marketType === SCALAR && 's'} 12 | Bid Q. 13 | Bid 14 | Ask 15 | Ask Q 16 | Last 17 |
18 |
19 | Outcome{!p.marketType === SCALAR && 's'} 20 | Bid 21 | Ask 22 |
23 |
24 |
25 | {(p.outcomes || []).map(outcome => ( 26 | 42 | ))} 43 |
44 |
45 | ); 46 | 47 | export default Outcomes; 48 | -------------------------------------------------------------------------------- /src/modules/outcomes/constants/trade-types.js: -------------------------------------------------------------------------------- 1 | export const BUY = 'buy'; 2 | export const SELL = 'sell'; 3 | -------------------------------------------------------------------------------- /src/modules/outcomes/less/outcome-trade-action.less: -------------------------------------------------------------------------------- 1 | .outcome-trade-action { 2 | display: flex; 3 | justify-content: center; 4 | margin: 1em; 5 | 6 | .trade-confirmation { 7 | display: flex; 8 | flex: 1; 9 | flex-direction: column; 10 | justify-content: center; 11 | 12 | span { 13 | 14 | .font-size-large(); 15 | 16 | align-self: center; 17 | } 18 | 19 | .trade-confirmation-actions { 20 | display: flex; 21 | 22 | button { 23 | flex: 1; 24 | margin: 1em 1em 0; 25 | 26 | &.cancel { 27 | background-color: @color-gray; 28 | } 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/modules/outcomes/less/outcome-trade-summary.less: -------------------------------------------------------------------------------- 1 | .outcome-trade-summary { 2 | & > div { 3 | display: flex; 4 | margin: 1em 0 1em 1em; 5 | 6 | & > span:first-child { 7 | flex: 1; 8 | } 9 | 10 | & > span { 11 | display: flex; 12 | flex: 5; 13 | 14 | .value-denomination { 15 | display: flex; 16 | flex: 2; 17 | justify-content: flex-end; 18 | 19 | & + span { 20 | flex: 1; 21 | padding-left: 1em; 22 | } 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/modules/outcomes/less/outcome-trade.less: -------------------------------------------------------------------------------- 1 | .outcome-trade { 2 | @media @breakpoint-mobile { 3 | background-color: @color-gray-extra-light; 4 | padding: 1em 0; 5 | } 6 | 7 | h3 { 8 | @media @breakpoint-mobile { 9 | display: none; 10 | } 11 | } 12 | 13 | .outcome-trade-input-error-message { 14 | color: @color-red-light; 15 | padding: 0 0 0.5em; 16 | } 17 | 18 | & > span { 19 | margin-left: 1em; 20 | } 21 | 22 | .outcome-trade-inputs { 23 | display: flex; 24 | flex-direction: column; 25 | 26 | .outcome-trade-inputs-sides { 27 | display: flex; 28 | flex-direction: row; 29 | 30 | & > * { 31 | flex: 1; 32 | 33 | .link { 34 | flex: 1; 35 | 36 | &.selected { 37 | 38 | .border(true, @border-bottom, @color-purple, @border-width-3); 39 | } 40 | 41 | &:hover:not(.selected) { 42 | 43 | .border(true, @border-bottom, @color-purple, @border-width-2); 44 | } 45 | 46 | li { 47 | display: flex; 48 | justify-content: center; 49 | margin: 0; 50 | 51 | &.selected { 52 | 53 | .border(false); 54 | } 55 | 56 | &:hover:not(.selected) { 57 | 58 | .border(false); 59 | } 60 | } 61 | } 62 | } 63 | } 64 | 65 | .outcome-trade-inputs-fields { 66 | align-items: center; 67 | display: flex; 68 | flex-direction: row; 69 | padding: 1em; 70 | 71 | .input { 72 | flex: 3; 73 | } 74 | 75 | span { 76 | display: flex; 77 | flex: 1; 78 | justify-content: center; 79 | } 80 | } 81 | } 82 | 83 | .outcome-trade-actions { 84 | display: flex; 85 | justify-content: center; 86 | margin: 1em 0; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/modules/outcomes/less/outcome.less: -------------------------------------------------------------------------------- 1 | .outcome { 2 | .outcome-trade { 3 | box-shadow: inset 0 5px 5px -5px @color-black-extra-light, inset 0 -5px 5px -5px @color-black-extra-light; 4 | display: none; 5 | } 6 | 7 | &.selected { 8 | .outcome-trade { 9 | @media @breakpoint-mobile { 10 | display: flex; 11 | flex-direction: column; 12 | } 13 | } 14 | } 15 | 16 | .outcome-row-full, 17 | .outcome-row-condensed { 18 | 19 | .table-row(); 20 | 21 | @media @breakpoint-mobile { 22 | &.selected { 23 | .border(true, @border-left, @color-blue); 24 | } 25 | } 26 | 27 | &.link { 28 | cursor: default; 29 | } 30 | } 31 | 32 | .outcome-row-full { 33 | @media @breakpoint-mobile { 34 | display: none; 35 | } 36 | } 37 | 38 | .outcome-row-condensed { 39 | display: none; 40 | 41 | @media @breakpoint-mobile { 42 | display: flex; 43 | } 44 | 45 | .outcome-summary { 46 | align-items: flex-start; 47 | display: flex; 48 | flex-direction: column; 49 | justify-content: center; 50 | 51 | .outcome-name { 52 | 53 | .font-weight-normal(); 54 | 55 | margin-bottom: 0.2em; 56 | } 57 | } 58 | 59 | .outcome-best-orders { 60 | display: flex; 61 | justify-content: center; 62 | 63 | .outcome-best-container { 64 | border-radius: 5px; 65 | color: @color-white; 66 | display: flex; 67 | flex-direction: column; 68 | padding: 1em 1.5em; 69 | } 70 | 71 | &.outcome-best-bid .outcome-best-container { 72 | background-color: @color-red; 73 | } 74 | 75 | &.outcome-best-ask .outcome-best-container { 76 | background-color: @color-green; 77 | } 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/modules/outcomes/less/outcomes.less: -------------------------------------------------------------------------------- 1 | .outcomes { 2 | 3 | .table(); 4 | 5 | margin-top: 1em; 6 | 7 | .outcomes-header-full, 8 | .outcomes-header-condensed { 9 | .table-header(); 10 | } 11 | 12 | .outcomes-header-full { 13 | @media @breakpoint-mobile { 14 | display: none; 15 | } 16 | } 17 | 18 | .outcomes-header-condensed { 19 | display: none; 20 | 21 | @media @breakpoint-mobile { 22 | display: flex; 23 | 24 | .border(false); 25 | } 26 | } 27 | 28 | .outcomes-header-full, 29 | .outcomes-header-condensed, 30 | .outcome-row-full, 31 | .outcome-row-condensed { 32 | & > * { 33 | flex: 1; 34 | 35 | &:first-child { 36 | flex: 3; 37 | margin-left: 1em; 38 | } 39 | 40 | @media @breakpoint-mobile { 41 | padding-left: 1em; 42 | padding-right: 1em; 43 | } 44 | } 45 | 46 | span:not(:first-child) { 47 | text-align: center; 48 | 49 | .border(false, @border-left); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/modules/portfolio/components/markets.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Market from 'modules/my-markets/components/my-market'; 3 | import Link from 'modules/link/components/link'; 4 | 5 | const PortfolioMarkets = p => ( 6 |
7 | {!!p.markets && !!p.markets.length && p.markets.map(market => ( 8 | 9 |
10 | {market.description} 11 | {!!market && 12 |
13 | 14 |
15 | } 16 |
17 | 18 | ))} 19 |
20 | ); 21 | 22 | // TODO -- Prop Validations 23 | // PortfolioMarkets.propTypes = { 24 | // markets: React.PropTypes.array.isRequired 25 | // }; 26 | 27 | export default PortfolioMarkets; 28 | -------------------------------------------------------------------------------- /src/modules/portfolio/components/portfolio-view.jsx: -------------------------------------------------------------------------------- 1 | import React, { PropTypes } from 'react'; 2 | 3 | import TabNavigation from 'modules/common/components/tab-navigation'; 4 | import Positions from 'modules/portfolio/components/positions'; 5 | import Markets from 'modules/portfolio/components/markets'; 6 | import Reports from 'modules/portfolio/components/reports'; 7 | 8 | import { MY_POSITIONS, MY_MARKETS, MY_REPORTS } from 'modules/app/constants/views'; 9 | 10 | const PortfolioView = (p) => { 11 | let node; 12 | 13 | switch (p.activeView) { 14 | default: 15 | case MY_POSITIONS: 16 | node = ; 17 | break; 18 | case MY_MARKETS: 19 | node = ; 20 | break; 21 | case MY_REPORTS: 22 | node = ; 23 | break; 24 | } 25 | return ( 26 |
27 |
28 | {!!p.navItems && !!p.navItems.length && 29 | 33 | } 34 |
35 | 36 |
37 |
38 | {node} 39 |
40 |
41 |
42 | ); 43 | }; 44 | 45 | PortfolioView.propTypes = { 46 | navItems: PropTypes.array.isRequired, 47 | totals: PropTypes.object.isRequired, 48 | positions: PropTypes.object.isRequired, 49 | markets: PropTypes.object.isRequired, 50 | reports: PropTypes.object.isRequired, 51 | settings: PropTypes.object.isRequired 52 | }; 53 | 54 | export default PortfolioView; 55 | -------------------------------------------------------------------------------- /src/modules/portfolio/components/positions.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Positions from 'modules/my-positions/components/my-positions'; 3 | import PositionsMarketOverview from 'modules/my-positions/components/my-positions-market-overview'; 4 | import Link from 'modules/link/components/link'; 5 | 6 | const PortfolioPositions = p => ( 7 |
8 | {!!p.markets && !!p.markets.length && p.markets.map(market => ( 9 |
10 | 11 | 15 | 16 | {!!market.myPositionOutcomes && !!market.myPositionOutcomes.length && 17 | 23 | } 24 |
25 | ))} 26 |
27 | ); 28 | 29 | // TODO -- Prop Validations 30 | // PortfolioPositions.propTypes = { 31 | // markets: React.PropTypes.array.isRequired 32 | // }; 33 | 34 | export default PortfolioPositions; 35 | -------------------------------------------------------------------------------- /src/modules/portfolio/components/reports.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactTooltip from 'react-tooltip'; 3 | 4 | import Report from 'modules/my-reports/components/my-report'; 5 | import Link from 'modules/link/components/link'; 6 | 7 | const PortfolioReports = p => ( 8 |
9 | {!!p.reports && !!p.reports.length && p.reports.map(market => ( 10 | 11 |
12 | 13 | {market.description} 14 | {market.isChallenged && 15 | 19 |  20 | 21 | } 22 | {!market.isChallenged && market.isChallengeable && 23 | 27 |  28 | 29 | } 30 | 31 | {!!market && 32 |
33 | 34 |
35 | } 36 |
37 | 38 | ))} 39 | 40 |
41 | ); 42 | 43 | // TODO -- Prop Validations 44 | // PortfolioReports.propTypes = { 45 | // reports: React.PropTypes.array.isRequired 46 | // }; 47 | 48 | export default PortfolioReports; 49 | -------------------------------------------------------------------------------- /src/modules/reports/components/report-panel.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | import MarketHeader from 'modules/market/components/market-header'; 4 | import ComponentNav from 'modules/common/components/component-nav'; 5 | import ReportForm from 'modules/reports/components/report-form'; 6 | import MarketDetails from 'modules/market/components/market-details'; 7 | 8 | import { MARKET_REPORTING_NAV_REPORT, MARKET_REPORTING_NAV_DETAILS } from 'modules/app/constants/views'; 9 | 10 | import getValue from 'utils/get-value'; 11 | 12 | export default class ReportPanel extends Component { 13 | constructor(props) { 14 | super(props); 15 | 16 | this.state = { 17 | selectedNav: MARKET_REPORTING_NAV_REPORT 18 | }; 19 | 20 | this.updateSelectedNav = this.updateSelectedNav.bind(this); 21 | } 22 | 23 | updateSelectedNav(selectedNav) { 24 | this.setState({ selectedNav }); 25 | } 26 | 27 | render() { 28 | const p = this.props; 29 | const s = this.state; 30 | 31 | const market = getValue(p, 'market'); 32 | 33 | return ( 34 |
35 | 36 | 41 | {s.selectedNav === MARKET_REPORTING_NAV_REPORT && 42 |
43 | 48 |
49 | } 50 | {s.selectedNav === MARKET_REPORTING_NAV_DETAILS && 51 | 52 | } 53 |
54 | ); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/modules/reports/less/report-form.less: -------------------------------------------------------------------------------- 1 | .report-form { 2 | display: flex; 3 | flex-direction: column; 4 | margin: 1em; 5 | 6 | & > div { 7 | display: flex; 8 | flex-direction: column; 9 | 10 | &:not(:first-child) { 11 | margin: 1em 0; 12 | } 13 | } 14 | 15 | .reportable-outcomes { 16 | display: flex; 17 | flex-direction: column; 18 | margin-top: 1em; 19 | 20 | .outcome-option { 21 | margin: 0.25em; 22 | 23 | .outcome-option-radio { 24 | margin-right: 1em; 25 | } 26 | } 27 | } 28 | 29 | .checkbox { 30 | margin-top: 1em; 31 | } 32 | 33 | .report-actions { 34 | flex-direction: row; 35 | margin-bottom: 0; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/modules/transactions/components/transactions-view.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import Transactions from 'modules/transactions/components/transactions'; 4 | 5 | const TransactionsPage = p => ( 6 |
7 |
8 | {p.transactionsTotals.title} 9 |
10 | 11 |
12 | 16 |
17 |
18 | ); 19 | 20 | TransactionsPage.propTypes = { 21 | className: React.PropTypes.string, 22 | transactions: React.PropTypes.array, 23 | transactionsTotals: React.PropTypes.object 24 | }; 25 | 26 | export default TransactionsPage; 27 | -------------------------------------------------------------------------------- /src/modules/transactions/components/transactions.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Transaction from 'modules/transactions/components/transaction'; 3 | 4 | const Transactions = p => ( 5 |
6 |
7 | {(p.transactions || []).map((transaction, i) => 8 | 13 | )} 14 |
15 | {!!p.transactions.length && 16 | 17 | {"continue trading while transactions are running, just don't close the browser before they're done!"} 18 | 19 | } 20 |
21 | ); 22 | 23 | // TODO -- prop validations 24 | // Transactions.propTypes = { 25 | // transactions: React.PropTypes.array 26 | // }; 27 | export default Transactions; 28 | -------------------------------------------------------------------------------- /src/modules/transactions/constants/types.js: -------------------------------------------------------------------------------- 1 | export const BUY = 'buy'; 2 | export const SELL = 'sell'; 3 | export const TRADE_SUMMARY = 'trade_summary'; 4 | export const BID = 'bid'; 5 | export const ASK = 'ask'; 6 | export const SHORT_SELL = 'short_sell'; 7 | export const SHORT_ASK = 'short_ask'; 8 | export const CREATE_MARKET = 'create_market'; 9 | export const COMMIT_REPORT = 'commit_report'; 10 | export const REVEAL_REPORT = 'reveal_report'; 11 | export const REGISTER_ACCOUNT = 'register_account'; 12 | export const GENERATE_ORDER_BOOK = 'generate_order_book'; 13 | export const CANCEL_ORDER = 'cancel_order'; 14 | export const SELL_COMPLETE_SETS = 'sell_complete_sets'; 15 | -------------------------------------------------------------------------------- /src/selectors/active-view.js: -------------------------------------------------------------------------------- 1 | export default 'markets'; 2 | -------------------------------------------------------------------------------- /src/selectors/chat.js: -------------------------------------------------------------------------------- 1 | export default { 2 | augur: {} 3 | }; 4 | -------------------------------------------------------------------------------- /src/selectors/core-stats.js: -------------------------------------------------------------------------------- 1 | import { randomNum } from 'utils/random-number'; 2 | import makeNumber from 'utils/make-number'; 3 | 4 | export default [ 5 | { 6 | totalEth: { 7 | label: 'Total ETH', 8 | title: 'Ether -- outcome trading currency', 9 | value: makeNumber(Math.abs(randomNum(1000)), 'ETH') 10 | }, 11 | totalRep: { 12 | label: 'Total REP', 13 | title: 'Reputation -- event voting currency', 14 | value: makeNumber(Math.abs(randomNum(100)), 'REP') 15 | } 16 | }, 17 | // { 18 | // totalRiskedEth: { 19 | // label: 'Risked ETH', 20 | // title: 'Risked Ether -- Ether tied up in positions', 21 | // value: makeNumber(Math.abs(randomNum(1000)), 'ETH') 22 | // }, 23 | // totalAvailableEth: { 24 | // label: 'Available ETH', 25 | // title: 'Available Ether -- Ether not tied up in positions', 26 | // value: makeNumber(Math.abs(randomNum(1000)), 'ETH') 27 | // } 28 | // }, 29 | { 30 | totalPL: { 31 | label: 'Total P/L', 32 | tile: 'Profit/Loss -- net of all trades', 33 | value: makeNumber(0), 34 | colorize: true 35 | }, 36 | totalPLMonth: { 37 | label: '30 Day P/L', 38 | tile: 'Profit/Loss -- net of all trades over the last 30 days', 39 | value: makeNumber(randomNum(10), 'ETH'), 40 | colorize: true 41 | }, 42 | totalPLDay: { 43 | label: '1 Day P/L', 44 | tile: 'Profit/Loss -- net of all trades over the last day', 45 | value: makeNumber(randomNum(10), 'ETH'), 46 | colorize: true 47 | } 48 | } 49 | ]; 50 | -------------------------------------------------------------------------------- /src/selectors/filter-sort.js: -------------------------------------------------------------------------------- 1 | export default { 2 | selectedFilterSort: { // Initial Defaults 3 | type: 'open', 4 | sort: 'volume', 5 | isDesc: true 6 | }, 7 | types: [ 8 | { 9 | label: 'Open', 10 | value: 'open', 11 | default: true 12 | }, 13 | { 14 | label: 'Closed', 15 | value: 'closed' 16 | }, 17 | { 18 | label: 'Reporting', 19 | value: 'reporting' 20 | } 21 | ], 22 | sorts: [ 23 | { 24 | label: 'Volume', 25 | value: 'volume', 26 | default: true 27 | }, 28 | { 29 | label: 'Newest', 30 | value: 'newest' 31 | }, 32 | { 33 | label: 'Expiry', 34 | value: 'expiry' 35 | }, 36 | { 37 | label: 'Taker Fee', 38 | value: 'takerFee' 39 | }, 40 | { 41 | label: 'Maker Fee', 42 | value: 'makerFee' 43 | } 44 | ], 45 | order: { 46 | isDesc: true // This is the default 47 | }, 48 | onChange: (type, sort, order) => { 49 | const selectors = require('../selectors'); 50 | 51 | const isDesc = order == null ? selectors.filterSort.selectedFilterSort.isDesc : order; 52 | 53 | selectors.update({ 54 | filterSort: { 55 | ...selectors.filterSort, 56 | filterSort: { 57 | type: type || selectors.filterSort.selectedFilterSort.type, 58 | sort: sort || selectors.filterSort.selectedFilterSort.sort, 59 | isDesc 60 | } 61 | } 62 | }); 63 | } 64 | }; 65 | -------------------------------------------------------------------------------- /src/selectors/is-transactions-working.js: -------------------------------------------------------------------------------- 1 | export default true; 2 | -------------------------------------------------------------------------------- /src/selectors/keywords.js: -------------------------------------------------------------------------------- 1 | export default { 2 | value: '', 3 | onChangeKeywords: (keywords) => { 4 | const selectors = require('../selectors'); 5 | 6 | selectors.update({ 7 | keywords: { 8 | ...selectors.keywords, 9 | value: keywords 10 | } 11 | }); 12 | } 13 | }; 14 | -------------------------------------------------------------------------------- /src/selectors/links.js: -------------------------------------------------------------------------------- 1 | import { ACCOUNT, MARKETS, MAKE, TRANSACTIONS, M, MY_POSITIONS, MY_MARKETS, MY_REPORTS, LOGIN_MESSAGE } from 'modules/app/constants/views'; 2 | import { LOGIN } from 'modules/auth/constants/auth-types'; 3 | 4 | export default { 5 | authLink: { href: '/?page=register', onClick: url => require('../selectors').update({ activeView: LOGIN, url }) }, 6 | marketsLink: { href: '/', onClick: url => require('../selectors').update({ activeView: MARKETS, url }) }, 7 | transactionsLink: { href: '/?page=transactions', onClick: url => require('../selectors').update({ activeView: TRANSACTIONS, url }) }, 8 | marketLink: { href: '/?page=m', onClick: url => require('../selectors').update({ activeView: M, url }) }, 9 | previousLink: { href: '/', onClick: url => require('../selectors').update({ activeView: MARKETS, url }) }, 10 | createMarketLink: { href: '/?page=create', onClick: url => require('../selectors').update({ activeView: MAKE, url }) }, 11 | accountLink: { href: '/?page=account', onClick: url => require('../selectors').update({ activeView: ACCOUNT, url }) }, 12 | myPositionsLink: { href: '/?page=my-positions', onClick: url => require('../selectors').update({ activeView: MY_POSITIONS, url }) }, 13 | myMarketsLink: { href: '/?page=my-markets', onClick: url => require('../selectors').update({ activeView: MY_MARKETS, url }) }, 14 | myReportsLink: { href: '/?page=my-reports', onClick: url => require('../selectors').update({ activeView: MY_REPORTS, url }) }, 15 | loginMessageLink: { href: '/?page=login-message', onClick: url => require('../selectors').update({ activeView: LOGIN_MESSAGE, url }) } 16 | }; 17 | -------------------------------------------------------------------------------- /src/selectors/login-account-markets.js: -------------------------------------------------------------------------------- 1 | import markets from 'selectors/my-markets'; 2 | import summary from 'selectors/my-markets-summary'; 3 | 4 | export default { 5 | markets, 6 | summary 7 | }; 8 | -------------------------------------------------------------------------------- /src/selectors/login-account-positions.js: -------------------------------------------------------------------------------- 1 | import markets from 'selectors/positions-markets'; 2 | import summary from 'selectors/positions-summary'; 3 | 4 | export default { 5 | markets, 6 | summary 7 | }; 8 | -------------------------------------------------------------------------------- /src/selectors/login-account-reports.js: -------------------------------------------------------------------------------- 1 | import reports from 'selectors/my-reports'; 2 | import summary from 'selectors/my-reports-summary'; 3 | 4 | export default { 5 | reports, 6 | summary 7 | }; 8 | -------------------------------------------------------------------------------- /src/selectors/market-data-age.js: -------------------------------------------------------------------------------- 1 | export default { 2 | lastUpdatedBefore: '1 second ago', 3 | isMarketDataLoading: false 4 | }; 5 | -------------------------------------------------------------------------------- /src/selectors/market-data-nav-items.js: -------------------------------------------------------------------------------- 1 | import { MARKET_DATA_NAV_OUTCOMES, MARKET_DATA_ORDERS, MARKET_DATA_NAV_CHARTS, MARKET_DATA_NAV_DETAILS } from 'modules/app/constants/views'; 2 | 3 | export default { 4 | [MARKET_DATA_NAV_OUTCOMES]: { 5 | label: 'Outcomes' 6 | }, 7 | [MARKET_DATA_ORDERS]: { 8 | label: 'Orders', 9 | mobileOnly: true 10 | }, 11 | [MARKET_DATA_NAV_CHARTS]: { 12 | label: 'Charts' 13 | }, 14 | [MARKET_DATA_NAV_DETAILS]: { 15 | label: 'Details' 16 | } 17 | }; 18 | -------------------------------------------------------------------------------- /src/selectors/market-data-updater.js: -------------------------------------------------------------------------------- 1 | // Starts timer and restarts it on demand 2 | 3 | const UPDATE_INTERVAL_SECS = 15; 4 | 5 | let timerId = startTimer(); 6 | 7 | export default { 8 | /** 9 | * Resets market fields and restarts timer 10 | * @param marketId 11 | */ 12 | update: (marketId) => { 13 | const marketDataAge = require('../selectors').marketDataAge; 14 | 15 | if (marketDataAge != null) { 16 | marketDataAge.lastUpdatedBefore = '1 second ago'; 17 | marketDataAge.isMarketDataLoading = true; 18 | setTimeout(() => { 19 | const marketDataAge = require('../selectors').marketDataAge; 20 | 21 | marketDataAge.isMarketDataLoading = false; 22 | require('../selectors').update({ 23 | marketDataAge 24 | }); 25 | }, 1000); 26 | require('../selectors').update({ 27 | marketDataAge 28 | }); 29 | } 30 | clearInterval(timerId); 31 | timerId = startTimer(); 32 | }, 33 | updateIntervalSecs: UPDATE_INTERVAL_SECS 34 | }; 35 | 36 | /** 37 | * Starts timer which periodically updates market fields and redraws the app 38 | * 39 | * @return {number} timerID 40 | */ 41 | function startTimer() { 42 | return setInterval(() => { 43 | const marketDataAge = require('../selectors').marketDataAge; 44 | 45 | if (marketDataAge != null) { 46 | const lastUpdatedBeforeSecs = parseInt(marketDataAge.lastUpdatedBefore, 10); 47 | marketDataAge.lastUpdatedBefore = `${(lastUpdatedBeforeSecs + 1)} seconds ago`; 48 | require('../selectors').update({ 49 | marketDataAge 50 | }, { ignore: true }); 51 | } 52 | }, 1000); 53 | } 54 | -------------------------------------------------------------------------------- /src/selectors/market-reporting-nav-items.js: -------------------------------------------------------------------------------- 1 | import { MARKET_REPORTING_NAV_REPORT, MARKET_REPORTING_NAV_DETAILS } from 'modules/app/constants/views'; 2 | 3 | export default { 4 | [MARKET_REPORTING_NAV_REPORT]: { 5 | label: 'Report' 6 | }, 7 | [MARKET_REPORTING_NAV_DETAILS]: { 8 | label: 'Details' 9 | } 10 | }; 11 | -------------------------------------------------------------------------------- /src/selectors/market-user-data-nav-items.js: -------------------------------------------------------------------------------- 1 | import { MARKET_USER_DATA_NAV_POSITIONS, MARKET_USER_DATA_NAV_OPEN_ORDERS } from 'modules/app/constants/views'; 2 | 3 | export default { 4 | [MARKET_USER_DATA_NAV_POSITIONS]: { 5 | label: 'Positions' 6 | }, 7 | [MARKET_USER_DATA_NAV_OPEN_ORDERS]: { 8 | label: 'Open Orders' 9 | } 10 | }; 11 | -------------------------------------------------------------------------------- /src/selectors/market.js: -------------------------------------------------------------------------------- 1 | import markets from './markets'; 2 | 3 | export default markets[0]; 4 | -------------------------------------------------------------------------------- /src/selectors/markets-header.js: -------------------------------------------------------------------------------- 1 | export default { 2 | selectedMarketsHeader: null, 3 | numMarkets: 10, 4 | numFavorites: 6, 5 | numPendingReports: 20, 6 | onClickAllMarkets: () => {}, 7 | onClickFavorites: () => {}, 8 | onClickPendingReports: () => {} 9 | }; 10 | -------------------------------------------------------------------------------- /src/selectors/markets-totals.js: -------------------------------------------------------------------------------- 1 | export default { 2 | numAll: 6, 3 | numFavorites: 4, 4 | numPendingReports: 3, 5 | numUnpaginated: 7, 6 | numFiltered: 7, 7 | }; 8 | -------------------------------------------------------------------------------- /src/selectors/my-markets-summary.js: -------------------------------------------------------------------------------- 1 | export default { 2 | numMarkets: Math.random() * 4 3 | }; 4 | -------------------------------------------------------------------------------- /src/selectors/my-reports-summary.js: -------------------------------------------------------------------------------- 1 | export default { 2 | numReports: Math.random() * 4, 3 | netRep: Math.random() * 10 4 | }; 5 | -------------------------------------------------------------------------------- /src/selectors/order-cancellation.js: -------------------------------------------------------------------------------- 1 | export default { 2 | cancellationStatuses: { 3 | CANCELLATION_CONFIRMATION: 'CANCELLATION_CONFIRMATION', 4 | CANCELLING: 'CANCELLING', 5 | CANCELLED: 'CANCELLED', 6 | CANCELLATION_FAILED: 'CANCELLATION_FAILED' 7 | }, 8 | cancelOrder: (orderID) => { 9 | require('../selectors').orderCancellation[orderID] = require('../selectors').orderCancellation.cancellationStatuses.CANCELLING; 10 | require('../selectors').update({}); 11 | 12 | setTimeout(() => { 13 | require('../selectors').markets.forEach((market) => { 14 | market.outcomes.forEach((outcome) => { 15 | const order = outcome.userOpenOrders.find(openOrder => openOrder.id === orderID); 16 | if (order != null) { 17 | if (order.type === 'buy') { 18 | // cancellation success => remove 19 | const index = outcome.userOpenOrders.findIndex(openOrder => openOrder.id === orderID); 20 | outcome.userOpenOrders.splice(index, 1); 21 | } else { 22 | // cancellation failure => display cancel action again 23 | require('../selectors').orderCancellation[orderID] = require('../selectors').orderCancellation.cancellationStatuses.CANCELLATION_FAILED; 24 | 25 | setTimeout(() => { 26 | delete require('../selectors').orderCancellation[orderID]; 27 | require('../selectors').update({}); 28 | }, 2000); 29 | } 30 | require('../selectors').update({}); 31 | } 32 | }); 33 | }); 34 | }, 2000); 35 | }, 36 | showCancelOrderConfirmation: (orderID) => { 37 | // prevent accidental cancellation from double click 38 | setTimeout(() => { 39 | require('../selectors').orderCancellation[orderID] = require('../selectors').orderCancellation.cancellationStatuses.CANCELLATION_CONFIRMATION; 40 | require('../selectors').update({}); 41 | }, 300); 42 | }, 43 | abortCancelOrderConfirmation: (orderID) => { 44 | delete require('../selectors').orderCancellation[orderID]; 45 | require('../selectors').update({}); 46 | } 47 | }; 48 | -------------------------------------------------------------------------------- /src/selectors/outcome-trade-nav-items.js: -------------------------------------------------------------------------------- 1 | import { BUY, SELL } from 'modules/outcomes/constants/trade-types'; 2 | 3 | export default { 4 | [BUY]: { 5 | label: BUY 6 | }, 7 | [SELL]: { 8 | label: SELL 9 | } 10 | }; 11 | -------------------------------------------------------------------------------- /src/selectors/pagination.js: -------------------------------------------------------------------------------- 1 | import { MARKETS } from 'modules/app/constants/views'; 2 | 3 | export default { 4 | numPerPage: 10, 5 | numPages: 10, 6 | selectedPageNum: 1, 7 | nextPageNum: 2, 8 | startItemNum: 1, 9 | endItemNum: 10, 10 | numUnpaginated: 89, 11 | nextItemNum: 11, 12 | onUpdateSelectedPageNum: (selectedPageNum) => { 13 | const selectors = require('../selectors'); 14 | 15 | selectors.update({ 16 | pagination: { 17 | ...selectors.pagination, 18 | selectedPageNum, 19 | nextPageNum: selectedPageNum + 1, 20 | previousPageNum: selectedPageNum - 1, 21 | startItemNum: ((selectedPageNum - 1) * 10) + 1, 22 | endItemNum: selectedPageNum * 10, 23 | nextItemNum: (selectedPageNum * 10) + 1, 24 | previousItemNum: ((selectedPageNum - 2) * 10) + 1 25 | } 26 | }); 27 | }, 28 | previousPageLink: { href: '/?page=1', onClick: url => require('../selectors').update({ activeView: MARKETS, url }) }, 29 | nextPageLink: { href: '/?page=2', onClick: url => require('../selectors').update({ activeView: MARKETS, url }) }, 30 | }; 31 | -------------------------------------------------------------------------------- /src/selectors/portfolio-nav-items.js: -------------------------------------------------------------------------------- 1 | import links from 'selectors/links'; 2 | 3 | import { MY_POSITIONS, MY_MARKETS, MY_REPORTS } from 'modules/app/constants/views'; 4 | 5 | import makeNumber from 'utils/make-number'; 6 | import { randomNum } from 'utils/random-number'; 7 | 8 | export default [ 9 | { 10 | label: 'Positions', 11 | link: links.myPositionsLink, 12 | page: MY_POSITIONS, 13 | leadingTitle: 'Total Positions', 14 | leadingValue: makeNumber(Math.round(randomNum()), 'positions'), 15 | trailingTitle: 'Total Gain/Loss', 16 | trailingValue: makeNumber(randomNum(), ' ETH') 17 | }, 18 | { 19 | label: 'Markets', 20 | link: links.myMarketsLink, 21 | page: MY_MARKETS, 22 | leadingTitle: 'Total Markets', 23 | leadingValue: makeNumber(Math.round(randomNum()), 'markets'), 24 | trailingTitle: 'Total Gain/Loss', 25 | trailingValue: makeNumber(randomNum(), ' ETH') 26 | }, 27 | { 28 | label: 'Reports', 29 | link: links.myReportsLink, 30 | page: MY_REPORTS, 31 | leadingTitle: 'Total Reports', 32 | leadingValue: makeNumber(Math.round(randomNum()), 'reports'), 33 | trailingTitle: 'Total Gain/Loss', 34 | trailingValue: makeNumber(randomNum(), ' REP') 35 | } 36 | ]; 37 | -------------------------------------------------------------------------------- /src/selectors/portfolio-totals.js: -------------------------------------------------------------------------------- 1 | import makeNumber from 'utils/make-number'; 2 | 3 | const randomSign = Math.random() < 0.5 ? -1 : 1; 4 | 5 | export default { 6 | netChange: makeNumber(randomSign * Math.random() * 10, ' ETH') 7 | }; 8 | -------------------------------------------------------------------------------- /src/selectors/portfolio.js: -------------------------------------------------------------------------------- 1 | import navItems from 'selectors/portfolio-nav-items'; 2 | import totals from 'selectors/portfolio-totals'; 3 | import positions from 'selectors/login-account-positions'; 4 | import markets from 'selectors/login-account-markets'; 5 | import reports from 'selectors/login-account-reports'; 6 | 7 | export default { 8 | navItems, 9 | totals, 10 | positions, 11 | markets, 12 | reports 13 | }; 14 | -------------------------------------------------------------------------------- /src/selectors/positions-summary.js: -------------------------------------------------------------------------------- 1 | import makeNumber from 'utils/make-number'; 2 | import { randomNum } from 'utils/random-number'; 3 | 4 | export default { 5 | numPositions: makeNumber(randomNum(), 'Positions', true), 6 | qtyShares: makeNumber(randomNum(), 'shares'), 7 | purchasePrice: makeNumber(randomNum(), ' ETH'), 8 | realizedNet: makeNumber(randomNum(900), ' ETH'), 9 | unrealizedNet: makeNumber(randomNum(100), ' ETH'), 10 | totalNet: makeNumber(randomNum(), ' ETH') 11 | }; 12 | -------------------------------------------------------------------------------- /src/selectors/reportable-outcomes.js: -------------------------------------------------------------------------------- 1 | import { BINARY, CATEGORICAL } from 'modules/markets/constants/market-types'; 2 | 3 | const reportableOutcomes = (type, outcomes) => { 4 | switch (type) { 5 | case BINARY: 6 | return [ 7 | { 8 | id: '1', 9 | name: 'No' 10 | }, 11 | { 12 | id: '2', 13 | name: 'Yes' 14 | } 15 | ]; 16 | case CATEGORICAL: 17 | return outcomes; 18 | default: 19 | return []; 20 | } 21 | }; 22 | 23 | export default reportableOutcomes; 24 | -------------------------------------------------------------------------------- /src/selectors/scalar-share-denomination.js: -------------------------------------------------------------------------------- 1 | import { SHARE, MILLI_SHARE, MICRO_SHARE } from 'modules/market/constants/share-denominations'; 2 | 3 | export default { 4 | markets: { 5 | 0: MILLI_SHARE 6 | }, 7 | denominations: [ 8 | { 9 | label: 'Share', 10 | value: SHARE 11 | }, 12 | { 13 | label: 'mShare', 14 | value: MILLI_SHARE 15 | }, 16 | { 17 | label: 'μShare', 18 | value: MICRO_SHARE 19 | } 20 | ], 21 | updateSelectedShareDenomination: (id, selection) => { 22 | require('../selectors').update({ 23 | scalarMarketShareDenomination: { 24 | ...require('../selectors').scalarShareDenomination, 25 | markets: { 26 | ...require('../selectors').scalarShareDenomination.markets, 27 | [id]: selection 28 | } 29 | } 30 | }); 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /src/selectors/search.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinybike/augur-ui-react-components/742bdb50af36d36045678a2610d4b68e44638db6/src/selectors/search.js -------------------------------------------------------------------------------- /src/selectors/selected-outcome.js: -------------------------------------------------------------------------------- 1 | export default { 2 | selectedOutcomeID: null, 3 | updateSelectedOutcome: (selectedOutcomeID) => { 4 | const selectors = require('../selectors'); 5 | 6 | selectors.update({ 7 | selectedOutcome: { 8 | ...selectors.selectedOutcome, 9 | selectedOutcomeID 10 | } 11 | }); 12 | } 13 | }; 14 | -------------------------------------------------------------------------------- /src/selectors/settings.js: -------------------------------------------------------------------------------- 1 | export default {}; 2 | -------------------------------------------------------------------------------- /src/selectors/shares-purchased.js: -------------------------------------------------------------------------------- 1 | function randomShares(n) { return (n * Math.random()).toString(); } 2 | 3 | export default [{ 4 | id: '123', 5 | outcomes: [{ 6 | id: '1', 7 | shares: randomShares(10) 8 | }, { 9 | id: '2', 10 | shares: randomShares(1) 11 | }] 12 | }, { 13 | id: '456', 14 | outcomes: [{ 15 | id: '1', 16 | shares: randomShares(10) 17 | }, { 18 | id: '2', 19 | shares: '0' 20 | }, 21 | { 22 | id: '3', 23 | shares: '0' 24 | }, 25 | { 26 | id: '4', 27 | shares: randomShares(100) 28 | }, 29 | { 30 | id: '5', 31 | shares: randomShares(10) 32 | }, 33 | { 34 | id: '6', 35 | shares: randomShares(10) 36 | }] 37 | }]; 38 | -------------------------------------------------------------------------------- /src/selectors/trade-commit-lock.js: -------------------------------------------------------------------------------- 1 | export default { 2 | isLocked: false 3 | }; 4 | -------------------------------------------------------------------------------- /src/selectors/transactions-totals.js: -------------------------------------------------------------------------------- 1 | export default { 2 | numWorking: 1, 3 | numPending: 0, 4 | numComplete: 3, 5 | numWorkingAndPending: 1, 6 | numTotal: 4, 7 | title: 'Transaction Working', 8 | shortTitle: 'Working' 9 | }; 10 | -------------------------------------------------------------------------------- /src/selectors/url.js: -------------------------------------------------------------------------------- 1 | export default '/'; 2 | -------------------------------------------------------------------------------- /src/styles.less: -------------------------------------------------------------------------------- 1 | // Core 2 | @import (less) '../node_modules/normalize.css/normalize.css'; 3 | @import './modules/app/less/typography'; 4 | @import './modules/app/less/responsive'; 5 | @import './modules/app/less/colors'; 6 | @import './modules/app/less/animations'; 7 | @import './modules/app/less/borders'; 8 | @import './modules/app/less/arrangement'; 9 | @import './modules/app/less/layout'; 10 | @import './modules/app/less/common'; 11 | 12 | // Module Styles 13 | @import './modules/**/less/*'; 14 | -------------------------------------------------------------------------------- /src/utils/add-commas-to-number.js: -------------------------------------------------------------------------------- 1 | export default function (number) { 2 | let sides = []; 3 | 4 | sides = number.toString().split('.'); 5 | sides[0] = sides[0].replace(/\B(?=(\d{3})+(?!\d))/g, ','); 6 | 7 | return sides.join('.'); 8 | } 9 | -------------------------------------------------------------------------------- /src/utils/debounce.js: -------------------------------------------------------------------------------- 1 | export default function debounce(func, wait) { 2 | let timeout; 3 | const realWait = wait || 250; 4 | 5 | return (...args) => { 6 | const context = this; 7 | 8 | const later = () => { 9 | timeout = null; 10 | func.apply(context, args); 11 | }; 12 | 13 | const callNow = !timeout; 14 | 15 | clearTimeout(timeout); 16 | timeout = setTimeout(later, realWait); 17 | if (callNow) { 18 | func.apply(context, args); 19 | } 20 | }; 21 | } 22 | -------------------------------------------------------------------------------- /src/utils/empty-number.js: -------------------------------------------------------------------------------- 1 | function emptyNumber(denomination) { 2 | return { 3 | value: 0, 4 | formattedValue: 0, 5 | formatted: '-', 6 | roundedValue: 0, 7 | rounded: '-', 8 | minimized: '-', 9 | full: '-', 10 | denomination: denomination || '' 11 | }; 12 | } 13 | 14 | export default emptyNumber; 15 | -------------------------------------------------------------------------------- /src/utils/get-value.js: -------------------------------------------------------------------------------- 1 | // Gets value of a arbitrarily deeply nested value by key path 2 | // @params {Object} obj - parent object 3 | // @params {String} target - string of path `this.is.the.target` 4 | // @returns value - returns null is value is not found, otherwise, returns value 5 | function getValue(obj, target) { 6 | return target.split('.').reduce((o, x) => ((typeof o === 'undefined' || o === null) ? o : o[x]), obj); 7 | } 8 | 9 | export default getValue; 10 | -------------------------------------------------------------------------------- /src/utils/make-date.js: -------------------------------------------------------------------------------- 1 | function makeDate(d) { 2 | const months = [ 3 | 'Jan', 'Feb', 'Mar', 4 | 'Apr', 'May', 'Jun', 5 | 'Jul', 'Aug', 'Sep', 6 | 'Oct', 'Nov', 'Dec' 7 | ]; 8 | const date = (d instanceof Date) ? d : new Date(0); 9 | return { 10 | value: date, 11 | formatted: `${months[d.getMonth()]} ${d.getDate()}, ${d.getFullYear()}`, 12 | full: d.toISOString() 13 | }; 14 | } 15 | 16 | export default makeDate; 17 | -------------------------------------------------------------------------------- /src/utils/make-number.js: -------------------------------------------------------------------------------- 1 | function makeNumber(num, denomination, omitSign, noRandom) { 2 | let rndNum = num; 3 | if (!noRandom || Math.round(num) !== num) { 4 | rndNum = Math.round(num * 10000) / 10000; 5 | } 6 | 7 | const o = { 8 | value: rndNum, 9 | formattedValue: rndNum, 10 | formatted: rndNum.toFixed(2), 11 | roundedValue: Math.round(rndNum), 12 | rounded: Math.round(rndNum).toFixed(2), 13 | minimized: rndNum.toFixed(0), 14 | denomination: denomination || '' 15 | }; 16 | if (denomination === ' shares') { 17 | o.formatted = addBigUnitPostfix(rndNum); 18 | o.rounded = addBigUnitPostfix(rndNum); 19 | o.fullPrecision = rndNum.toString(); 20 | } 21 | 22 | const neverShowPlusSign = true; 23 | if (!omitSign && !neverShowPlusSign) { 24 | if (o.value > 0) { 25 | o.formatted = `+${o.formatted}`; 26 | o.rounded = `+${o.rounded}`; 27 | o.minimized = `+${o.minimized}`; 28 | } 29 | } 30 | 31 | o.full = o.formatted + o.denomination; 32 | 33 | return o; 34 | } 35 | 36 | function addBigUnitPostfix(value) { 37 | let postfixed; 38 | if (value > 1000000000000) { 39 | postfixed = '> 1T'; 40 | } else if (value > 10000000000) { 41 | postfixed = `${(value / 1000000000).toFixed(0)}B`; 42 | } else if (value > 10000000) { 43 | postfixed = `${(value / 1000000).toFixed(0)}M`; 44 | } else if (value > 10000) { 45 | postfixed = `${(value / 1000).toFixed(0)}K`; 46 | } else { 47 | postfixed = value.toFixed(2); 48 | } 49 | return postfixed; 50 | } 51 | 52 | export default makeNumber; 53 | -------------------------------------------------------------------------------- /src/utils/random-number.js: -------------------------------------------------------------------------------- 1 | export const randomSign = () => (Math.random() > 0.5 ? 1 : -1); 2 | export const randomNum = (multiplier = 10) => Math.random() * multiplier * randomSign(); 3 | -------------------------------------------------------------------------------- /src/utils/scroll-top-on-change.js: -------------------------------------------------------------------------------- 1 | export default (url) => { 2 | if (url && url !== `${window.location.pathname}${window.location.search}`) { 3 | window.scroll(0, 0); 4 | window.history.pushState(null, null, url); 5 | } 6 | }; 7 | -------------------------------------------------------------------------------- /src/utils/share-denomination-label.js: -------------------------------------------------------------------------------- 1 | import { MICRO_SHARE, MILLI_SHARE, SHARE } from 'modules/market/constants/share-denominations'; 2 | 3 | export default function (selectedDenomination, shareDenominations) { 4 | switch (selectedDenomination) { 5 | case (MICRO_SHARE): { 6 | const value = shareDenominations && shareDenominations.find(denomination => denomination.value === MICRO_SHARE); 7 | return (value && value.label) || 'μShares'; 8 | } 9 | case (MILLI_SHARE): { 10 | const value = shareDenominations && shareDenominations.find(denomination => denomination.value === MILLI_SHARE); 11 | return (value && value.label) || 'mShares'; 12 | } 13 | default: 14 | case (SHARE): { 15 | const value = shareDenominations && shareDenominations.find(denomination => denomination.value === SHARE); 16 | return (value && value.label) || 'Shares'; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/utils/should-component-update-pure.js: -------------------------------------------------------------------------------- 1 | export default function (nextProps, nextState) { 2 | return isShallowUnEqual(nextProps, this.props) || isShallowUnEqual(nextState, this.state); 3 | } 4 | 5 | export function shouldComponentUpdateLog(nextProps, nextState) { 6 | return isShallowUnEqual(nextProps, this.props, true) || isShallowUnEqual(nextState, this.state, true); 7 | } 8 | 9 | export function shouldComponentUpdateOnStateChangeOnly(nextProps, nextState) { 10 | return isShallowUnEqual(nextState, this.state); 11 | } 12 | 13 | function isShallowUnEqual(obj1, obj2, log) { 14 | // both arguments reference the same object 15 | if (obj1 === obj2) { 16 | return false; 17 | } 18 | 19 | // arguments are either not objects or undefined/null 20 | if (typeof obj1 !== 'object' || obj1 == null || typeof obj2 !== 'object' || obj2 == null) { 21 | return true; 22 | } 23 | 24 | const keysA = Object.keys(obj1); 25 | const keysB = Object.keys(obj2); 26 | const keysALen = keysA.length; 27 | 28 | // keys don't match 29 | if (keysALen !== keysB.length) { 30 | return true; 31 | } 32 | 33 | for (let i = 0; i < keysALen; i++) { 34 | // actual values are different + not functions 35 | if (obj1[keysA[i]] !== obj2[keysA[i]] && typeof obj1[keysA[i]] !== 'function') { 36 | log && console.log('------->', keysA[i], obj1[keysA[i]], obj2[keysA[i]]); 37 | return true; 38 | } 39 | } 40 | 41 | // nothing needs to be updated 42 | return false; 43 | } 44 | -------------------------------------------------------------------------------- /test/assertions/active-view.js: -------------------------------------------------------------------------------- 1 | import { assert } from 'chai'; 2 | 3 | export default function (activeView) { 4 | assert.isDefined(activeView, `activeView isn't defined`); 5 | assert.isString(activeView, `activeView isn't a string`); 6 | } -------------------------------------------------------------------------------- /test/assertions/chat.js: -------------------------------------------------------------------------------- 1 | import { assert } from 'chai'; 2 | 3 | export default function (chat) { 4 | assert.isDefined(chat, `chat isn't defined`); 5 | assert.isObject(chat, `chat isn't an object`); 6 | 7 | Object.keys(chat).forEach(room => { 8 | assert.isDefined(chat[room], `chat.${room} isn't defined`); 9 | assert.isObject(chat[room], `chat.${room} isn't an object`); 10 | }); 11 | 12 | // TODO -- flesh these test out 13 | } 14 | -------------------------------------------------------------------------------- /test/assertions/common/component-nav.js: -------------------------------------------------------------------------------- 1 | import { assert } from 'chai'; 2 | 3 | export default function(nav, label = 'Component Nav Item') { 4 | describe(`${label} Shape`, () => { 5 | assert.isDefined(nav); 6 | assert.isObject(nav); 7 | 8 | assert.isDefined(nav.label, `${label}.label isn't defined`); 9 | assert.isString(nav.label, `${label}.label isn't a string`); 10 | }); 11 | } 12 | -------------------------------------------------------------------------------- /test/assertions/common/formatted-date.js: -------------------------------------------------------------------------------- 1 | import { assert } from 'chai'; 2 | 3 | export default function (formattedDate, label = 'Formatted Date'){ 4 | describe(`${label}`, () => { 5 | it(`should be formatted date`, () => { 6 | assert.isDefined(formattedDate.value, `value is not defined`); 7 | assert.instanceOf(formattedDate.value, Date, `value is not a date`); 8 | assert.isDefined(formattedDate.formatted, `formatted is not defined`); 9 | assert.isString(formattedDate.formatted, `formatted is not a string`); 10 | assert.isDefined(formattedDate.full, `full is not defined`); 11 | assert.isString(formattedDate.full, `full is not a string`); 12 | }); 13 | }); 14 | } 15 | -------------------------------------------------------------------------------- /test/assertions/common/formatted-number.js: -------------------------------------------------------------------------------- 1 | import { assert } from 'chai'; 2 | 3 | export default function (actual, label = 'Formatted Number') { 4 | describe(label, () => { 5 | it('should be formatted number', () => { 6 | assert.isDefined(actual.value, `'value' isn't defined`); 7 | assert.isNumber(actual.value, `'value' isn't a number`); 8 | assert.isDefined(actual.formattedValue, `'formattedValue' isn't defined`); 9 | assert.isNumber(actual.formattedValue, `'formattedValue' isn't a number`); 10 | assert.isDefined(actual.formatted, `'formatted' isn't defined`); 11 | assert.isString(actual.formatted, `'formatted' isn't a string`); 12 | assert.isDefined(actual.roundedValue, `'roundedValue' isn't defined`); 13 | assert.isNumber(actual.roundedValue, `'roundedValue' isn't a number`); 14 | assert.isDefined(actual.rounded, `'rounded' isn't defined`); 15 | assert.isString(actual.rounded, `'rounded' isn't a string`); 16 | assert.isDefined(actual.minimized, `'minimized' isn't defined`); 17 | assert.isString(actual.minimized, `'minimized' isn't a string`); 18 | assert.isDefined(actual.denomination, `'denomination' isn't defined`); 19 | assert.isString(actual.denomination, `'denomination' isn't a String`); 20 | assert.isDefined(actual.full, `'full' isn't defined`); 21 | assert.isString(actual.full, `'full' isn't a string`); 22 | }); 23 | }); 24 | }; 25 | -------------------------------------------------------------------------------- /test/assertions/common/initial-fair-prices.js: -------------------------------------------------------------------------------- 1 | import { assert } from 'chai'; 2 | 3 | export default function (initialFairPrices, refObj){ 4 | describe(`${refObj}'s initiaiFairPrices`, () => { 5 | describe('type', () => { 6 | it('should exist', () => { 7 | assert.isDefined(initialFairPrices.type, 'initialFairPrices.type is not defined'); 8 | }); 9 | 10 | it('should be a string', () => { 11 | assert.isString(initialFairPrices.type, 'initialFairPrices.type is not a string'); 12 | }); 13 | }); 14 | 15 | describe('values', () => { 16 | it('should exist', () => { 17 | assert.isDefined(initialFairPrices.values, 'initialFairPrices.values is not defined'); 18 | }); 19 | 20 | it('should be an array', () => { 21 | assert.isArray(initialFairPrices.values, 'initialFairPrices.values is not an array'); 22 | }); 23 | }); 24 | 25 | describe('raw', () => { 26 | it('should exist', () => { 27 | assert.isDefined(initialFairPrices.raw, 'initialFairPrices.raw is not defined'); 28 | }); 29 | 30 | it('should be an array', () => { 31 | assert.isArray(initialFairPrices.raw, 'initialFairPrices.raw is not an array'); 32 | }); 33 | }); 34 | }); 35 | } -------------------------------------------------------------------------------- /test/assertions/common/link.js: -------------------------------------------------------------------------------- 1 | import { assert } from 'chai'; 2 | 3 | export default function (link, label = 'Link') { 4 | describe(`${label} Shape`, () => { 5 | assert.isDefined(link); 6 | assert.isObject(link); 7 | 8 | it('href', () => { 9 | assert.isDefined(link.href); 10 | assert.isString(link.href); 11 | }); 12 | 13 | it('onClick', () => { 14 | assert.isDefined(link.onClick); 15 | assert.isFunction(link.onClick); 16 | }); 17 | }); 18 | } -------------------------------------------------------------------------------- /test/assertions/common/market-link.js: -------------------------------------------------------------------------------- 1 | import { assert } from 'chai'; 2 | 3 | export default function (marketLink, label = 'marketLink') { 4 | describe(label, () => { 5 | it('should be market link', () => { 6 | assert.isDefined(marketLink, `'marketLink' is not defined`); 7 | assert.isObject(marketLink, `'marketLink' is not defined`); 8 | 9 | assert.isDefined(marketLink.text,`'text' is not defined`); 10 | assert.isString(marketLink.text, `'text' is not a string`); 11 | 12 | assert.isDefined(marketLink.className, `'className' is not defined`); 13 | assert.isString(marketLink.className, `'className' is not a string`); 14 | 15 | assert.isDefined(marketLink.onClick, `'onClick' is not defined`); 16 | assert.isFunction(marketLink.onClick, `'onClick' is not a function`); 17 | }); 18 | }); 19 | } -------------------------------------------------------------------------------- /test/assertions/common/nav-item.js: -------------------------------------------------------------------------------- 1 | import { assert } from 'chai'; 2 | import assertLink from '../../../test/assertions/common/link'; 3 | 4 | export default function (navItem, label = 'Nav Item'){ 5 | describe(`${label}' Shape`, () => { 6 | assert.isDefined(navItem); 7 | assert.isObject(navItem); 8 | 9 | it('label', () => { 10 | assert.isDefined(navItem.label); 11 | assert.isString(navItem.label); 12 | }); 13 | 14 | it('link', () => { 15 | assertLink(navItem.link, 'portfolio.navItem.link'); 16 | }); 17 | 18 | it('page', () => { 19 | assert.isDefined(navItem.page); 20 | assert.isString(navItem.page); 21 | }); 22 | }); 23 | } -------------------------------------------------------------------------------- /test/assertions/core-stats.js: -------------------------------------------------------------------------------- 1 | import { assert } from 'chai'; 2 | 3 | export default function (coreStats) { 4 | assert.isDefined(coreStats, `'coreStats' was not defined as expected`); 5 | } 6 | -------------------------------------------------------------------------------- /test/assertions/favorite-markets.js: -------------------------------------------------------------------------------- 1 | import { assert } from 'chai'; 2 | 3 | export default function (positionsSummary) { 4 | // implement me 5 | }; 6 | 7 | -------------------------------------------------------------------------------- /test/assertions/is-transactions-working.js: -------------------------------------------------------------------------------- 1 | import { assert } from 'chai'; 2 | 3 | export default function(isTransactionsWorking) { 4 | assert.isDefined(isTransactionsWorking, `isTransactionsWorking isn't defined`); 5 | assert.isBoolean(isTransactionsWorking, `isTransactionsWorking isn't a boolean`); 6 | } 7 | -------------------------------------------------------------------------------- /test/assertions/keywords.js: -------------------------------------------------------------------------------- 1 | import { assert } from 'chai'; 2 | 3 | export default function (keywords) { 4 | assert.isDefined(keywords, `keywords isn't defined`); 5 | assert.isObject(keywords, `keywords isn't an object`); 6 | assert.isDefined(keywords.value, `keywords.value isn't defined`); 7 | assert.isString(keywords.value, `keywords.value isn't a string`); 8 | assert.isDefined(keywords.onChangeKeywords, `keywords.onChangeKeywords isn't defined`); 9 | assert.isFunction(keywords.onChangeKeywords, `keywords.onChangeKeywords isn't a function`); 10 | } 11 | -------------------------------------------------------------------------------- /test/assertions/links.js: -------------------------------------------------------------------------------- 1 | import { assert } from 'chai'; 2 | import assertLink from '../../test/assertions/common/link'; 3 | 4 | 5 | export default function(links) { 6 | describe('augur-ui-react-components links state', () => { 7 | assert.isDefined(links, `links isn't defined`); 8 | assert.isObject(links, `links isn't an object`); 9 | 10 | it('authLink', () => { 11 | assertLink(links.authLink, 'authLink'); 12 | }); 13 | 14 | it('marketsLink', () => { 15 | assertLink(links.marketsLink, 'marketsLink'); 16 | }); 17 | 18 | it('transactionsLink', () => { 19 | assertLink(links.transactionsLink, 'transactionsLink'); 20 | }); 21 | 22 | it('marketLink', () => { 23 | assertLink(links.marketLink, 'marketLink'); 24 | }); 25 | 26 | it('previousLink', () => { 27 | assertLink(links.previousLink, 'previousLink'); 28 | }); 29 | 30 | it('createMarketLink', () => { 31 | assertLink(links.createMarketLink, 'createMarketLink'); 32 | }); 33 | 34 | it('loginMessageLink', () => { 35 | assertLink(links.loginMessageLink, 'loginMessageLink'); 36 | }); 37 | }); 38 | }; 39 | -------------------------------------------------------------------------------- /test/assertions/login-account-markets.js: -------------------------------------------------------------------------------- 1 | import { assert } from 'chai'; 2 | 3 | export default function (loginAccountMarkets){ 4 | describe(`augur-ui-react-components loginAccountMarket's shape`, () => { 5 | assert.isDefined(loginAccountMarkets); 6 | assert.isObject(loginAccountMarkets); 7 | }); 8 | }; 9 | -------------------------------------------------------------------------------- /test/assertions/login-account-positions.js: -------------------------------------------------------------------------------- 1 | import { assert } from 'chai'; 2 | 3 | export default function (loginAccountPositions){ 4 | describe(`augur-ui-react-components loginAccountPositions' shape`, () => { 5 | assert.isDefined(loginAccountPositions); 6 | assert.isObject(loginAccountPositions); 7 | 8 | it('markets', () => { 9 | assert.isDefined(loginAccountPositions.markets); 10 | assert.isArray(loginAccountPositions.markets); 11 | }); 12 | 13 | it('summary', () => { 14 | assert.isDefined(loginAccountPositions.summary); 15 | assert.isObject(loginAccountPositions.summary); 16 | }); 17 | }); 18 | }; -------------------------------------------------------------------------------- /test/assertions/login-account-reports.js: -------------------------------------------------------------------------------- 1 | import { assert } from 'chai'; 2 | 3 | export default function (loginAccountReports){ 4 | describe(`augur-ui-react-components loginAccountReports' shape`, () => { 5 | assert.isDefined(loginAccountReports); 6 | assert.isObject(loginAccountReports); 7 | 8 | it('reports', () => { 9 | assert.isDefined(loginAccountReports.reports); 10 | assert.isArray(loginAccountReports.reports); 11 | }); 12 | 13 | it('summary', () => { 14 | assert.isDefined(loginAccountReports.summary); 15 | assert.isObject(loginAccountReports.summary); 16 | }); 17 | }); 18 | }; 19 | -------------------------------------------------------------------------------- /test/assertions/market-data-age.js: -------------------------------------------------------------------------------- 1 | import {assert} from 'chai'; 2 | 3 | export default function (marketDataAge) { 4 | describe('augur-ui-react-components marketDataAge', () => { 5 | it('marketDataAge', () => { 6 | assert.isObject(marketDataAge); 7 | }); 8 | 9 | it('marketDataAge.lastUpdatedBefore', () => { 10 | assert.isString(marketDataAge.lastUpdatedBefore); 11 | }); 12 | 13 | it('marketDataAge.isMarketDataLoading', () => { 14 | assert.isBoolean(marketDataAge.isMarketDataLoading); 15 | }); 16 | }); 17 | } 18 | -------------------------------------------------------------------------------- /test/assertions/market-data-nav-items.js: -------------------------------------------------------------------------------- 1 | import { assert } from 'chai'; 2 | 3 | import assertComponentNavItem from './common/component-nav'; 4 | 5 | export default function (marketDataNavItems) { 6 | assert.isDefined(marketDataNavItems, `marketDataNavItems isn't defined`); 7 | assert.isObject(marketDataNavItems, `marketDataNavItems isn't an object`); 8 | 9 | Object.keys(marketDataNavItems).forEach(navItem => { 10 | assertComponentNavItem(marketDataNavItems[navItem], navItem); 11 | }); 12 | } 13 | -------------------------------------------------------------------------------- /test/assertions/market-data-updater.js: -------------------------------------------------------------------------------- 1 | import {assert} from 'chai'; 2 | 3 | export default function (marketDataUpdater) { 4 | describe('augur-ui-react-components marketDataUpdater', () => { 5 | it('marketDataUpdater', () => { 6 | assert.isObject(marketDataUpdater); 7 | }); 8 | 9 | it('marketDataUpdater.update', () => { 10 | assert.isFunction(marketDataUpdater.update); 11 | }); 12 | 13 | it('marketDataUpdater.updateIntervalSecs', () => { 14 | assert.isNumber(marketDataUpdater.updateIntervalSecs); 15 | }); 16 | }); 17 | } 18 | -------------------------------------------------------------------------------- /test/assertions/market-reporting-nav-items.js: -------------------------------------------------------------------------------- 1 | import { assert } from 'chai'; 2 | 3 | import assertComponentNavItem from './common/component-nav'; 4 | 5 | export default function (marketReportingNavItems) { 6 | assert.isDefined(marketReportingNavItems, `marketReportingNavItems isn't defined`); 7 | assert.isObject(marketReportingNavItems, `marketReportingNavItems isn't an object`); 8 | 9 | Object.keys(marketReportingNavItems).forEach(navItem => { 10 | assertComponentNavItem(marketReportingNavItems[navItem], navItem); 11 | }); 12 | } 13 | -------------------------------------------------------------------------------- /test/assertions/market-user-data-nav-items.js: -------------------------------------------------------------------------------- 1 | import { assert } from 'chai'; 2 | 3 | import assertComponentNavItem from './common/component-nav'; 4 | 5 | export default function (marketUserDataNavItems) { 6 | assert.isDefined(marketUserDataNavItems, `marketUserDataNavItems isn't defined`); 7 | assert.isObject(marketUserDataNavItems, `marketUserDataNavItems isn't an object`); 8 | 9 | Object.keys(marketUserDataNavItems).forEach(navItem => { 10 | assertComponentNavItem(marketUserDataNavItems[navItem], navItem); 11 | }); 12 | } 13 | -------------------------------------------------------------------------------- /test/assertions/markets-header.js: -------------------------------------------------------------------------------- 1 | import { assert } from 'chai'; 2 | 3 | export default function(marketsHeader) { 4 | assert.isDefined(marketsHeader, `marketsHeader isn't defined`); 5 | assert.isObject(marketsHeader, `marketsHeader isn't an object`); 6 | } 7 | -------------------------------------------------------------------------------- /test/assertions/markets-totals.js: -------------------------------------------------------------------------------- 1 | import { assert } from 'chai'; 2 | 3 | export default function(marketsTotals) { 4 | assert.isDefined(marketsTotals, `marketsTotals isn't defined`); 5 | assert.isObject(marketsTotals, `marketsTotals isn't an object`); 6 | 7 | checkDefinedAndNumber(marketsTotals.numAll, `numAll`); 8 | checkDefinedAndNumber(marketsTotals.numFavorites, `numFavorites`); 9 | checkDefinedAndNumber(marketsTotals.numFiltered, `numFiltered`); 10 | checkDefinedAndNumber(marketsTotals.numPendingReports, `numPendingReports`); 11 | checkDefinedAndNumber(marketsTotals.numUnpaginated, `numUnpaginated`); 12 | } 13 | 14 | 15 | function checkDefinedAndNumber(obj, name) { 16 | assert.isDefined(obj, `marketsTotals.${name} isn't defined`); 17 | assert.isNumber(obj, `marketsTotals.${name} isn't a number`); 18 | } 19 | -------------------------------------------------------------------------------- /test/assertions/markets.js: -------------------------------------------------------------------------------- 1 | import { assert } from 'chai'; 2 | 3 | export default function (markets) { 4 | assert.isDefined(markets, `markets is not defined`); 5 | assert.isArray(markets, `markets isn't an array`); 6 | } 7 | -------------------------------------------------------------------------------- /test/assertions/my-markets-summary.js: -------------------------------------------------------------------------------- 1 | import { assert } from 'chai'; 2 | 3 | export default function (myMarketsSummary){ 4 | describe(`augur-ui-react-components myMarketsSummary's shape`, () => { 5 | assert.isDefined(myMarketsSummary); 6 | assert.isObject(myMarketsSummary); 7 | 8 | assertMyMarketsSummary(myMarketsSummary); 9 | }); 10 | }; 11 | 12 | export function assertMyMarketsSummary(summary){ 13 | describe(`summary's shape`, () => { 14 | assert.isDefined(summary); 15 | assert.isObject(summary); 16 | 17 | it('numMarkets', () => { 18 | assert.isDefined(summary.numMarkets); 19 | assert.isNumber(summary.numMarkets); 20 | }); 21 | }); 22 | }; 23 | -------------------------------------------------------------------------------- /test/assertions/my-reports-summary.js: -------------------------------------------------------------------------------- 1 | import { assert } from 'chai'; 2 | import assertFormattedNumber from '../../test/assertions/common/formatted-number'; 3 | 4 | export default function (reportsSummary) { 5 | assert.isDefined(reportsSummary, `reportsSummary isn't defined`); 6 | assert.isObject(reportsSummary, `reportsSummary isn't an object`); 7 | 8 | assertFormattedNumber(reportsSummary.numReports, 'reportsSummary.numReports'); 9 | assertFormattedNumber(reportsSummary.netRep, 'reportsSummary.netRep'); 10 | }; 11 | 12 | -------------------------------------------------------------------------------- /test/assertions/order-cancellation.js: -------------------------------------------------------------------------------- 1 | import { assert } from 'chai'; 2 | 3 | export default function (orderCancellation) { 4 | describe('augur-ui-react-components orderCancellation', () => { 5 | it('orderCancellation', () => { 6 | assert.isObject(orderCancellation); 7 | }); 8 | 9 | it('orderCancellation.cancelOrder', () => { 10 | assert.isFunction(orderCancellation.cancelOrder); 11 | }); 12 | 13 | it('orderCancellation.abortCancelOrderConfirmation', () => { 14 | assert.isFunction(orderCancellation.abortCancelOrderConfirmation); 15 | }); 16 | 17 | it('orderCancellation.showCancelOrderConfirmation', () => { 18 | assert.isFunction(orderCancellation.showCancelOrderConfirmation); 19 | }); 20 | 21 | it('orderCancellation.cancellationStatuses', () => { 22 | assert.isObject(orderCancellation.cancellationStatuses); 23 | assert.deepEqual(orderCancellation.cancellationStatuses, { 24 | CANCELLATION_CONFIRMATION: 'CANCELLATION_CONFIRMATION', 25 | CANCELLING: 'CANCELLING', 26 | CANCELLED: 'CANCELLED', 27 | CANCELLATION_FAILED: 'CANCELLATION_FAILED' 28 | }); 29 | }); 30 | }); 31 | }; 32 | -------------------------------------------------------------------------------- /test/assertions/outcome-trade-nav-items.js: -------------------------------------------------------------------------------- 1 | import { assert } from 'chai'; 2 | 3 | import assertComponentNavItem from './common/component-nav'; 4 | 5 | export default function (marketDataNavItems) { 6 | assert.isDefined(marketDataNavItems, `marketDataNavItems isn't defined`); 7 | assert.isObject(marketDataNavItems, `marketDataNavItems isn't an object`); 8 | 9 | Object.keys(marketDataNavItems).forEach(navItem => { 10 | assertComponentNavItem(marketDataNavItems[navItem], navItem); 11 | }); 12 | } 13 | -------------------------------------------------------------------------------- /test/assertions/portfolio-nav-items.js: -------------------------------------------------------------------------------- 1 | import { assert } from 'chai'; 2 | 3 | import assertNavItem from './common/nav-item'; 4 | 5 | export default function (portfolioNavItems){ 6 | describe(`augur-ui-react-components portfolio's navItems state`, () => { 7 | assert.isDefined(portfolioNavItems); 8 | assert.isArray(portfolioNavItems); 9 | 10 | portfolioNavItems.forEach(navItem => { assertNavItem(navItem, 'portfolio.navItem') }); 11 | }); 12 | }; -------------------------------------------------------------------------------- /test/assertions/portfolio-summaries.js: -------------------------------------------------------------------------------- 1 | import { assert } from 'chai'; 2 | 3 | export default function (portfolioSummaries){ 4 | describe(`augur-ui-react-components portfolio's summaries shape`, () => { 5 | assert.isDefined(portfolioSummaries); 6 | assert.isArray(portfolioSummaries); 7 | 8 | portfolioSummaries.forEach(summary => { assertSummary(summary) }); 9 | }); 10 | } 11 | 12 | function assertSummary(summary){ 13 | describe(`summary's shape`, () => { 14 | it('label', () => { 15 | assert.isDefined(summary.label); 16 | assert.isString(summary.label); 17 | }); 18 | 19 | it('value', () => { 20 | assert.isDefined(summary.value); 21 | assert.isString(summary.value); 22 | }); 23 | }); 24 | }; 25 | -------------------------------------------------------------------------------- /test/assertions/portfolio-totals.js: -------------------------------------------------------------------------------- 1 | import { assert } from 'chai'; 2 | 3 | import assertFormattedNumber from '../../test/assertions/common/formatted-number'; 4 | 5 | export default function (portfolioTotals){ 6 | describe(`augur-ui-react-components portfolioTotals' shape`, () => { 7 | assert.isDefined(portfolioTotals); 8 | assert.isObject(portfolioTotals); 9 | 10 | it('net', () => { 11 | assert.isDefined(portfolioTotals.netChange); 12 | assertFormattedNumber(portfolioTotals.netChange, 'portfolio.totals.netChange'); 13 | }); 14 | }); 15 | }; -------------------------------------------------------------------------------- /test/assertions/portfolio.js: -------------------------------------------------------------------------------- 1 | import { assert } from 'chai'; 2 | 3 | export default function (portfolio){ 4 | describe('augur-ui-react-components portfolio state', () => { 5 | assert.isDefined(portfolio); 6 | assert.isObject(portfolio); 7 | }); 8 | }; -------------------------------------------------------------------------------- /test/assertions/positions-summary.js: -------------------------------------------------------------------------------- 1 | import { assert } from 'chai'; 2 | import assertFormattedNumber from '../../test/assertions/common/formatted-number'; 3 | 4 | export default function (positionsSummary) { 5 | assert.isDefined(positionsSummary, `positionsSummary isn't defined`); 6 | assert.isObject(positionsSummary, `positionsSummary isn't an object`); 7 | 8 | assertFormattedNumber(positionsSummary.numPositions, 'positionsSummary.numPositions'); 9 | assertFormattedNumber(positionsSummary.purchasePrice, 'positionsSummary.purchasePrice'); 10 | assertFormattedNumber(positionsSummary.qtyShares, 'positionsSummary.qtyShares'); 11 | assertFormattedNumber(positionsSummary.realizedNet, 'positionsSummary.realizedNet'); 12 | assertFormattedNumber(positionsSummary.unrealizedNet, 'positionsSummary.unrealizedNet'); 13 | assertFormattedNumber(positionsSummary.totalNet, 'positionsSummary.totalNet'); 14 | }; 15 | 16 | -------------------------------------------------------------------------------- /test/assertions/reportable-outcomes.js: -------------------------------------------------------------------------------- 1 | import { assert } from 'chai'; 2 | 3 | export default function (reportableOutcomes) { 4 | describe(`augur-ui-react-components reportableOutcomes' shape`, () => { 5 | assert.isDefined(reportableOutcomes, `'reportableOutcomes' is not defined`); 6 | assert.isArray(reportableOutcomes, `'reportableOutcomes' is not an array`); 7 | 8 | reportableOutcomes.forEach(outcome => { 9 | it('id', () => { 10 | assert.isDefined(outcome.id, `reportableOutcomes' id is not defined`); 11 | assert.isString(outcome.id, `reportableOutcomes' id is not a string`); 12 | }); 13 | 14 | it('name', () => { 15 | assert.isDefined(outcome.name, `reportableOutcomes' name is not defined`); 16 | assert.isString(outcome.name, `reportableOutcomes' name is not a string`); 17 | }); 18 | }); 19 | }); 20 | }; -------------------------------------------------------------------------------- /test/assertions/scalar-share-denomination.js: -------------------------------------------------------------------------------- 1 | import { assert } from 'chai'; 2 | 3 | export default function (scalarShareDenomination) { 4 | assert.isDefined(scalarShareDenomination, `scalarShareDenomination isn't defined`); 5 | assert.isObject(scalarShareDenomination, `scalarShareDenomination isn't an object`); 6 | 7 | 8 | describe('scalarShareDenomination.markets', () => { 9 | const markets = scalarShareDenomination.markets; 10 | 11 | assert.isDefined(markets, `markets isn't defined`); 12 | assert.isObject(markets, `markets isn't an object`); 13 | 14 | Object.keys(markets || {}).forEach(market => { 15 | assert.isDefined(markets[market], `markets.market isn't defined`); 16 | assert.isString(markets[market], `markets.market isn't a string`); 17 | }); 18 | 19 | }); 20 | 21 | describe('scalarShareDenomination.denominations', () => { 22 | const denominations = scalarShareDenomination.denominations; 23 | 24 | assert.isDefined(denominations, `denominations isn't defined`); 25 | assert.isArray(denominations, `denominations isn't an array`); 26 | 27 | (denominations || []).forEach(denomination => { 28 | assert.isDefined(denomination, `denominations.denomination isn't defined`); 29 | assert.isObject(denomination, `denominations.denomination isn't an object`); 30 | 31 | assert.isDefined(denomination.label, `denomination.label isn't defined`); 32 | assert.isString(denomination.label, `denomination.label isn't a string`); 33 | 34 | assert.isDefined(denomination.value, `denomination.value isn't defined`); 35 | assert.isString(denomination.value, `denomination.value isn't a string`); 36 | }); 37 | }); 38 | 39 | assert.isDefined(scalarShareDenomination.updateSelectedShareDenomination, `updateSelectedShareDenomination isn't defined`); 40 | assert.isFunction(scalarShareDenomination.updateSelectedShareDenomination, `updateSelectedShareDenomination isn't a function`); 41 | } 42 | -------------------------------------------------------------------------------- /test/assertions/search-sort.js: -------------------------------------------------------------------------------- 1 | import { assert } from 'chai'; 2 | 3 | export default function(searchSort) { 4 | assert.isDefined(searchSort, `searchSort isn't defined`); 5 | assert.isObject(searchSort, `searchSort isn't an object`); 6 | assert.isDefined(searchSort.onChangeSort, `searchSort.onChangeSort isn't defined`); 7 | assert.isFunction(searchSort.onChangeSort, `searchSort.onChangeSort isn't a function`); 8 | assertionSelectedSort(searchSort.selectedSort); 9 | assertionSortOptions(searchSort.sortOptions); 10 | } 11 | 12 | function assertionSelectedSort(actual) { 13 | assert.isDefined(actual, `selectedSort isn't defined`); 14 | assert.isObject(actual, `selectedSort isn't an Object`); 15 | assert.isDefined(actual.prop, `selectedSort.prop isn't defined`); 16 | assert.isString(actual.prop, `selectedSort.prop isn't a string`); 17 | assert.isDefined(actual.isDesc, `selectedSort.isDesc isn't defined`); 18 | assert.isBoolean(actual.isDesc, `selectedSort.isDesc isn't a boolean`); 19 | } 20 | 21 | function assertionSortOptions(actual) { 22 | assert.isDefined(actual, `sortOptions isn't defined`); 23 | assert.isArray(actual, `sortOptions isn't an array`); 24 | 25 | assert.isDefined(actual[0], `sortOptions[0] doesn't exist`); 26 | assert.isObject(actual[0], `sortOptions[0] isn't an object`); 27 | assert.isDefined(actual[0].label, `sortOptions[0].label isn't defined`); 28 | assert.isString(actual[0].label, `sortOptions[0].label isn't a string`); 29 | assert.isDefined(actual[0].value, `sortOptions[0].value isn't defined`); 30 | assert.isString(actual[0].value, `sortOptions[0].value isn't a string`); 31 | } 32 | 33 | -------------------------------------------------------------------------------- /test/assertions/selected-outcome.js: -------------------------------------------------------------------------------- 1 | import { assert } from 'chai'; 2 | 3 | export default function (selectedOutcome) { 4 | assert.isObject(selectedOutcome, `selectedOutcome isn't an object`); 5 | assert.isDefined(selectedOutcome.selectedOutcomeID, `selectedOutcome isn't defined`); 6 | assert.isFunction(selectedOutcome.updateSelectedOutcome, `updateSelectedOutcome isn't a function`); 7 | assert.isDefined(selectedOutcome.updateSelectedOutcome, `updateSelectedOutcome isn't defined`); 8 | }; 9 | 10 | -------------------------------------------------------------------------------- /test/assertions/selected-user-open-orders-group.js: -------------------------------------------------------------------------------- 1 | import { assert } from 'chai'; 2 | 3 | export default function (selectedUserOpenOrdersGroup) { 4 | describe('augur-ui-react-components selectedUserOpenOrdersGroup', () => { 5 | it('should exist', () => { 6 | assert.isDefined(selectedUserOpenOrdersGroup, `selectedUserOpenOrdersGroup is empty.`); 7 | }); 8 | 9 | it('should be object', () => { 10 | assert.isObject(selectedUserOpenOrdersGroup, `selectedUserOpenOrdersGroup is not object.`); 11 | }); 12 | 13 | describe('selectedUserOpenOrdersGroupID', () => { 14 | it('should exist', () => { 15 | assert.isDefined(selectedUserOpenOrdersGroup.selectedUserOpenOrdersGroupID, `selectedUserOpenOrdersGroupID is not defined.`); 16 | }); 17 | }); 18 | 19 | describe('updateSelectedUserOpenOrdersGroup', () => { 20 | it('should be function', () => { 21 | assert.isFunction(selectedUserOpenOrdersGroup.updateSelectedUserOpenOrdersGroup, `updateSelectedUserOpenOrdersGroup is not function.`); 22 | }); 23 | }); 24 | }); 25 | }; 26 | -------------------------------------------------------------------------------- /test/assertions/settings.js: -------------------------------------------------------------------------------- 1 | import { assert } from 'chai'; 2 | 3 | export default function (settings) { 4 | assert.isDefined(settings, `settings isn't defined`); 5 | assert.isObject(settings, `settings isn't an object`); 6 | 7 | // TODO -- needs to be fleshed out 8 | } 9 | -------------------------------------------------------------------------------- /test/assertions/site-header.js: -------------------------------------------------------------------------------- 1 | import { assert } from 'chai'; 2 | import assertLoginAccount from './login-account'; 3 | import assertActivePage from './active-view'; 4 | import assertPositionsSummary from './positions-summary'; 5 | import assertTransactionsTotals from './transactions-totals'; 6 | import assertIsTransactionsWorking from './is-transactions-working'; 7 | 8 | export default function(siteHeader) { 9 | assert.isDefined(siteHeader, `siteHeader isn't defined`); 10 | assert.isObject(siteHeader, `siteHeader isn't a object`); 11 | assertLoginAccount(siteHeader.loginAccount); 12 | assertActivePage(siteHeader.activePage); 13 | assertPositionsSummary(siteHeader.positionsSummary); 14 | assertTransactionsTotals(siteHeader.transactionsTotals); 15 | assertIsTransactionsWorking(siteHeader.isTransactionsWorking); 16 | } 17 | -------------------------------------------------------------------------------- /test/assertions/tags.js: -------------------------------------------------------------------------------- 1 | import { assert } from 'chai'; 2 | 3 | export default function (tags) { 4 | 5 | assert.isDefined(tags, `filters isn't defined`); 6 | assert.isArray(tags, `filters isn't an array`); 7 | 8 | tags.forEach((tag) => { 9 | assert.isDefined(tag, `[0].options[0] isn't defined`); 10 | assert.isObject(tag, `[0].options[0] isn't a object`); 11 | 12 | assert.isDefined(tag.name, `[0].options[0].name isn't defined`); 13 | assert.isString(tag.name, `[0].options[0].name isn't a string`); 14 | 15 | assert.isDefined(tag.value, `[0].options[0].value isn't defined`); 16 | assert.isString(tag.value, `[0].options[0].value isn't a string`); 17 | 18 | assert.isDefined(tag.numMatched, `[0].options[0].numMatched isn't defined`); 19 | assert.isNumber(tag.numMatched, `[0].options[0].numMatched isn't a number`); 20 | 21 | assert.isDefined(tag.isSelected, `[0].options[0].isSelected isn't defined`); 22 | assert.isBoolean(tag.isSelected, `[0].options[0].isSelected isn't a boolean`); 23 | 24 | assert.isDefined(tag.onClick, `[0].options[0].onClick isn't defined`); 25 | assert.isFunction(tag.onClick, `[0].options[0].onClick isn't a function`); 26 | }); 27 | } 28 | -------------------------------------------------------------------------------- /test/assertions/trade-commit-lock.js: -------------------------------------------------------------------------------- 1 | import { assert } from 'chai'; 2 | 3 | export default function (tradeCommitLock) { 4 | assert.isDefined(tradeCommitLock, 'tradeCommitLock is not defined'); 5 | assert.isObject(tradeCommitLock, 'tradeCommitLock is not an object'); 6 | 7 | it('isLocked', () => { 8 | assert.isDefined(tradeCommitLock.isLocked, `'tradeCommitLock.isLocked' is not defined`); 9 | assert.isBoolean(tradeCommitLock.isLocked, `'tradeCommitLock.isLocked' is not a boolean`); 10 | }); 11 | } -------------------------------------------------------------------------------- /test/assertions/transactions-totals.js: -------------------------------------------------------------------------------- 1 | import { assert } from 'chai'; 2 | 3 | export default function(transactionsTotals) { 4 | assert.isObject(transactionsTotals); 5 | 6 | assert.isString(transactionsTotals.title); 7 | assert.isString(transactionsTotals.shortTitle); 8 | 9 | assert.isNumber(transactionsTotals.numWorking); 10 | assert.isNumber(transactionsTotals.numPending); 11 | assert.isNumber(transactionsTotals.numComplete); 12 | assert.isNumber(transactionsTotals.numWorkingAndPending); 13 | assert.isNumber(transactionsTotals.numTotal); 14 | } 15 | -------------------------------------------------------------------------------- /test/assertions/transactions.js: -------------------------------------------------------------------------------- 1 | import { assert } from 'chai'; 2 | 3 | export default function (transactions) { 4 | assert.isDefined(transactions, `transactions isn't defined`); 5 | assert.isArray(transactions, `transactions isn't an array`); 6 | 7 | transactions.forEach(transaction => assertTransaction(transactions[0])); 8 | } 9 | 10 | function assertTransaction(transaction) { 11 | assert.isString(transaction.id); 12 | assert.isString(transaction.type); 13 | assert.isString(transaction.status); 14 | if (transaction.data) { 15 | assert.isObject(transaction); 16 | } 17 | } -------------------------------------------------------------------------------- /test/assertions/url.js: -------------------------------------------------------------------------------- 1 | import { assert } from 'chai'; 2 | 3 | export default function (url) { 4 | assert.isDefined(url, `url isn't defined`); 5 | assert.isString(url, `url isn't a string`); 6 | } -------------------------------------------------------------------------------- /test/mocha.opts: -------------------------------------------------------------------------------- 1 | --compilers js:babel-register 2 | --recursive 3 | -------------------------------------------------------------------------------- /test/selectors-test.js: -------------------------------------------------------------------------------- 1 | import selectors from '../src/selectors'; 2 | import assertions from '../src/assertions'; 3 | 4 | Object.defineProperty(selectors, 'render', { 5 | value: () => console.log('fake render'), 6 | enumerable: false 7 | }); 8 | 9 | Object.keys(selectors).forEach(selectorKey => { 10 | console.log('-->', selectorKey); 11 | if (typeof assertions[selectorKey] !== 'function') { 12 | throw new Error(`missing assertion ${selectorKey}`) 13 | } 14 | assertions[selectorKey](selectors[selectorKey]); 15 | }); 16 | --------------------------------------------------------------------------------