diff --git a/explorer/client/@types/link-stats/index.d.ts b/explorer/client/@types/link-stats/index.d.ts index 962b322c11a..1630e7d31db 100644 --- a/explorer/client/@types/link-stats/index.d.ts +++ b/explorer/client/@types/link-stats/index.d.ts @@ -15,6 +15,7 @@ interface IJobRun { createdAt: string finishedAt?: string chainlinkNode: IChainlinkNode + etherscanHost: string taskRuns: ITaskRun[] } diff --git a/explorer/client/src/__tests__/reducers/config.test.ts b/explorer/client/src/__tests__/reducers/config.test.ts new file mode 100644 index 00000000000..60f78a11018 --- /dev/null +++ b/explorer/client/src/__tests__/reducers/config.test.ts @@ -0,0 +1,33 @@ +import reducer, { IState } from '../../reducers' +import { Action } from '../../reducers/config' + +describe('reducers/config', () => { + it('returns an initial state', () => { + const action = {} as Action + const state = reducer({}, action) as IState + + expect(state.search).toEqual({ + etherscanHost: undefined + }) + }) + + it('can update the search query', () => { + const action = { + type: 'UPSERT_JOB_RUN', + data: { + meta: { + jobRun: { + meta: { + etherscanHost: 'ropsten.etherscan.io' + } + } + } + } + } as Action + const state = reducer({}, action) as IState + + expect(state.config).toEqual({ + etherscanHost: 'ropsten.etherscan.io' + }) + }) +}) diff --git a/explorer/client/src/__tests__/reducers/jobRuns.test.ts b/explorer/client/src/__tests__/reducers/jobRuns.test.ts index 65e9875968a..8b14d2f2ffe 100644 --- a/explorer/client/src/__tests__/reducers/jobRuns.test.ts +++ b/explorer/client/src/__tests__/reducers/jobRuns.test.ts @@ -70,7 +70,12 @@ describe('reducers/jobRuns', () => { id: '9b7d791a-9a1f-4c55-a6be-b4231cf9fd4e' } } - const data = { jobRuns: normalizedJobRuns } + const data = { + jobRuns: normalizedJobRuns, + meta: { + jobRun: { meta: {} } + } + } const action = { type: 'UPSERT_JOB_RUN', data: data } as JobRunsAction const state = reducer(STATE, action) as IState diff --git a/explorer/client/src/__tests__/reducers/jobRunsIndex.test.ts b/explorer/client/src/__tests__/reducers/jobRunsIndex.test.ts index f059e861140..02864c200b1 100644 --- a/explorer/client/src/__tests__/reducers/jobRunsIndex.test.ts +++ b/explorer/client/src/__tests__/reducers/jobRunsIndex.test.ts @@ -53,7 +53,12 @@ describe('reducers/jobRunsIndex', () => { describe('UPSERT_JOB_RUN', () => { it('clears items', () => { - const data = { jobRuns: {} } + const data = { + jobRuns: {}, + meta: { + jobRun: { meta: {} } + } + } const action = { type: 'UPSERT_JOB_RUN', data: data } as JobRunsAction const state = reducer(STATE, action) as IState diff --git a/explorer/client/src/actions/jobRuns.ts b/explorer/client/src/actions/jobRuns.ts index 879fc2fd2b5..9229d2cf9cd 100644 --- a/explorer/client/src/actions/jobRuns.ts +++ b/explorer/client/src/actions/jobRuns.ts @@ -21,7 +21,7 @@ const getJobRuns = (query: Query, page: number, size: number) => { const getJobRun = (jobRunId?: string) => { return (dispatch: Dispatch) => { api.getJobRun(jobRunId).then((r: IJobRun) => { - const normalizedData = normalize(r) + const normalizedData = normalize(r, { endpoint: 'jobRun' }) const action: JobRunsAction = { type: 'UPSERT_JOB_RUN', data: normalizedData diff --git a/explorer/client/src/components/JobRuns/Details.tsx b/explorer/client/src/components/JobRuns/Details.tsx index 364f5b34497..02488a56dcf 100644 --- a/explorer/client/src/components/JobRuns/Details.tsx +++ b/explorer/client/src/components/JobRuns/Details.tsx @@ -119,9 +119,10 @@ const styles = ({ spacing, palette }: Theme) => interface IProps extends WithStyles { jobRun: IJobRun + etherscanHost: string } -const Details = ({ classes, jobRun }: IProps) => { +const Details = ({ classes, jobRun, etherscanHost }: IProps) => { return (
@@ -169,7 +170,7 @@ const Details = ({ classes, jobRun }: IProps) => { Tasks - +
diff --git a/explorer/client/src/components/JobRuns/EtherscanLink.tsx b/explorer/client/src/components/JobRuns/EtherscanLink.tsx index a676cd70a9d..8f8237fd4a8 100644 --- a/explorer/client/src/components/JobRuns/EtherscanLink.tsx +++ b/explorer/client/src/components/JobRuns/EtherscanLink.tsx @@ -28,15 +28,15 @@ const styles = ({ palette, spacing }: Theme) => interface IProps extends WithStyles { txHash: string + host: string } -const host = process.env.ETHERSCAN_HOST || 'ropsten.etherscan.io' -const url = (txHash: string) => `https://${host}/tx/${txHash}` +const url = (host: string, txHash: string) => `https://${host}/tx/${txHash}` -const Details = ({ classes, txHash }: IProps) => { +const Details = ({ classes, host, txHash }: IProps) => { return ( diff --git a/explorer/client/src/components/JobRuns/TaskRuns.tsx b/explorer/client/src/components/JobRuns/TaskRuns.tsx index 721d53a4cc7..02b88c611ee 100644 --- a/explorer/client/src/components/JobRuns/TaskRuns.tsx +++ b/explorer/client/src/components/JobRuns/TaskRuns.tsx @@ -39,10 +39,11 @@ const styles = ({ spacing, palette }: Theme) => }) interface IProps extends WithStyles { + etherscanHost: string taskRuns?: ITaskRun[] } -const TaskRuns = ({ taskRuns, classes }: IProps) => { +const TaskRuns = ({ etherscanHost, taskRuns, classes }: IProps) => { return (
    {taskRuns && @@ -60,7 +61,10 @@ const TaskRuns = ({ taskRuns, classes }: IProps) => { {run.transactionHash && ( - + )} diff --git a/explorer/client/src/containers/JobRuns/Show.tsx b/explorer/client/src/containers/JobRuns/Show.tsx index b68cdb565a3..b4119169978 100644 --- a/explorer/client/src/containers/JobRuns/Show.tsx +++ b/explorer/client/src/containers/JobRuns/Show.tsx @@ -55,12 +55,13 @@ const styles = ({ spacing, breakpoints }: Theme) => interface IProps extends WithStyles { jobRunId?: string jobRun?: IJobRun + etherscanHost?: string getJobRun: Function path: string } const Show = withStyles(styles)( - ({ jobRunId, jobRun, getJobRun, classes }: IProps) => { + ({ jobRunId, jobRun, getJobRun, classes, etherscanHost }: IProps) => { useEffect(() => { getJobRun(jobRunId) }, []) @@ -79,7 +80,14 @@ const Show = withStyles(styles)(
    - {jobRun ?
    : } + {jobRun && etherscanHost ? ( +
    + ) : ( + + )}
    @@ -103,13 +111,19 @@ const jobRunSelector = ( } } +const etherscanHostSelector = ({ config }: IState) => { + return config.etherscanHost +} + interface IOwnProps { jobRunId?: string } const mapStateToProps = (state: IState, { jobRunId }: IOwnProps) => { const jobRun = jobRunSelector(state, jobRunId) - return { jobRun } + const etherscanHost = etherscanHostSelector(state) + + return { jobRun, etherscanHost } } const mapDispatchToProps = (dispatch: Dispatch) => diff --git a/explorer/client/src/reducers.ts b/explorer/client/src/reducers.ts index 3741d4eef16..e689f493603 100644 --- a/explorer/client/src/reducers.ts +++ b/explorer/client/src/reducers.ts @@ -1,4 +1,5 @@ import { combineReducers } from 'redux' +import config, { IState as IConfigState } from './reducers/config' import search, { IState as ISearchState } from './reducers/search' import jobRuns, { IState as IJobRunsState } from './reducers/jobRuns' import taskRuns, { IState as ITaskRunsState } from './reducers/taskRuns' @@ -10,6 +11,7 @@ import jobRunsIndex, { } from './reducers/jobRunsIndex' export interface IState { + config: IConfigState chainlinkNodes: IChainlinkNodesState jobRuns: IJobRunsState taskRuns: ITaskRunsState @@ -18,6 +20,7 @@ export interface IState { } const reducer = combineReducers({ + config, chainlinkNodes, jobRuns, taskRuns, diff --git a/explorer/client/src/reducers/config.ts b/explorer/client/src/reducers/config.ts new file mode 100644 index 00000000000..691510f112e --- /dev/null +++ b/explorer/client/src/reducers/config.ts @@ -0,0 +1,21 @@ +export interface IState { + etherscanHost?: string +} + +export type Action = + | { type: 'UPSERT_JOB_RUN'; data: any } + | { type: '@@redux/INIT' } + | { type: '@@INIT' } + +const initialState = { etherscanHost: undefined } + +export default (state: IState = initialState, action: Action) => { + switch (action.type) { + case 'UPSERT_JOB_RUN': + return Object.assign({}, state, { + etherscanHost: action.data.meta.jobRun.meta.etherscanHost + }) + default: + return state + } +} diff --git a/explorer/src/serializers/jobRunSerializer.ts b/explorer/src/serializers/jobRunSerializer.ts index c0d887eb590..e1d16f99ad5 100644 --- a/explorer/src/serializers/jobRunSerializer.ts +++ b/explorer/src/serializers/jobRunSerializer.ts @@ -36,15 +36,20 @@ export const taskRuns = { ] } -const jobRunsSerializer = (run: JobRun) => { +const ETHERSCAN_HOST = process.env.ETHERSCAN_HOST || 'ropsten.etherscan.io' + +const jobRunSerializer = (run: JobRun) => { const opts = { attributes: BASE_ATTRIBUTES.concat(['taskRuns']), keyForAttribute: 'camelCase', chainlinkNode: chainlinkNode, - taskRuns: taskRuns + taskRuns: taskRuns, + meta: { + etherscanHost: ETHERSCAN_HOST + } } as SerializerOptions return new JSONAPISerializer('job_runs', opts).serialize(run) } -export default jobRunsSerializer +export default jobRunSerializer