Fixed vendor issues + new logos
@@ -24450,6 +24450,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>shop-vendors</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
<concept_node>
|
<concept_node>
|
||||||
<name>timetickets</name>
|
<name>timetickets</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 86 KiB |
|
Before Width: | Height: | Size: 8.4 KiB After Width: | Height: | Size: 8.7 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 9.1 KiB |
BIN
client/public/vorfahrt.png
Normal file
|
After Width: | Height: | Size: 100 KiB |
@@ -69,6 +69,7 @@ function Header({
|
|||||||
<Menu
|
<Menu
|
||||||
mode="horizontal"
|
mode="horizontal"
|
||||||
theme="light"
|
theme="light"
|
||||||
|
style={{ backgroundColor: "#eee" }}
|
||||||
className="header-main-menu"
|
className="header-main-menu"
|
||||||
selectedKeys={[selectedHeader]}
|
selectedKeys={[selectedHeader]}
|
||||||
onClick={handleMenuClick}
|
onClick={handleMenuClick}
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
import { DeleteFilled } from "@ant-design/icons";
|
import { DeleteFilled } from "@ant-design/icons";
|
||||||
import { Button, Form, Input, InputNumber, Select } from "antd";
|
import { Button, Form, Input, InputNumber, Select, Space } from "antd";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import InputNumberCalculator from "../form-input-number-calculator/form-input-number-calculator.component";
|
import InputNumberCalculator from "../form-input-number-calculator/form-input-number-calculator.component";
|
||||||
import FormItemEmail from "../form-items-formatted/email-form-item.component";
|
import FormItemEmail from "../form-items-formatted/email-form-item.component";
|
||||||
|
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
|
||||||
|
|
||||||
export default function VendorsFormComponent({
|
export default function VendorsFormComponent({
|
||||||
form,
|
form,
|
||||||
|
formLoading,
|
||||||
handleDelete,
|
handleDelete,
|
||||||
responsibilityCenters,
|
responsibilityCenters,
|
||||||
}) {
|
}) {
|
||||||
@@ -14,12 +16,91 @@ export default function VendorsFormComponent({
|
|||||||
const { getFieldValue } = form;
|
const { getFieldValue } = form;
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Button htmlType="submit" type="primary">
|
<Space>
|
||||||
{t("general.actions.save")}
|
<Button
|
||||||
</Button>
|
onClick={() => form.submit()}
|
||||||
<Button type="danger" onClick={handleDelete}>
|
type="primary"
|
||||||
{t("general.actions.delete")}
|
loading={formLoading}
|
||||||
</Button>
|
>
|
||||||
|
{t("general.actions.save")}
|
||||||
|
</Button>
|
||||||
|
<Button type="danger" onClick={handleDelete} loading={formLoading}>
|
||||||
|
{t("general.actions.delete")}
|
||||||
|
</Button>
|
||||||
|
</Space>
|
||||||
|
<LayoutFormRow grow>
|
||||||
|
<Form.Item label={t("vendors.fields.name")} name="name">
|
||||||
|
<Input />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label={t("vendors.fields.email")}
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
type: "email",
|
||||||
|
message: t("general.validation.invalidemail"),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
name="email"
|
||||||
|
>
|
||||||
|
<FormItemEmail email={getFieldValue("email")} />
|
||||||
|
</Form.Item>
|
||||||
|
</LayoutFormRow>
|
||||||
|
<LayoutFormRow grow>
|
||||||
|
<Form.Item label={t("vendors.fields.street1")} name="street1">
|
||||||
|
<Input />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item label={t("vendors.fields.street2")} name="street2">
|
||||||
|
<Input />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item label={t("vendors.fields.city")} name="city">
|
||||||
|
<Input />
|
||||||
|
</Form.Item>
|
||||||
|
</LayoutFormRow>
|
||||||
|
<LayoutFormRow grow>
|
||||||
|
{" "}
|
||||||
|
<Form.Item label={t("vendors.fields.state")} name="state">
|
||||||
|
<Input />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item label={t("vendors.fields.zip")} name="zip">
|
||||||
|
<Input />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item label={t("vendors.fields.country")} name="country">
|
||||||
|
<Input />
|
||||||
|
</Form.Item>
|
||||||
|
</LayoutFormRow>
|
||||||
|
<LayoutFormRow>
|
||||||
|
<Form.Item label={t("vendors.fields.discount")} name="discount">
|
||||||
|
<InputNumberCalculator />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item label={t("vendors.fields.terms")} name="terms">
|
||||||
|
<Input />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item label={t("vendors.fields.due_date")} name="due_date">
|
||||||
|
<InputNumber />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item label={t("vendors.fields.taxid")} name="taxid">
|
||||||
|
<Input />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label={t("vendors.fields.prompt_discount")}
|
||||||
|
name="prompt_discount"
|
||||||
|
>
|
||||||
|
<InputNumberCalculator />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label={t("vendors.fields.cost_center")}
|
||||||
|
rules={[
|
||||||
|
{ required: true, message: t("general.validation.required") },
|
||||||
|
]}
|
||||||
|
name="cost_center"
|
||||||
|
>
|
||||||
|
<Select style={{ width: "150px" }}>
|
||||||
|
{responsibilityCenters.costs.map((item) => (
|
||||||
|
<Select.Option key={item.name}>{item.name}</Select.Option>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
</Form.Item>
|
||||||
|
</LayoutFormRow>
|
||||||
|
|
||||||
<Form.List name="favorite">
|
<Form.List name="favorite">
|
||||||
{(fields, { add, remove }) => {
|
{(fields, { add, remove }) => {
|
||||||
@@ -65,72 +146,6 @@ export default function VendorsFormComponent({
|
|||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
</Form.List>
|
</Form.List>
|
||||||
|
|
||||||
<Form.Item label={t("vendors.fields.zip")} name="zip">
|
|
||||||
<Input />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label={t("vendors.fields.terms")} name="terms">
|
|
||||||
<Input />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label={t("vendors.fields.taxid")} name="taxid">
|
|
||||||
<Input />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label={t("vendors.fields.street1")} name="street1">
|
|
||||||
<Input />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label={t("vendors.fields.street2")} name="street2">
|
|
||||||
<Input />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label={t("vendors.fields.state")} name="state">
|
|
||||||
<Input />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("vendors.fields.prompt_discount")}
|
|
||||||
name="prompt_discount"
|
|
||||||
>
|
|
||||||
<InputNumberCalculator />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label={t("vendors.fields.name")} name="name">
|
|
||||||
<Input />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("vendors.fields.email")}
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
type: "email",
|
|
||||||
message: t("general.validation.invalidemail"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
name="email"
|
|
||||||
>
|
|
||||||
<FormItemEmail email={getFieldValue("email")} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label={t("vendors.fields.due_date")} name="due_date">
|
|
||||||
<InputNumber />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label={t("vendors.fields.display_name")} name="display_name">
|
|
||||||
<Input />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label={t("vendors.fields.discount")} name="discount">
|
|
||||||
<InputNumberCalculator />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label={t("vendors.fields.country")} name="country">
|
|
||||||
<Input />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("vendors.fields.cost_center")}
|
|
||||||
rules={[{ required: true, message: t("general.validation.required") }]}
|
|
||||||
name="cost_center"
|
|
||||||
>
|
|
||||||
<Select style={{ width: "150px" }}>
|
|
||||||
{responsibilityCenters.costs.map((item) => (
|
|
||||||
<Select.Option key={item.name}>{item.name}</Select.Option>
|
|
||||||
))}
|
|
||||||
</Select>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label={t("vendors.fields.city")} name="city">
|
|
||||||
<Input />
|
|
||||||
</Form.Item>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,17 @@
|
|||||||
import { useMutation, useQuery } from "@apollo/react-hooks";
|
import { useMutation, useQuery } from "@apollo/react-hooks";
|
||||||
import { Form, notification } from "antd";
|
import { Form, notification } from "antd";
|
||||||
import queryString from "query-string";
|
import queryString from "query-string";
|
||||||
import React, { useEffect } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { useLocation } from "react-router-dom";
|
import { useLocation } from "react-router-dom";
|
||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
import { DELETE_VENDOR, INSERT_NEW_VENDOR, QUERY_VENDOR_BY_ID, UPDATE_VENDOR } from "../../graphql/vendors.queries";
|
import {
|
||||||
|
DELETE_VENDOR,
|
||||||
|
INSERT_NEW_VENDOR,
|
||||||
|
QUERY_VENDOR_BY_ID,
|
||||||
|
UPDATE_VENDOR,
|
||||||
|
} from "../../graphql/vendors.queries";
|
||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
import AlertComponent from "../alert/alert.component";
|
import AlertComponent from "../alert/alert.component";
|
||||||
import LoadingSpinner from "../loading-spinner/loading-spinner.component";
|
import LoadingSpinner from "../loading-spinner/loading-spinner.component";
|
||||||
@@ -19,7 +24,7 @@ const mapStateToProps = createStructuredSelector({
|
|||||||
function VendorsFormContainer({ refetch, bodyshop }) {
|
function VendorsFormContainer({ refetch, bodyshop }) {
|
||||||
const search = queryString.parse(useLocation().search);
|
const search = queryString.parse(useLocation().search);
|
||||||
const { selectedvendor } = search;
|
const { selectedvendor } = search;
|
||||||
|
const [formLoading, setFormLoading] = useState(false);
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { loading, error, data } = useQuery(QUERY_VENDOR_BY_ID, {
|
const { loading, error, data } = useQuery(QUERY_VENDOR_BY_ID, {
|
||||||
@@ -32,6 +37,7 @@ function VendorsFormContainer({ refetch, bodyshop }) {
|
|||||||
const [insertvendor] = useMutation(INSERT_NEW_VENDOR);
|
const [insertvendor] = useMutation(INSERT_NEW_VENDOR);
|
||||||
const [deleteVendor] = useMutation(DELETE_VENDOR);
|
const [deleteVendor] = useMutation(DELETE_VENDOR);
|
||||||
const handleDelete = () => {
|
const handleDelete = () => {
|
||||||
|
setFormLoading(true);
|
||||||
deleteVendor({ variables: { id: selectedvendor } })
|
deleteVendor({ variables: { id: selectedvendor } })
|
||||||
.then((r) => {
|
.then((r) => {
|
||||||
notification["success"]({
|
notification["success"]({
|
||||||
@@ -45,9 +51,11 @@ function VendorsFormContainer({ refetch, bodyshop }) {
|
|||||||
message: t("vendors.errors.deleting"),
|
message: t("vendors.errors.deleting"),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
setFormLoading(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleFinish = (values) => {
|
const handleFinish = (values) => {
|
||||||
|
setFormLoading(true);
|
||||||
if (selectedvendor && selectedvendor !== "new") {
|
if (selectedvendor && selectedvendor !== "new") {
|
||||||
//It's a vendor to update.
|
//It's a vendor to update.
|
||||||
updateVendor({
|
updateVendor({
|
||||||
@@ -85,6 +93,7 @@ function VendorsFormContainer({ refetch, bodyshop }) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
setFormLoading(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -92,16 +101,19 @@ function VendorsFormContainer({ refetch, bodyshop }) {
|
|||||||
}, [data, form, selectedvendor]);
|
}, [data, form, selectedvendor]);
|
||||||
|
|
||||||
if (loading) return <LoadingSpinner />;
|
if (loading) return <LoadingSpinner />;
|
||||||
if (error) return <AlertComponent message={error.message} type='error' />;
|
if (error) return <AlertComponent message={error.message} type="error" />;
|
||||||
return (
|
return (
|
||||||
<Form
|
<Form
|
||||||
onFinish={handleFinish}
|
onFinish={handleFinish}
|
||||||
form={form}
|
form={form}
|
||||||
autoComplete='new-password'
|
layout="vertical"
|
||||||
initialValues={data ? data.vendors_by_pk : null}>
|
autoComplete="new-password"
|
||||||
|
initialValues={data ? data.vendors_by_pk : null}
|
||||||
|
>
|
||||||
{selectedvendor ? (
|
{selectedvendor ? (
|
||||||
<VendorsFormComponent
|
<VendorsFormComponent
|
||||||
form={form}
|
form={form}
|
||||||
|
formLoading={formLoading}
|
||||||
handleDelete={handleDelete}
|
handleDelete={handleDelete}
|
||||||
responsibilityCenters={bodyshop.md_responsibility_centers || null}
|
responsibilityCenters={bodyshop.md_responsibility_centers || null}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ export const QUERY_VENDOR_BY_ID = gql`
|
|||||||
favorite
|
favorite
|
||||||
email
|
email
|
||||||
due_date
|
due_date
|
||||||
display_name
|
|
||||||
discount
|
discount
|
||||||
country
|
country
|
||||||
cost_center
|
cost_center
|
||||||
|
|||||||
@@ -158,7 +158,7 @@ export function Manage({ match, conflict }) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Layout className="layout-container">
|
<Layout className="layout-container">
|
||||||
<Header style={{ background: "#fff" }}>
|
<Header style={{ background: "azure" }}>
|
||||||
<HeaderContainer />
|
<HeaderContainer />
|
||||||
</Header>
|
</Header>
|
||||||
<Content className="content-container">
|
<Content className="content-container">
|
||||||
|
|||||||
@@ -1,12 +1,28 @@
|
|||||||
|
import { Col, Row } from "antd";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import VendorsListContainer from "../../components/vendors-list/vendors-list.container";
|
|
||||||
import VendorsFormContainer from "../../components/vendors-form/vendors-form.container";
|
import VendorsFormContainer from "../../components/vendors-form/vendors-form.container";
|
||||||
|
import VendorsListContainer from "../../components/vendors-list/vendors-list.container";
|
||||||
|
|
||||||
|
const listSpan = {
|
||||||
|
md: { span: 24 },
|
||||||
|
lg: { span: 8 },
|
||||||
|
};
|
||||||
|
const formSapn = {
|
||||||
|
md: { span: 24 },
|
||||||
|
lg: { span: 16 },
|
||||||
|
};
|
||||||
|
|
||||||
export default function ShopVendorPageComponent() {
|
export default function ShopVendorPageComponent() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<VendorsListContainer />
|
<Row gutter={[16, 16]}>
|
||||||
<VendorsFormContainer />
|
<Col {...listSpan}>
|
||||||
|
<VendorsListContainer />
|
||||||
|
</Col>
|
||||||
|
<Col {...formSapn}>
|
||||||
|
<VendorsFormContainer />
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1514,6 +1514,7 @@
|
|||||||
"shop": "Manage my Shop ({{shopname}})",
|
"shop": "Manage my Shop ({{shopname}})",
|
||||||
"shop-csi": "CSI Responses",
|
"shop-csi": "CSI Responses",
|
||||||
"shop-templates": "Shop Templates",
|
"shop-templates": "Shop Templates",
|
||||||
|
"shop-vendors": "Vendors",
|
||||||
"timetickets": "Time Tickets",
|
"timetickets": "Time Tickets",
|
||||||
"vehicle-details": "Vehicle: {{vehicle}}",
|
"vehicle-details": "Vehicle: {{vehicle}}",
|
||||||
"vehicles": "Vehicles"
|
"vehicles": "Vehicles"
|
||||||
|
|||||||
@@ -1514,6 +1514,7 @@
|
|||||||
"shop": "",
|
"shop": "",
|
||||||
"shop-csi": "",
|
"shop-csi": "",
|
||||||
"shop-templates": "",
|
"shop-templates": "",
|
||||||
|
"shop-vendors": "",
|
||||||
"timetickets": "",
|
"timetickets": "",
|
||||||
"vehicle-details": "",
|
"vehicle-details": "",
|
||||||
"vehicles": ""
|
"vehicles": ""
|
||||||
|
|||||||
@@ -1514,6 +1514,7 @@
|
|||||||
"shop": "",
|
"shop": "",
|
||||||
"shop-csi": "",
|
"shop-csi": "",
|
||||||
"shop-templates": "",
|
"shop-templates": "",
|
||||||
|
"shop-vendors": "",
|
||||||
"timetickets": "",
|
"timetickets": "",
|
||||||
"vehicle-details": "",
|
"vehicle-details": "",
|
||||||
"vehicles": ""
|
"vehicles": ""
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
- args:
|
||||||
|
cascade: false
|
||||||
|
read_only: false
|
||||||
|
sql: ALTER TABLE "public"."vendors" ADD COLUMN "display_name" text;
|
||||||
|
type: run_sql
|
||||||
|
- args:
|
||||||
|
cascade: false
|
||||||
|
read_only: false
|
||||||
|
sql: ALTER TABLE "public"."vendors" ALTER COLUMN "display_name" DROP NOT NULL;
|
||||||
|
type: run_sql
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
- args:
|
||||||
|
cascade: true
|
||||||
|
read_only: false
|
||||||
|
sql: ALTER TABLE "public"."vendors" DROP COLUMN "display_name" CASCADE;
|
||||||
|
type: run_sql
|
||||||