import * as _ from 'lodash'; import CircularProgress from 'material-ui/CircularProgress'; import * as React from 'react'; import { Container } from 'ts/components/ui/container'; import { Retry } from 'ts/components/ui/retry'; import { Text } from 'ts/components/ui/text'; import { colors } from 'ts/style/colors'; import { styled } from 'ts/style/theme'; import { ScreenWidths, WebsiteBackendJobInfo } from 'ts/types'; import { backendClient } from 'ts/utils/backend_client'; import { constants } from 'ts/utils/constants'; import { utils } from 'ts/utils/utils'; const TABLE_ROW_MIN_HEIGHT = 100; export interface OpenPositionsProps { hash: string; screenWidth: ScreenWidths; } export interface OpenPositionsState { jobInfos?: WebsiteBackendJobInfo[]; error?: Error; } 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); const isSmallScreen = utils.isMobileWidth(this.props.screenWidth); return ( {!isSmallScreen && (
)} Open Positions {isReadyToRender ? this._renderTable() : this._renderLoading()}
); } private _renderLoading(): React.ReactNode { 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) ? ( ) : ( )}
); } private _renderTable(): React.ReactNode { return (
{_.map(this.state.jobInfos, jobInfo => { return ( ); })}
Interested in telling us why you'd be a valuable addition to the team outside of the positions listed above?{' '} Email us!
); } private async _fetchJobInfosAsync(): Promise { 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 _openJobInfoUrl(jobInfo: WebsiteBackendJobInfo): void { const url = jobInfo.url; utils.openUrl(url); } } export interface JobInfoTableRowProps { className?: string; screenWidth: ScreenWidths; jobInfo: WebsiteBackendJobInfo; onClick?: (event: React.MouseEvent) => void; } const PlainJobInfoTableRow: React.StatelessComponent = ({ className, screenWidth, jobInfo, onClick, }) => { const isSmallScreen = screenWidth === ScreenWidths.Sm; const titleClassName = isSmallScreen ? 'col col-12 center' : 'col col-5'; const paddingLeft = isSmallScreen ? undefined : '30px'; return ( {jobInfo.title} {!isSmallScreen && ( {jobInfo.department} )} {!isSmallScreen && ( {jobInfo.office} )} ); }; export const JobInfoTableRow = styled(PlainJobInfoTableRow)` cursor: pointer; background-color: ${colors.grey100}; border-radius: 7px; &:hover { opacity: 0.5; } `;