From f804c535224969eca81f2e7e039f7cff501d12a5 Mon Sep 17 00:00:00 2001 From: Ben Gotow Date: Mon, 28 Nov 2016 18:02:39 -0800 Subject: [PATCH] [dashboard] Put dashboard into work window --- .../public => }/images/close.png | Bin .../public => }/images/dropdown.png | Bin packages/local-sync/main.es6 | 9 +- .../src/local-sync-dashboard/app.js | 49 - .../{public/js => }/dropdown.jsx | 6 +- .../{public/js => }/elapsed-time.jsx | 7 +- .../{public/js => }/modal.jsx | 6 +- .../src/local-sync-dashboard/newrelic.js | 21 - .../local-sync-dashboard/public/css/app.css | 261 - .../local-sync-dashboard/public/favicon.png | Bin 2439 -> 0 bytes .../local-sync-dashboard/public/index.html | 27 - .../public/js/account-filter.jsx | 26 - .../local-sync-dashboard/public/js/app.jsx | 333 - .../public/js/mini-account.jsx | 40 - .../public/js/process-loads.jsx | 37 - .../public/js/react-dom.js | 42 - .../public/js/react-dom.min.js | 12 - .../local-sync-dashboard/public/js/react.js | 19599 ---------------- .../public/js/react.min.js | 16 - .../src/local-sync-dashboard/root.jsx | 181 + .../local-sync-dashboard/routes/account.js | 30 - .../routes/syncback-requests.js | 81 - .../{public/js => }/set-all-sync-policies.jsx | 8 +- .../{public/js => }/sync-graph.jsx | 8 +- .../{public/js => }/sync-policy.jsx | 6 +- .../js => }/syncback-request-details.jsx | 9 +- .../local-sync-worker/sync-process-manager.js | 6 +- packages/local-sync/stylesheets/index.less | 216 + 28 files changed, 426 insertions(+), 20610 deletions(-) rename packages/local-sync/{src/local-sync-dashboard/public => }/images/close.png (100%) rename packages/local-sync/{src/local-sync-dashboard/public => }/images/dropdown.png (100%) delete mode 100644 packages/local-sync/src/local-sync-dashboard/app.js rename packages/local-sync/src/local-sync-dashboard/{public/js => }/dropdown.jsx (94%) rename packages/local-sync/src/local-sync-dashboard/{public/js => }/elapsed-time.jsx (83%) rename packages/local-sync/src/local-sync-dashboard/{public/js => }/modal.jsx (96%) delete mode 100644 packages/local-sync/src/local-sync-dashboard/newrelic.js delete mode 100644 packages/local-sync/src/local-sync-dashboard/public/css/app.css delete mode 100644 packages/local-sync/src/local-sync-dashboard/public/favicon.png delete mode 100644 packages/local-sync/src/local-sync-dashboard/public/index.html delete mode 100644 packages/local-sync/src/local-sync-dashboard/public/js/account-filter.jsx delete mode 100644 packages/local-sync/src/local-sync-dashboard/public/js/app.jsx delete mode 100644 packages/local-sync/src/local-sync-dashboard/public/js/mini-account.jsx delete mode 100644 packages/local-sync/src/local-sync-dashboard/public/js/process-loads.jsx delete mode 100644 packages/local-sync/src/local-sync-dashboard/public/js/react-dom.js delete mode 100644 packages/local-sync/src/local-sync-dashboard/public/js/react-dom.min.js delete mode 100644 packages/local-sync/src/local-sync-dashboard/public/js/react.js delete mode 100644 packages/local-sync/src/local-sync-dashboard/public/js/react.min.js create mode 100644 packages/local-sync/src/local-sync-dashboard/root.jsx delete mode 100644 packages/local-sync/src/local-sync-dashboard/routes/account.js delete mode 100644 packages/local-sync/src/local-sync-dashboard/routes/syncback-requests.js rename packages/local-sync/src/local-sync-dashboard/{public/js => }/set-all-sync-policies.jsx (90%) rename packages/local-sync/src/local-sync-dashboard/{public/js => }/sync-graph.jsx (94%) rename packages/local-sync/src/local-sync-dashboard/{public/js => }/sync-policy.jsx (94%) rename packages/local-sync/src/local-sync-dashboard/{public/js => }/syncback-request-details.jsx (96%) create mode 100644 packages/local-sync/stylesheets/index.less diff --git a/packages/local-sync/src/local-sync-dashboard/public/images/close.png b/packages/local-sync/images/close.png similarity index 100% rename from packages/local-sync/src/local-sync-dashboard/public/images/close.png rename to packages/local-sync/images/close.png diff --git a/packages/local-sync/src/local-sync-dashboard/public/images/dropdown.png b/packages/local-sync/images/dropdown.png similarity index 100% rename from packages/local-sync/src/local-sync-dashboard/public/images/dropdown.png rename to packages/local-sync/images/dropdown.png diff --git a/packages/local-sync/main.es6 b/packages/local-sync/main.es6 index bd555b299..14da6c9e0 100644 --- a/packages/local-sync/main.es6 +++ b/packages/local-sync/main.es6 @@ -1,9 +1,14 @@ +/* eslint global-require: 0 */ +import {ComponentRegistry} from 'nylas-exports' import {createLogger} from './src/shared/logger' export function activate() { global.Logger = createLogger('local-sync') - require('./src/local-api/app.js'); - require('./src/local-sync-worker/app.js'); + require('./src/local-api/app'); + require('./src/local-sync-worker/app'); + + const Root = require('./src/local-sync-dashboard/root').default; + ComponentRegistry.register(Root, {role: 'Developer:LocalSyncUI'}); } export function deactivate() { diff --git a/packages/local-sync/src/local-sync-dashboard/app.js b/packages/local-sync/src/local-sync-dashboard/app.js deleted file mode 100644 index d9719213d..000000000 --- a/packages/local-sync/src/local-sync-dashboard/app.js +++ /dev/null @@ -1,49 +0,0 @@ -const fs = require('fs'); -const path = require('path'); -const Inert = require('inert'); -const Hapi = require('hapi'); -const HapiWebSocket = require('hapi-plugin-websocket'); - -const server = new Hapi.Server(); -server.connection({ port: process.env.PORT }); - -const attach = (directory) => { - const routesDir = path.join(__dirname, directory) - fs.readdirSync(routesDir).forEach((filename) => { - if (filename.endsWith('.js')) { - const routeFactory = require(path.join(routesDir, filename)); - routeFactory(server); - } - }); -} - -server.register([HapiWebSocket, Inert], () => { - attach('./routes/') - - server.route({ - method: 'GET', - path: '/ping', - config: { - auth: false, - }, - handler: (request, reply) => { - global.Logger.info("---> Ping!") - reply("pong") - }, - }); - - server.route({ - method: 'GET', - path: '/{param*}', - handler: { - directory: { - path: require('path').join(__dirname, 'public'), - }, - }, - }); - - server.start((startErr) => { - if (startErr) { throw startErr; } - global.Logger.info({uri: server.info.uri}, 'Dashboard running'); - }); -}); diff --git a/packages/local-sync/src/local-sync-dashboard/public/js/dropdown.jsx b/packages/local-sync/src/local-sync-dashboard/dropdown.jsx similarity index 94% rename from packages/local-sync/src/local-sync-dashboard/public/js/dropdown.jsx rename to packages/local-sync/src/local-sync-dashboard/dropdown.jsx index c09f78d64..31a8f7a19 100644 --- a/packages/local-sync/src/local-sync-dashboard/public/js/dropdown.jsx +++ b/packages/local-sync/src/local-sync-dashboard/dropdown.jsx @@ -1,6 +1,6 @@ -const React = window.React; +import {React} from 'nylas-exports'; -class Dropdown extends React.Component { +export default class Dropdown extends React.Component { constructor(props) { super(props); this.state = { @@ -67,5 +67,3 @@ Dropdown.propTypes = { defaultOption: React.PropTypes.string, onSelect: React.PropTypes.func, } - -window.Dropdown = Dropdown; diff --git a/packages/local-sync/src/local-sync-dashboard/public/js/elapsed-time.jsx b/packages/local-sync/src/local-sync-dashboard/elapsed-time.jsx similarity index 83% rename from packages/local-sync/src/local-sync-dashboard/public/js/elapsed-time.jsx rename to packages/local-sync/src/local-sync-dashboard/elapsed-time.jsx index ecad76b01..c8b2b2a4d 100644 --- a/packages/local-sync/src/local-sync-dashboard/public/js/elapsed-time.jsx +++ b/packages/local-sync/src/local-sync-dashboard/elapsed-time.jsx @@ -1,12 +1,11 @@ -const React = window.React; -const ReactDOM = window.ReactDOM; +import {React, ReactDOM} from 'nylas-exports'; setInterval(() => { const event = new Event('tick'); window.dispatchEvent(event); }, 1000); -class ElapsedTime extends React.Component { +export default class ElapsedTime extends React.Component { constructor(props) { super(props); this.state = { @@ -36,5 +35,3 @@ ElapsedTime.propTypes = { refTimestamp: React.PropTypes.number, // milliseconds formatTime: React.PropTypes.func, } - -window.ElapsedTime = ElapsedTime; diff --git a/packages/local-sync/src/local-sync-dashboard/public/js/modal.jsx b/packages/local-sync/src/local-sync-dashboard/modal.jsx similarity index 96% rename from packages/local-sync/src/local-sync-dashboard/public/js/modal.jsx rename to packages/local-sync/src/local-sync-dashboard/modal.jsx index bcc8587f2..b8c350454 100644 --- a/packages/local-sync/src/local-sync-dashboard/public/js/modal.jsx +++ b/packages/local-sync/src/local-sync-dashboard/modal.jsx @@ -1,6 +1,6 @@ -const React = window.React; +import {React} from 'nylas-exports'; -class Modal extends React.Component { +export default class Modal extends React.Component { constructor(props) { super(props); this.state = { @@ -101,5 +101,3 @@ Modal.propTypes = { onClose: React.PropTypes.func, actionElems: React.PropTypes.arrayOf(React.PropTypes.object), } - -window.Modal = Modal; diff --git a/packages/local-sync/src/local-sync-dashboard/newrelic.js b/packages/local-sync/src/local-sync-dashboard/newrelic.js deleted file mode 100644 index 97cd18e90..000000000 --- a/packages/local-sync/src/local-sync-dashboard/newrelic.js +++ /dev/null @@ -1,21 +0,0 @@ -const {NODE_ENV} = process.env -/** - * New Relic agent configuration. - * - * See lib/config.defaults.js in the agent distribution for a more complete - * description of configuration variables and their potential values. - */ -exports.config = { - /** - * Array of application names. - */ - app_name: [`k2-dash-${NODE_ENV}`], - logging: { - /** - * Level at which to log. 'trace' is most useful to New Relic when diagnosing - * issues with the agent, 'info' and higher will impose the least overhead on - * production applications. - */ - level: 'info', - }, -} diff --git a/packages/local-sync/src/local-sync-dashboard/public/css/app.css b/packages/local-sync/src/local-sync-dashboard/public/css/app.css deleted file mode 100644 index c77a55c1c..000000000 --- a/packages/local-sync/src/local-sync-dashboard/public/css/app.css +++ /dev/null @@ -1,261 +0,0 @@ -body { - background-image: url(http://news.nationalgeographic.com/content/dam/news/2015/12/13/BookTalk%20K2/01BookTalkK2.jpg); - background-image: -moz-linear-gradient(top, rgba(232, 244, 250, 0.2), rgba(231, 231, 233, 1)), url(http://news.nationalgeographic.com/content/dam/news/2015/12/13/BookTalk%20K2/01BookTalkK2.jpg); - background-image: -webkit-linear-gradient(top, rgba(232, 244, 250, 0.2), rgba(231, 231, 233, 1)), url(http://news.nationalgeographic.com/content/dam/news/2015/12/13/BookTalk%20K2/01BookTalkK2.jpg); - background-size: 100vw auto; - background-attachment: fixed; - font-family: Roboto, sans-serif; - font-size: 11px; -} - -h2 { - padding-top: 10px; - text-align: center; -} - -pre { - margin: 0; -} - -#accounts-wrapper { - position: relative; -} - -.account { - position: absolute; - border-radius: 5px; - width: 240px; - height: 450px; - background-color: rgb(255, 255, 255); - padding: 15px; - margin: 5px; - overflow: hidden; -} - -.account h3 { - font-size: 13px; - margin: 0; - padding: 0; -} - -.account .section { - font-size: 12px; - padding: 10px 0; - text-align: center; -} - -.account.errored { - color: #a94442; - border-radius: 4px; - background-color: rgb(231, 195, 195); -} - -.error-link { - font-weight: bold; -} - -.error-link:hover { - cursor: pointer; - color: #702726; -} - -#open-all-sync { - color: #ffffff; - padding-left: 5px; -} - -.right-action { - float: right; - margin-top: 10px; -} - -.action-link { - color: rgba(16, 83, 161, 0.88); - text-decoration: underline; - cursor: pointer; - margin: 5px 0; -} - -.action-link.cancel { - margin-top: 10px; -} - -.sync-policy textarea { - width: 100%; - height: 200px; - white-space: pre; -} - -.modal { - background-color: white; - width: 50%; - margin: 10vh auto; - padding: 20px; - max-height: calc(80vh - 40px); /* minus padding */ - overflow: auto; -} - -.modal-bg { - position: fixed; - width: 100%; - height: 100%; - left: 0; - top: 0; - background-color: rgba(0, 0, 0, 0.3); - z-index: 10; -} - -.modal-close-wrapper { - position: relative; - height: 0; - width: 0; - float: right; - top: -10px; -} - -.modal-close { - position: absolute; - cursor: pointer; - font-size: 14px; - font-weight: bold; - background: url('../images/close.png') center center no-repeat; - background-size: 12px auto; - height: 12px; - width: 12px; - top: 12px; - right: 12px; -} - -.sync-graph { - margin-top: 3px; -} - -.stats b { - display: inline-block; - margin-top: 5px; - margin-bottom: 1px; -} - -#syncback-request-details { - font-size: 15px; - color: black; -} - -#syncback-request-details .counts { - margin: 10px; -} - -#syncback-request-details span { - margin: 10px; -} - -#syncback-request-details table { - width: 100%; - border: solid black 1px; - box-shadow: 1px 1px #333333; - margin: 10px 0; - border-collapse: collapse; -} - -#syncback-request-details tr:nth-child(even) { - background-color: #F1F1F1; -} - -#syncback-request-details tr:not(:first-child):hover { - background-color: #C9C9C9; -} - -#syncback-request-details td, #syncback-request-details th { - text-align: center; - padding: 10px 5px; - border: solid black 1px; -} - -.dropdown-arrow { - margin: 0 5px; - height: 7px; - vertical-align: middle; -} - -.dropdown-options { - border: solid black 1px; - position: absolute; - background-color: white; - text-align: left; - display: inline; -} - -.dropdown-option { - position: relative; - padding: 0px 2px; -} - -.dropdown-option:hover { - background-color: rgb(114, 163, 255); -} - -.dropdown-selected { - display: inline; -} - -.dropdown-wrapper { - display: inline; - cursor: pointer; - font-weight: normal; -} - -.mini-account::after { - display: inline-block; - position: relative; - height: 100%; - width: 100%; - background-color: #666666; - content: ""; - z-index: -1; -} - -.mini-account { - background-color: rgb(0, 255, 157); - display: inline-block; - width: 10px; - height: 10px; -} - -.mini-account.errored { - background-color: rgb(255, 38, 0); -} - -.process-loads { - display: inline-block; - padding: 15px; - width: 250px; - margin: 15px 0; - background-color: white; -} - -.process-loads .section { - text-decoration: underline; - margin-bottom: 10px; - font-size: 12px; -} - -.sum-accounts { - border-top: solid black 1px; - margin-top: 5px; - padding-top: 5px; -} - -.account-filter { - padding-left: 5px; -} - -.process-group { - display: inline-block; - margin: 10px; - max-width: 250px; - vertical-align: top; -} - -#group-by-process { - vertical-align: middle; -} diff --git a/packages/local-sync/src/local-sync-dashboard/public/favicon.png b/packages/local-sync/src/local-sync-dashboard/public/favicon.png deleted file mode 100644 index d595d6d01db04ba06c163cffce983309cfdffb85..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2439 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 diff --git a/packages/local-sync/src/local-sync-dashboard/public/index.html b/packages/local-sync/src/local-sync-dashboard/public/index.html deleted file mode 100644 index 888e40cfb..000000000 --- a/packages/local-sync/src/local-sync-dashboard/public/index.html +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - K2 Dashboard - - -

K2 Dashboard

-
- - diff --git a/packages/local-sync/src/local-sync-dashboard/public/js/account-filter.jsx b/packages/local-sync/src/local-sync-dashboard/public/js/account-filter.jsx deleted file mode 100644 index 4c13b2462..000000000 --- a/packages/local-sync/src/local-sync-dashboard/public/js/account-filter.jsx +++ /dev/null @@ -1,26 +0,0 @@ -const React = window.React; - -function AccountFilter(props) { - return ( -
- Display: -
- ) -} - -AccountFilter.propTypes = { - onChange: React.PropTypes.func, - id: React.PropTypes.string, -} - -AccountFilter.states = { - all: "all", - errored: "errored", - notErrored: "not-errored", -}; - -window.AccountFilter = AccountFilter; diff --git a/packages/local-sync/src/local-sync-dashboard/public/js/app.jsx b/packages/local-sync/src/local-sync-dashboard/public/js/app.jsx deleted file mode 100644 index 1b03ab9f6..000000000 --- a/packages/local-sync/src/local-sync-dashboard/public/js/app.jsx +++ /dev/null @@ -1,333 +0,0 @@ -/* eslint react/react-in-jsx-scope: 0*/ -/* eslint no-console: 0*/ - -const React = window.React; -const ReactDOM = window.ReactDOM; -const _ = window._; -const { - SyncPolicy, - SetAllSyncPolicies, - AccountFilter, - SyncGraph, - SyncbackRequestDetails, - ElapsedTime, - Modal, - MiniAccount, - ProcessLoads, -} = window; - -function calcAcctPosition(count) { - const width = 280; - const height = 490; - const marginTop = 0; - const marginSide = 0; - - const acctsPerRow = Math.floor((window.innerWidth - 2 * marginSide) / width); - const row = Math.floor(count / acctsPerRow) - const col = count - (row * acctsPerRow); - const top = marginTop + (row * height); - const left = marginSide + (width * col); - - return {left: left, top: top}; -} - -function formatSyncTimes(timestamp) { - return timestamp / 1000; -} - -class Account extends React.Component { - constructor(props) { - super(props); - this.state = { - accountId: props.account.id, - version: null, - } - } - - shouldComponentUpdate(nextProps) { - return nextProps.account.version !== this.props.account.version || - nextProps.active !== this.props.active || - nextProps.assignment !== this.props.assignment || - nextProps.count !== this.props.count; - } - - clearError() { - const req = new XMLHttpRequest(); - const url = `${window.location.protocol}/accounts/${this.state.accountId}/clear-sync-error`; - req.open("PUT", url, true); - req.onreadystatechange = () => { - if (req.readyState === XMLHttpRequest.DONE) { - if (req.status === 200) { - // Would setState here, but external updates currently refresh the account - } else { - console.error(req.responseText); - } - } - } - req.send(); - } - - renderPolicyOrError() { - const account = this.props.account; - if (account.sync_error != null) { - return this.renderError(); - } - return ( - - ); - } - - renderError() { - const {message, stack} = this.props.account.sync_error - return ( -
-
Error
- -
{JSON.stringify(stack, null, 2)}
-
-
this.clearError()}>Clear Error
-
- ) - } - - render() { - const {account, assignment, active} = this.props; - const errorClass = account.sync_error ? ' errored' : '' - - const numStoredSyncs = account.last_sync_completions.length; - const oldestSync = account.last_sync_completions[numStoredSyncs - 1]; - const newestSync = account.last_sync_completions[0]; - const avgBetweenSyncs = (newestSync - oldestSync) / (1000 * numStoredSyncs); - - let firstSyncDuration = "Incomplete"; - if (account.first_sync_completion) { - firstSyncDuration = (new Date(account.first_sync_completion) - new Date(account.created_at)) / 1000; - } - - const position = calcAcctPosition(this.props.count); - - return ( -
-

{account.email_address} [{account.id}] {active ? '🌕' : '🌑'}

- {assignment} - -
- First Sync Duration (sec): -
{firstSyncDuration}
- Average Time Between Syncs (sec): -
{avgBetweenSyncs}
- Time Since Last Sync (sec): -
-            
-          
- Recent Syncs: - -
- {this.renderPolicyOrError()} -
- ); - } -} - -Account.propTypes = { - account: React.PropTypes.object, - active: React.PropTypes.bool, - assignment: React.PropTypes.string, - count: React.PropTypes.number, -} - -class Root extends React.Component { - - constructor() { - super(); - this.state = { - accounts: {}, - assignments: {}, - activeAccountIds: [], - visibleAccounts: AccountFilter.states.all, - groupByProcess: false, - }; - } - - componentDidMount() { - let url = null; - if (window.location.protocol === "https:") { - url = `wss://${window.location.host}/websocket`; - } else { - url = `ws://${window.location.host}/websocket`; - } - this.websocket = new WebSocket(url); - this.websocket.onopen = () => { - this.websocket.send("Message to send"); - }; - this.websocket.onmessage = (evt) => { - try { - const msg = JSON.parse(evt.data); - if (msg.cmd === 'UPDATE') { - this.onReceivedUpdate(msg.payload); - } - } catch (err) { - console.error(err); - } - }; - this.websocket.onclose = () => { - window.location.reload(); - }; - } - - onReceivedUpdate(update) { - const accounts = Object.assign({}, this.state.accounts); - for (const account of update.updatedAccounts) { - if (accounts[account.id]) { - account.version = accounts[account.id].version + 1; - } else { - account.version = 0; - } - accounts[account.id] = account; - } - - this.setState({ - assignments: update.assignments || this.state.assignments, - activeAccountIds: update.activeAccountIds || this.state.activeAccountIds, - accounts: accounts, - processLoads: update.processLoads, - }) - } - - onFilter() { - this.setState({visibleAccounts: document.getElementById('account-filter').value}); - } - - onGroupChange() { - this.setState({ - groupByProcess: document.getElementById('group-by-process').checked, - }); - } - - render() { - let ids = Object.keys(this.state.accounts); - - switch (this.state.visibleAccounts) { - case AccountFilter.states.errored: - ids = ids.filter((id) => this.state.accounts[id].sync_error) - break; - case AccountFilter.states.notErrored: - ids = ids.filter((id) => !this.state.accounts[id].sync_error) - break; - default: - break; - } - - let content; - if (this.props.collapsed) { - const groupByProcess = ( -
- this.onGroupChange()} - /> - Group Accounts By Process -
- ) - - if (this.state.groupByProcess) { - const accountsById = _.groupBy(this.state.accounts, 'id'); - const processes = []; - - for (const processName of Object.keys(this.state.processLoads)) { - const accounts = [] - - for (const accountId of this.state.processLoads[processName]) { - const account = accountsById[accountId][0]; - accounts.push(( - - )) - } - processes.push(( -
- {accounts} -
- )) - } - content = ( -
- {groupByProcess} -
- {processes} -
-
- ) - } else { - content = ( -
- {groupByProcess} -
- { - ids.sort((a, b) => a / 1 - b / 1).map((id) => - - ) - } -
-
- ) - } - } else { - let count = 0; - content = ( -
- { - ids.sort((a, b) => a / 1 - b / 1).map((id) => - - ) - } -
- ) - } - - return ( -
- - this.onFilter.call(this)} /> - parseInt(id, 10))} /> - {content} -
- ) - } -} - -Root.propTypes = { - collapsed: React.PropTypes.bool, -} - -let collapsed = false; -const collapsedStr = "collapsed"; -const index = window.location.search.indexOf(collapsedStr); -if (index >= 0) { - const value = window.location.search.substring(index + collapsedStr.length + 1); - if (value.startsWith("true")) { - collapsed = true; - } -} - -ReactDOM.render( - , - document.getElementById('root') -); diff --git a/packages/local-sync/src/local-sync-dashboard/public/js/mini-account.jsx b/packages/local-sync/src/local-sync-dashboard/public/js/mini-account.jsx deleted file mode 100644 index aba4b4d22..000000000 --- a/packages/local-sync/src/local-sync-dashboard/public/js/mini-account.jsx +++ /dev/null @@ -1,40 +0,0 @@ -const React = window.React; - -class MiniAccount extends React.Component { - - calculateColor() { - // in milliseconds - const grayAfter = 1000 * 60 * 10; // 10 minutes - const elapsedTime = Date.now() - this.props.account.last_sync_completions[0]; - let opacity = 0; - if (elapsedTime < grayAfter) { - opacity = 1.0 - elapsedTime / grayAfter; - } - - return `rgba(0, 255, 157, ${opacity})`; - } - - render() { - let errorClass; - const style = {}; - if (this.props.account.sync_error) { - errorClass = 'errored'; - } else { - errorClass = ''; - style.backgroundColor = this.calculateColor(); - } - - return ( -
- ) - } -} - -MiniAccount.propTypes = { - account: React.PropTypes.object, -}; - -window.MiniAccount = MiniAccount; diff --git a/packages/local-sync/src/local-sync-dashboard/public/js/process-loads.jsx b/packages/local-sync/src/local-sync-dashboard/public/js/process-loads.jsx deleted file mode 100644 index e8917fd52..000000000 --- a/packages/local-sync/src/local-sync-dashboard/public/js/process-loads.jsx +++ /dev/null @@ -1,37 +0,0 @@ -const React = window.React; - -function ProcessLoads(props) { - let entries; - let sumElem; - if (props.loads == null || Object.keys(props.loads).length === 0) { - entries = "No Data"; - sumElem = ""; - } else { - entries = []; - let sum = 0; - for (const processName of Object.keys(props.loads).sort()) { - const count = props.loads[processName].length; - sum += count; - entries.push( -
- {processName}: {count} accounts -
- ); - } - sumElem =
Total Accounts: {sum}
- } - - return ( -
-
Process Loads
- {entries} - {sumElem} -
- ) -} - -ProcessLoads.propTypes = { - loads: React.PropTypes.object, -} - -window.ProcessLoads = ProcessLoads; diff --git a/packages/local-sync/src/local-sync-dashboard/public/js/react-dom.js b/packages/local-sync/src/local-sync-dashboard/public/js/react-dom.js deleted file mode 100644 index 1cf5496b5..000000000 --- a/packages/local-sync/src/local-sync-dashboard/public/js/react-dom.js +++ /dev/null @@ -1,42 +0,0 @@ -/** - * ReactDOM v15.1.0 - * - * Copyright 2013-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - */ -// Based off https://github.com/ForbesLindesay/umd/blob/master/template.js -;(function(f) { - // CommonJS - if (typeof exports === "object" && typeof module !== "undefined") { - module.exports = f(require('react')); - - // RequireJS - } else if (typeof define === "function" && define.amd) { - define(['react'], f); - - //