WIP Whiteboard Changes
This commit is contained in:
@@ -22,7 +22,7 @@ class ErrorBoundary extends React.Component {
|
||||
|
||||
render() {
|
||||
if (this.state.hasErrored === true) {
|
||||
return <div>Uh oh, something went wrong. {this.state.error}</div>;
|
||||
return <div>Uh oh, something went wrong.</div>;
|
||||
} else {
|
||||
return this.props.children;
|
||||
}
|
||||
|
||||
@@ -25,18 +25,17 @@ function searchResult(query) {
|
||||
function renderOption(item) {
|
||||
return (
|
||||
<Option key={item.category} text={item.category}>
|
||||
<div className="global-search-item">
|
||||
<span className="global-search-item-desc">
|
||||
<div className='global-search-item'>
|
||||
<span className='global-search-item-desc'>
|
||||
Found {item.query} on
|
||||
<a
|
||||
href={`https://s.taobao.com/search?q=${item.query}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
target='_blank'
|
||||
rel='noopener noreferrer'>
|
||||
{item.category}
|
||||
</a>
|
||||
</span>
|
||||
<span className="global-search-item-count">{item.count} results</span>
|
||||
<span className='global-search-item-count'>{item.count} results</span>
|
||||
</div>
|
||||
</Option>
|
||||
);
|
||||
@@ -56,25 +55,26 @@ export default class GlobalSearch extends React.Component {
|
||||
render() {
|
||||
const { dataSource } = this.state;
|
||||
return (
|
||||
<div style={{ width: 300 }}>
|
||||
<AutoComplete
|
||||
size="large"
|
||||
style={{ width: "100%" }}
|
||||
dataSource={dataSource.map(renderOption)}
|
||||
onSelect={onSelect}
|
||||
onSearch={this.handleSearch}
|
||||
placeholder="input here"
|
||||
optionLabelProp="text"
|
||||
>
|
||||
<Input
|
||||
suffix={
|
||||
<Button style={{ marginRight: -12 }} size="large" type="primary">
|
||||
<Icon type="search" />
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
</AutoComplete>
|
||||
</div>
|
||||
<div />
|
||||
// <div style={{ width: 300 }}>
|
||||
// <AutoComplete
|
||||
// size="large"
|
||||
// style={{ width: "100%" }}
|
||||
// dataSource={dataSource.map(renderOption)}
|
||||
// onSelect={onSelect}
|
||||
// onSearch={this.handleSearch}
|
||||
// placeholder="input here"
|
||||
// optionLabelProp="text"
|
||||
// >
|
||||
// <Input
|
||||
// suffix={
|
||||
// <Button style={{ marginRight: -12 }} size="large" type="primary">
|
||||
// <Icon type="search" />
|
||||
// </Button>
|
||||
// }
|
||||
// />
|
||||
// </AutoComplete>
|
||||
// </div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,8 +33,8 @@ function JobTombstone({ job, ...otherProps }) {
|
||||
if (!job) {
|
||||
return (
|
||||
<AlertComponent
|
||||
message="This job does not exist or you do not have access to it."
|
||||
type="error"
|
||||
message='This job does not exist or you do not have access to it.'
|
||||
type='error'
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -70,20 +70,19 @@ function JobTombstone({ job, ...otherProps }) {
|
||||
+" " + jobContext.owner?.first_name
|
||||
: "No owner"
|
||||
}
|
||||
tags={<Tag color="blue">{jobContext?.status}</Tag>}
|
||||
tags={<Tag color='blue'>{jobContext?.job_status?.name}</Tag>}
|
||||
extra={[
|
||||
<Form.Item key="1">
|
||||
<Button type="primary" htmlType="submit">
|
||||
<Form.Item key='1'>
|
||||
<Button type='primary' htmlType='submit'>
|
||||
Save
|
||||
</Button>
|
||||
</Form.Item>
|
||||
]}
|
||||
>
|
||||
<Descriptions size="small" column={3}>
|
||||
<Descriptions.Item label="Claim Total">
|
||||
]}>
|
||||
<Descriptions size='small' column={3}>
|
||||
<Descriptions.Item label='Claim Total'>
|
||||
$ {jobContext.claim_total?.toFixed(2)}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="Deductible">
|
||||
<Descriptions.Item label='Deductible'>
|
||||
$ {jobContext.deductible?.toFixed(2)}
|
||||
</Descriptions.Item>
|
||||
</Descriptions>
|
||||
@@ -91,51 +90,51 @@ function JobTombstone({ job, ...otherProps }) {
|
||||
|
||||
<Row>
|
||||
<Typography.Title level={4}>Information</Typography.Title>
|
||||
<Form.Item label="RO #">
|
||||
<Form.Item label='RO #'>
|
||||
{getFieldDecorator("ro_number", {
|
||||
initialValue: jobContext.ro_number
|
||||
})(<Input name="ro_number" readOnly onChange={handleChange} />)}
|
||||
})(<Input name='ro_number' readOnly onChange={handleChange} />)}
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item label="Estimate #">
|
||||
<Form.Item label='Estimate #'>
|
||||
{getFieldDecorator("est_number", {
|
||||
initialValue: jobContext.est_number
|
||||
})(<Input name="est_number" readOnly onChange={handleChange} />)}
|
||||
})(<Input name='est_number' readOnly onChange={handleChange} />)}
|
||||
</Form.Item>
|
||||
</Row>
|
||||
|
||||
<Row>
|
||||
<Typography.Title level={4}>Insurance Information</Typography.Title>
|
||||
<Form.Item label="Insurance Company">
|
||||
<Form.Item label='Insurance Company'>
|
||||
{getFieldDecorator("est_co_nm", {
|
||||
initialValue: jobContext.est_co_nm
|
||||
})(<Input name="est_co_nm" onChange={handleChange} />)}
|
||||
})(<Input name='est_co_nm' onChange={handleChange} />)}
|
||||
</Form.Item>
|
||||
<Col span={8}>
|
||||
<Form.Item label="Estimator Last Name">
|
||||
<Form.Item label='Estimator Last Name'>
|
||||
{getFieldDecorator("est_ct_ln", {
|
||||
initialValue: jobContext.est_ct_ln
|
||||
})(<Input name="est_ct_ln" onChange={handleChange} />)}
|
||||
})(<Input name='est_ct_ln' onChange={handleChange} />)}
|
||||
</Form.Item>
|
||||
<Form.Item label="Estimator First Name">
|
||||
<Form.Item label='Estimator First Name'>
|
||||
{getFieldDecorator("est_ct_fn", {
|
||||
initialValue: jobContext.est_ct_fn
|
||||
})(<Input name="est_ct_fn" onChange={handleChange} />)}
|
||||
})(<Input name='est_ct_fn' onChange={handleChange} />)}
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<Form.Item label="Estimator Phone #">
|
||||
<Form.Item label='Estimator Phone #'>
|
||||
{getFieldDecorator("est_ph1", {
|
||||
initialValue: jobContext.est_ph1
|
||||
})(
|
||||
<FormItemPhone
|
||||
customInput={Input}
|
||||
name="est_ph1"
|
||||
name='est_ph1'
|
||||
onValueChange={handleChange}
|
||||
/>
|
||||
)}
|
||||
</Form.Item>
|
||||
<Form.Item label="Estimator Email">
|
||||
<Form.Item label='Estimator Email'>
|
||||
{getFieldDecorator("est_ea", {
|
||||
initialValue: jobContext.est_ea,
|
||||
rules: [
|
||||
@@ -144,7 +143,7 @@ function JobTombstone({ job, ...otherProps }) {
|
||||
message: "This is not a valid email address."
|
||||
}
|
||||
]
|
||||
})(<Input name="est_ea" onChange={handleChange} />)}
|
||||
})(<Input name='est_ea' onChange={handleChange} />)}
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
@@ -38,7 +38,10 @@ export default function JobsPage({ loading, jobs }) {
|
||||
sorter: (a, b) => alphaSort(a, b),
|
||||
sortOrder:
|
||||
state.sortedInfo.columnKey === "status" && state.sortedInfo.order,
|
||||
ellipsis: true
|
||||
ellipsis: true,
|
||||
render: (text, record) => {
|
||||
return record.job_status?.name ?? "";
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "Customer",
|
||||
@@ -75,9 +78,9 @@ export default function JobsPage({ loading, jobs }) {
|
||||
render: (text, record) => (
|
||||
<span>
|
||||
Action 一 {record.ro_number}
|
||||
<Divider type="vertical" />
|
||||
<Divider type="vertical" />
|
||||
More actions <Icon type="down" />
|
||||
<Divider type='vertical' />
|
||||
<Divider type='vertical' />
|
||||
More actions <Icon type='down' />
|
||||
</span>
|
||||
)
|
||||
}
|
||||
@@ -94,12 +97,12 @@ export default function JobsPage({ loading, jobs }) {
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Input name="searchCriteria" onChange={handleChange} />
|
||||
<Input name='searchCriteria' onChange={handleChange} />
|
||||
<Table
|
||||
loading={loading}
|
||||
pagination={{ position: "bottom" }}
|
||||
columns={columns.map(item => ({ ...item }))}
|
||||
rowKey="id"
|
||||
rowKey='id'
|
||||
dataSource={jobs}
|
||||
onChange={handleTableChange}
|
||||
/>
|
||||
|
||||
@@ -1,59 +1,75 @@
|
||||
import React from "react";
|
||||
import { Skeleton, Switch, Card, Icon, Avatar } from "antd";
|
||||
import { Link } from "react-router-dom";
|
||||
import { Menu, Dropdown, Card, Icon, Avatar, Button } from "antd";
|
||||
|
||||
const { Meta } = Card;
|
||||
export default function WhiteBoardCard({ metadata }) {
|
||||
// const {
|
||||
// onClick,
|
||||
// className,
|
||||
// name,
|
||||
// cardStyle,
|
||||
// body,
|
||||
// dueOn,
|
||||
// cardColor,
|
||||
// subTitle,
|
||||
// tagStyle,
|
||||
// escalationText,
|
||||
// tags,
|
||||
// showDeleteButton,
|
||||
// onDelete
|
||||
// } = this.props;
|
||||
const menu = (
|
||||
<Menu>
|
||||
<Menu.Item key='images'>
|
||||
<Icon type='file-image' />
|
||||
View Job Images
|
||||
</Menu.Item>
|
||||
<Menu.Item key='printing'>
|
||||
<Icon type='printer' />
|
||||
Printing
|
||||
</Menu.Item>
|
||||
<Menu.Item key='notes'>
|
||||
<Icon type='edit' />
|
||||
Job Notes
|
||||
</Menu.Item>
|
||||
<Menu.Item key='postinvoices'>
|
||||
<Icon type='shopping-cart' />
|
||||
Post Invoices
|
||||
</Menu.Item>
|
||||
<Menu.Item key='receiveparts'>
|
||||
<Icon type='inbox' />
|
||||
Receive Parts
|
||||
</Menu.Item>
|
||||
<Menu.Item key='partstatus'>
|
||||
<Icon type='tool' />
|
||||
Parts Status
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
);
|
||||
|
||||
class WhiteBoardCard extends React.Component {
|
||||
state = {
|
||||
loading: true
|
||||
};
|
||||
|
||||
onChange = checked => {
|
||||
this.setState({ loading: !checked });
|
||||
};
|
||||
|
||||
render() {
|
||||
const { loading } = this.state;
|
||||
// const {
|
||||
// onClick,
|
||||
// className,
|
||||
// name,
|
||||
// cardStyle,
|
||||
// body,
|
||||
// dueOn,
|
||||
// cardColor,
|
||||
// subTitle,
|
||||
// tagStyle,
|
||||
// escalationText,
|
||||
// tags,
|
||||
// showDeleteButton,
|
||||
// onDelete
|
||||
// } = this.props;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Card
|
||||
style={{ width: 300, marginTop: 16 }}
|
||||
actions={[
|
||||
<Icon type="setting" key="setting" />,
|
||||
<Icon type="edit" key="edit" />,
|
||||
<Icon type="ellipsis" key="ellipsis" />,
|
||||
<Switch checked={!loading} onChange={this.onChange} />
|
||||
]}
|
||||
>
|
||||
<Skeleton loading={loading} avatar active>
|
||||
<Meta
|
||||
avatar={
|
||||
<Avatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" />
|
||||
}
|
||||
title="Card title"
|
||||
description="This is the description"
|
||||
/>
|
||||
</Skeleton>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<Card
|
||||
title={
|
||||
(metadata.ro_number ?? metadata.est_number) +
|
||||
" | " +
|
||||
(metadata.owner?.first_name ?? "") +
|
||||
" " +
|
||||
(metadata.owner?.last_name ?? "")
|
||||
}
|
||||
style={{ width: 300, marginTop: 10 }}
|
||||
actions={[
|
||||
<Link to={`/manage/jobs/${metadata.id}`}>
|
||||
<Icon type='eye' key='view' />
|
||||
</Link>,
|
||||
<Icon type='message' key='message' />,
|
||||
<Dropdown overlay={menu} trigger={["click"]}>
|
||||
<Icon type='ellipsis' />
|
||||
</Dropdown>
|
||||
]}>
|
||||
<Avatar alt='Job' />
|
||||
This is the card data.
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default WhiteBoardCard;
|
||||
|
||||
@@ -11,7 +11,7 @@ export default function WhiteBoardKanBan({ data, eventBus }) {
|
||||
<Board
|
||||
tagStyle={{ fontSize: "80%" }}
|
||||
data={data}
|
||||
draggable
|
||||
laneDraggable={false}
|
||||
eventBusHandle={setEventBus}
|
||||
components={{ Card: WhiteBoardCard }}
|
||||
onCardClick={(cardId, metadata) =>
|
||||
|
||||
@@ -13,39 +13,34 @@ export default function WhiteBoardKanBanContainer() {
|
||||
}
|
||||
);
|
||||
|
||||
const static_data = {
|
||||
lanes: [
|
||||
{
|
||||
id: "lane1",
|
||||
title: "Planned Tasks",
|
||||
label: "2/2",
|
||||
cards: [
|
||||
{
|
||||
id: "Card1",
|
||||
title: "Write Blog",
|
||||
description: "Can AI make memes",
|
||||
label: "30 mins"
|
||||
},
|
||||
{
|
||||
id: "Card2",
|
||||
title: "Pay Rent",
|
||||
description: "Transfer via NEFT",
|
||||
label: "5 mins",
|
||||
metadata: { sha: "be312a1" }
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: "lane2",
|
||||
title: "Completed",
|
||||
label: "0/0",
|
||||
cards: []
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
if (loading) return <LoadingSpinner />;
|
||||
if (error) return <Alert message={error.message} />;
|
||||
let eventBus;
|
||||
return <WhiteBoardKanBan eventBus={eventBus} data={static_data} />;
|
||||
|
||||
let i = data.job_status.reduce((acc, value) => {
|
||||
//Create a lane object for each row.
|
||||
let newLane = {
|
||||
id: value.name,
|
||||
title: value.name,
|
||||
label: "0",
|
||||
cards: value.jobs.reduce((acc, value) => {
|
||||
acc.push({
|
||||
id: value.id,
|
||||
title: value.ro_number,
|
||||
description: value.est_number,
|
||||
label: value.id,
|
||||
metadata: value
|
||||
});
|
||||
return acc;
|
||||
}, [])
|
||||
};
|
||||
acc.push(newLane);
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
let laneData = {
|
||||
lanes: i
|
||||
};
|
||||
|
||||
return <WhiteBoardKanBan eventBus={eventBus} data={laneData} />;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user