WIP Download Images + Invoice Tables

This commit is contained in:
Patrick Fic
2020-03-06 14:52:47 -08:00
parent 50bc42347a
commit dd0562cae3
11 changed files with 286 additions and 29 deletions

View File

@@ -1,54 +1,64 @@
import { Card } from "antd";
import React, { useState } from "react";
import { Responsive, WidthProvider } from "react-grid-layout";
import styled from "styled-components";
//Combination of the following:
// /node_modules/react-grid-layout/css/styles.css
// /node_modules/react-resizable/css/styles.css
import "./dashboard-grid.styles.css";
const Sdiv = styled.div`
position: absolute;
height: 80%;
width: 80%;
top: 10%;
left: 10%;
background-color: #ffcc00;
`;
const ResponsiveReactGridLayout = WidthProvider(Responsive);
export default function DashboardGridComponent() {
const [state, setState] = useState({
layout: [
{ x: 0, y: 0, w: 2, h: 2 },
{ x: 1, y: 0, w: 2, h: 2 },
{ x: 4, y: 0, w: 2, h: 2 }
{ i: "1", x: 0, y: 0, w: 2, h: 2 },
{ i: "2", x: 2, y: 0, w: 2, h: 2 },
{ i: "3", x: 4, y: 0, w: 2, h: 2 }
]
});
const defaultProps = {
className: "layout",
breakpoints: { lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 },
cols: { lg: 12, md: 10, sm: 6, xs: 4, xxs: 2 },
rowHeight: 100
breakpoints: { lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 }
// cols: { lg: 12, md: 10, sm: 6, xs: 4, xxs: 2 },
// rowHeight: 100
};
// We're using the cols coming back from this to calculate where to add new items.
const onBreakpointChange = (breakpoint, cols) => {
console.log("breakpoint, cols", breakpoint, cols);
setState({ ...state, breakpoint: breakpoint, cols: cols });
// setState({ ...state, breakpoint: breakpoint, cols: cols });
};
return (
<div style={{ width: "100%", height: " 100%" }}>
<Sdiv>
The Grid.
<ResponsiveReactGridLayout
{...defaultProps}
onBreakpointChange={onBreakpointChange}
width="100%"
onLayoutChange={layout => {
console.log("layout", layout);
setState({ ...state, layout });
}}
>
{state.layout.map((item, index) => {
console.log("item", item);
return (
<Card style={{ width: "100px" }} key={index} data-grid={item}>
<Card style={{ width: "100px" }} key={item.i} data-grid={item}>
A Card {index}
</Card>
);
})}
</ResponsiveReactGridLayout>
</div>
</Sdiv>
);
}

View File

@@ -0,0 +1,71 @@
import { Table } from "antd";
import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import { alphaSort } from "../../utils/sorters";
import { DateFormatter } from "../../utils/DateFormatter";
export default function InvoicesListTableComponent({ loading, invoices }) {
const [state, setState] = useState({
sortedInfo: {}
});
const { t } = useTranslation();
const columns = [
{
title: t("invoices.fields.vendorname"),
dataIndex: "vendorname",
key: "vendorname",
// onFilter: (value, record) => record.ro_number.includes(value),
// filteredValue: state.filteredInfo.text || null,
sorter: (a, b) => alphaSort(a.vendor.name, b.vendor.name),
sortOrder:
state.sortedInfo.columnKey === "vendorname" && state.sortedInfo.order,
//ellipsis: true,
render: (text, record) => <span>{record.vendor.name}</span>
},
{
title: t("invoices.fields.invoice_number"),
dataIndex: "invoice_number",
key: "invoice_number",
// onFilter: (value, record) => record.ro_number.includes(value),
// filteredValue: state.filteredInfo.text || null,
sorter: (a, b) => alphaSort(a.invoice_number, b.invoice_number),
sortOrder:
state.sortedInfo.columnKey === "invoice_number" &&
state.sortedInfo.order
//ellipsis: true,
},
{
title: t("invoices.fields.date"),
dataIndex: "date",
key: "date",
// onFilter: (value, record) => record.ro_number.includes(value),
// filteredValue: state.filteredInfo.text || null,
sorter: (a, b) => a.date - b.date,
sortOrder:
state.sortedInfo.columnKey === "date" && state.sortedInfo.order,
//ellipsis: true,
render: (text, record) => <DateFormatter>{record.date}</DateFormatter>
}
];
const handleTableChange = (pagination, filters, sorter) => {
setState({ ...state, filteredInfo: filters, sortedInfo: sorter });
};
const rowExpander = record => (
<div style={{ margin: 0 }}>Invoice details</div>
);
return (
<Table
loading={loading}
size="small"
expandedRowRender={rowExpander}
pagination={{ position: "top", defaultPageSize: 25 }}
columns={columns.map(item => ({ ...item }))}
rowKey="id"
dataSource={invoices}
onChange={handleTableChange}
/>
);
}

View File

@@ -1,17 +1,15 @@
import { Button } from "antd";
import React from "react";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import {
toggleModalVisible,
setModalContext
} from "../../redux/modals/modals.actions";
import { Button } from "antd";
import { setModalContext } from "../../redux/modals/modals.actions";
import InvoicesListTableComponent from "../invoices-list-table/invoices-list-table.component";
import AlertComponent from "../alert/alert.component";
const mapStateToProps = createStructuredSelector({
//currentUser: selectCurrentUser
});
const mapDispatchToProps = dispatch => ({
toggleModalVisible: () => dispatch(toggleModalVisible("invoiceEnter")),
setInvoiceEnterContext: context =>
dispatch(setModalContext({ context: context, modal: "invoiceEnter" }))
});
@@ -19,9 +17,9 @@ export default connect(
mapStateToProps,
mapDispatchToProps
)(function JobsDetailPliComponent({
toggleModalVisible,
setInvoiceEnterContext,
job
job,
invoicesQuery
}) {
return (
<div>
@@ -37,6 +35,13 @@ export default connect(
>
Enter Invoice
</Button>
{invoicesQuery.error ? (
<AlertComponent message={invoicesQuery.error.message} type="error" />
) : null}
<InvoicesListTableComponent
loading={invoicesQuery.loading}
invoices={invoicesQuery.data ? invoicesQuery.data.invoices : null}
/>
</div>
);
});

View File

@@ -1,7 +1,12 @@
import React from "react";
import { useQuery } from "react-apollo";
import JobsDetailPliComponent from "./jobs-detail-pli.component";
import { QUERY_INVOICES_BY_JOBID } from "../../graphql/invoices.queries";
export default function JobsDetailPliContainer({ job }) {
console.log("job", job);
return <JobsDetailPliComponent job={job} />;
const invoicesQuery = useQuery(QUERY_INVOICES_BY_JOBID, {
variables: { jobid: job.id },
fetchPolicy: "network-only"
});
return <JobsDetailPliComponent job={job} invoicesQuery={invoicesQuery} />;
}

View File

@@ -1,16 +1,17 @@
import { Modal, notification, Upload } from "antd";
import { InboxOutlined } from "@ant-design/icons";
import { Modal, notification, Upload } from "antd";
import axios from "axios";
import React, { useState } from "react";
import { useMutation } from "react-apollo";
import Gallery from "react-grid-gallery";
import { useTranslation } from "react-i18next";
import Resizer from "react-image-file-resizer";
import {
INSERT_NEW_DOCUMENT,
DELETE_DOCUMENT
DELETE_DOCUMENT,
INSERT_NEW_DOCUMENT
} from "../../graphql/documents.queries";
import "./jobs-documents.styles.scss";
import { generateCdnThumb } from "../../utils/DocHelpers";
import "./jobs-documents.styles.scss";
function getBase64(file) {
return new Promise((resolve, reject) => {
@@ -45,6 +46,19 @@ function JobsDocumentsComponent({ shopId, jobId, loading, data, currentUser }) {
}, [])
);
const [galleryImages, setgalleryImages] = useState(
data.reduce((acc, value) => {
acc.push({
src: value.url,
thumbnail: value.thumb_url,
thumbnailHeight: 150,
thumbnailWidth: 150,
isSelected: false
});
return acc;
}, [])
);
const uploadToS3 = (
fileName,
fileType,
@@ -246,6 +260,29 @@ function JobsDocumentsComponent({ shopId, jobId, loading, data, currentUser }) {
<Modal visible={previewVisible} footer={null} onCancel={handleCancel}>
<img alt="example" style={{ width: "100%" }} src={previewImage} />
</Modal>
<button
onClick={() => {
axios
.get("/downloadImages", {
images: galleryImages.map(i => i.src)
})
.then(r => console.log("r", r));
}}
>
Dl
</button>
<Gallery
images={galleryImages}
onSelectImage={(index, image) => {
console.log("index, image", index, image);
setgalleryImages(
galleryImages.map((g, idx) =>
index === idx ? { ...g, isSelected: !g.isSelected } : g
)
);
}}
></Gallery>
</div>
);
}

View File

@@ -9,3 +9,25 @@ export const INSERT_NEW_INVOICE = gql`
}
}
`;
export const QUERY_INVOICES_BY_JOBID = gql`
query QUERY_INVOICES_BY_JOBID($jobid: uuid!) {
invoices(where: { jobid: { _eq: $jobid } }, order_by: { date: desc }) {
id
vendor {
id
name
}
total
invoice_number
date
invoicelines {
actual_price
actual_cost
cost_center
id
line_desc
}
}
}
`;

View File

@@ -4,8 +4,8 @@ export const generateCdnThumb = key => {
key: key,
edits: {
resize: {
height: 100,
width: 100
height: 150,
width: 150
}
}
});