From 679d60cd5a5debcacff42c38967c1f8b7d972882 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Mon, 11 Jun 2018 12:38:25 -0700 Subject: Implement large screen open positions --- packages/website/ts/pages/jobs/benefits.tsx | 2 +- packages/website/ts/pages/jobs/mission.tsx | 2 +- packages/website/ts/pages/jobs/open_positions.tsx | 196 ++++++++++++++-------- packages/website/ts/pages/jobs/teams.tsx | 2 +- 4 files changed, 129 insertions(+), 73 deletions(-) (limited to 'packages/website/ts/pages') 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) => ( -
+
{props.screenWidth === ScreenWidths.Sm ? : }
); 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) => {
); return ( -
+
{isSmallScreen ? (
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 ( -
- - - - - Position - - - Department - - - Office - - - - - {_.map(POSITIONS, position => { - return ( - - - {position.name} - - - {position.department} - - - {position.office} - +export class OpenPositions extends React.Component { + 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 +
+ {_.isUndefined(this.state.error) ? ( + + ) : ( + + )} +
+ ); + } else { + return ( +
+ + <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> -- cgit