diff options
Diffstat (limited to 'packages/website/ts/pages')
-rw-r--r-- | packages/website/ts/pages/jobs/benefits.tsx | 2 | ||||
-rw-r--r-- | packages/website/ts/pages/jobs/mission.tsx | 2 | ||||
-rw-r--r-- | packages/website/ts/pages/jobs/open_positions.tsx | 196 | ||||
-rw-r--r-- | packages/website/ts/pages/jobs/teams.tsx | 2 |
4 files changed, 129 insertions, 73 deletions
diff --git a/packages/website/ts/pages/jobs/benefits.tsx b/packages/website/ts/pages/jobs/benefits.tsx index ce261592f..a7cc23503 100644 --- a/packages/website/ts/pages/jobs/benefits.tsx +++ b/packages/website/ts/pages/jobs/benefits.tsx @@ -41,7 +41,7 @@ export interface BenefitsProps { } export const Benefits = (props: BenefitsProps) => ( - <div style={{ backgroundColor: colors.jobsPageGrey }}> + <div style={{ backgroundColor: colors.jobsPageBackground }}> {props.screenWidth === ScreenWidths.Sm ? <SmallLayout /> : <LargeLayout />} </div> ); diff --git a/packages/website/ts/pages/jobs/mission.tsx b/packages/website/ts/pages/jobs/mission.tsx index a3584e5f6..b4d294623 100644 --- a/packages/website/ts/pages/jobs/mission.tsx +++ b/packages/website/ts/pages/jobs/mission.tsx @@ -35,7 +35,7 @@ export const Mission = (props: MissionProps) => { </div> ); return ( - <div className="container lg-py4 md-py4" style={{ backgroundColor: colors.jobsPageGrey, color: colors.black }}> + <div className="container lg-py4 md-py4" style={{ backgroundColor: colors.jobsPageBackground, color: colors.black }}> <div className="mx-auto clearfix sm-py4"> {isSmallScreen ? ( <div> diff --git a/packages/website/ts/pages/jobs/open_positions.tsx b/packages/website/ts/pages/jobs/open_positions.tsx index f9c37d36f..5eb8e429d 100644 --- a/packages/website/ts/pages/jobs/open_positions.tsx +++ b/packages/website/ts/pages/jobs/open_positions.tsx @@ -1,80 +1,136 @@ import * as _ from 'lodash'; +import CircularProgress from 'material-ui/CircularProgress'; import { Table, TableBody, TableHeader, TableHeaderColumn, TableRow, TableRowColumn } from 'material-ui/Table'; import * as React from 'react'; -const POSITIONS = [ - { - name: 'Community Director', - department: 'Marketing', - office: 'Remote / San Francisco', - }, - { - name: 'Data Scientist / Data Engineer', - department: 'Engineering', - office: 'Remote / San Francisco', - }, - { - name: 'Executive Assitant / Office Manager', - department: 'Operations', - office: 'Remote / San Francisco', - }, - { - name: 'Research Fellow - Economics / Governance', - department: 'Engineering', - office: 'Remote / San Francisco', - }, - { - name: 'Software Engineer - Blockchain', - department: 'Engineer', - office: 'Remote / San Francisco', - }, - { - name: 'Software Engineer - Full-stack', - department: 'Marketing', - office: 'Remote / San Francisco', - }, -]; +import { Retry } from 'ts/components/ui/retry'; +import { colors } from 'ts/style/colors'; +import { WebsiteBackendJobInfo } from 'ts/types'; +import { backendClient } from 'ts/utils/backend_client'; + +const labelStyle = { fontFamily: 'Roboto Mono', fontSize: 18 }; export interface OpenPositionsProps { hash: string; } +export interface OpenPositionsState { + jobInfos?: WebsiteBackendJobInfo[]; + error?: Error; +} -export const OpenPositions = (props: OpenPositionsProps) => { - const labelStyle = { fontFamily: 'Roboto Mono', fontSize: 18 }; - return ( - <div id={props.hash} className="py4" style={{ paddingLeft: 200, paddingRight: 200 }}> - <Table selectable={false}> - <TableHeader displaySelectAll={false} adjustForCheckbox={false}> - <TableRow> - <TableHeaderColumn colSpan={6} style={labelStyle}> - Position - </TableHeaderColumn> - <TableHeaderColumn colSpan={3} style={labelStyle}> - Department - </TableHeaderColumn> - <TableHeaderColumn colSpan={3} style={labelStyle}> - Office - </TableHeaderColumn> - </TableRow> - </TableHeader> - <TableBody displayRowCheckbox={false} showRowHover={true}> - {_.map(POSITIONS, position => { - return ( - <TableRow hoverable={true} displayBorder={false} style={{ height: 100, border: 2 }}> - <TableRowColumn colSpan={6} style={labelStyle}> - {position.name} - </TableRowColumn> - <TableRowColumn colSpan={3} style={labelStyle}> - {position.department} - </TableRowColumn> - <TableRowColumn colSpan={3} style={labelStyle}> - {position.office} - </TableRowColumn> +export class OpenPositions extends React.Component<OpenPositionsProps, OpenPositionsState> { + private _isUnmounted: boolean; + constructor(props: OpenPositionsProps) { + super(props); + this._isUnmounted = false; + this.state = { + jobInfos: undefined, + error: undefined, + }; + } + public componentWillMount(): void { + // tslint:disable-next-line:no-floating-promises + this._fetchJobInfosAsync(); + } + public componentWillUnmount(): void { + this._isUnmounted = true; + } + public render(): React.ReactNode { + const isReadyToRender = _.isUndefined(this.state.error) && !_.isUndefined(this.state.jobInfos); + if (!isReadyToRender) { + return ( + // TODO: consolidate this loading component with the one in portal and RelayerIndex + // TODO: possibly refactor into a generic loading container with spinner and retry UI + <div className="center"> + {_.isUndefined(this.state.error) ? ( + <CircularProgress size={40} thickness={5} /> + ) : ( + <Retry onRetry={this._fetchJobInfosAsync.bind(this)} /> + )} + </div> + ); + } else { + return ( + <div id={this.props.hash} className="mx-auto max-width-4"> + <Title /> + <Table selectable={false} onCellClick={this._onCellClick.bind(this)}> + <TableHeader displaySelectAll={false} adjustForCheckbox={false}> + <TableRow> + <TableHeaderColumn colSpan={5} style={labelStyle}> + Position + </TableHeaderColumn> + <TableHeaderColumn colSpan={3} style={labelStyle}> + Department + </TableHeaderColumn> + <TableHeaderColumn colSpan={4} style={labelStyle}> + Office + </TableHeaderColumn> </TableRow> - ); - })} - </TableBody> - </Table> - </div> - ); -}; + </TableHeader> + <TableBody displayRowCheckbox={false} showRowHover={true}> + {_.map(this.state.jobInfos, jobInfo => { + return this._renderJobInfo(jobInfo); + })} + </TableBody> + </Table> + </div> + ); + } + } + private _renderJobInfo(jobInfo: WebsiteBackendJobInfo): React.ReactNode { + return ( + <TableRow key={jobInfo.id} hoverable={true} displayBorder={false} style={{ height: 100, border: 2 }}> + <TableRowColumn colSpan={5} style={labelStyle}> + {jobInfo.title} + </TableRowColumn> + <TableRowColumn colSpan={3} style={labelStyle}> + {jobInfo.department} + </TableRowColumn> + <TableRowColumn colSpan={4} style={labelStyle}> + {jobInfo.office} + </TableRowColumn> + </TableRow> + ); + } + private async _fetchJobInfosAsync(): Promise<void> { + try { + if (!this._isUnmounted) { + this.setState({ + jobInfos: undefined, + error: undefined, + }); + } + const jobInfos = await backendClient.getJobInfosAsync(); + if (!this._isUnmounted) { + this.setState({ + jobInfos, + }); + } + } catch (error) { + if (!this._isUnmounted) { + this.setState({ + error, + }); + } + } + } + private _onCellClick(rowNumber: number): void { + if (_.isUndefined(this.state.jobInfos)) { + return; + } + const url = this.state.jobInfos[rowNumber].url; + window.open(url, '_blank'); + } +} + +const Title = () => ( + <div + className="h2 lg-py4 md-py4 sm-py3" + style={{ + paddingLeft: 90, + fontFamily: 'Roboto Mono', + }} + > + {'Open Positions'} + </div> +); diff --git a/packages/website/ts/pages/jobs/teams.tsx b/packages/website/ts/pages/jobs/teams.tsx index 3d953c993..465bae7f4 100644 --- a/packages/website/ts/pages/jobs/teams.tsx +++ b/packages/website/ts/pages/jobs/teams.tsx @@ -42,7 +42,7 @@ export interface TeamsProps { export const Teams = (props: TeamsProps) => (props.screenWidth === ScreenWidths.Sm ? <SmallLayout /> : <LargeLayout />); const LargeLayout = () => ( - <div className="mx-auto max-width-4 clearfix"> + <div className="mx-auto max-width-4 clearfix pb4"> <div className="col lg-col-6 md-col-6 col-12"> <BulletedItemList headerText={HEADER_TEXT} bulletedItemInfos={ITEMS_COLUMN1} /> </div> |