diff --git a/bodyshop_translations.babel b/bodyshop_translations.babel index d872dc2b0..66b40af7a 100644 --- a/bodyshop_translations.babel +++ b/bodyshop_translations.babel @@ -4844,6 +4844,48 @@ + + shop_config + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + shop_vendors + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + vehicles false @@ -6065,6 +6107,27 @@ + + shop_vendors + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + vehicledetail false @@ -6753,6 +6816,121 @@ + + vendors + + + fields + + + city + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + cost_center + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + favorite + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + name + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + street1 + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + + + diff --git a/client/src/components/allocations-assignment/allocations-assignment.container.jsx b/client/src/components/allocations-assignment/allocations-assignment.container.jsx index 3369d6904..4cfd62fe3 100644 --- a/client/src/components/allocations-assignment/allocations-assignment.container.jsx +++ b/client/src/components/allocations-assignment/allocations-assignment.container.jsx @@ -5,7 +5,11 @@ import { INSERT_ALLOCATION } from "../../graphql/allocations.queries"; import { useTranslation } from "react-i18next"; import { notification } from "antd"; -export default function AllocationsAssignmentContainer({ jobLineId, hours }) { +export default function AllocationsAssignmentContainer({ + jobLineId, + hours, + refetch +}) { const visibilityState = useState(false); const { t } = useTranslation(); const [assignment, setAssignment] = useState({ @@ -22,7 +26,7 @@ export default function AllocationsAssignmentContainer({ jobLineId, hours }) { }); //TODO: Better way to reset the field decorators? visibilityState[1](false); - //refetch().then(r => form.resetFields()); + if (refetch) refetch(); }); }; diff --git a/client/src/components/header/header.component.jsx b/client/src/components/header/header.component.jsx index 478789c1e..2393f5e51 100644 --- a/client/src/components/header/header.component.jsx +++ b/client/src/components/header/header.component.jsx @@ -71,12 +71,16 @@ export default ({ - - - - {t("menus.header.shop")} - - + + + {t("menus.header.shop_config")} + + + + {t("menus.header.shop_vendors")} + + + @@ -187,6 +190,7 @@ export default function JobLinesComponent({ ); }} {...formItemLayout} + loading={loading} size="small" pagination={{ position: "bottom", defaultPageSize: 50 }} rowSelection={{ diff --git a/client/src/components/job-detail-lines/job-lines.container.jsx b/client/src/components/job-detail-lines/job-lines.container.jsx index 6223e80a3..a65c03e1c 100644 --- a/client/src/components/job-detail-lines/job-lines.container.jsx +++ b/client/src/components/job-detail-lines/job-lines.container.jsx @@ -8,7 +8,7 @@ import JobLinesComponent from "./job-lines.component"; //export default Form.create({ name: "JobsDetailJobLines" })( export default function JobLinesContainer({ jobId }) { - const { loading, error, data } = useQuery(GET_JOB_LINES_BY_PK, { + const { loading, error, data, refetch } = useQuery(GET_JOB_LINES_BY_PK, { variables: { id: jobId }, fetchPolicy: "network-only" }); @@ -21,6 +21,7 @@ export default function JobLinesContainer({ jobId }) { return ( setModalVisible(false)}> diff --git a/client/src/components/vendors-list/vendors-list.component.jsx b/client/src/components/vendors-list/vendors-list.component.jsx new file mode 100644 index 000000000..3813180fc --- /dev/null +++ b/client/src/components/vendors-list/vendors-list.component.jsx @@ -0,0 +1,107 @@ +import { Input, Table } from "antd"; +import React, { useState } from "react"; +import { useTranslation } from "react-i18next"; +import { alphaSort } from "../../utils/sorters"; +export default function VendorsListComponent({ + selectedVendor, + setSelectedVendor, + loading, + refetch, + vendors +}) { + const [state, setState] = useState({ + sortedInfo: {}, + filteredInfo: { text: "" } + }); + + const { t } = useTranslation(); + + const columns = [ + { + title: t("vendors.fields.name"), + dataIndex: "name", + key: "name", + sorter: (a, b) => alphaSort(a.name, b.name), + sortOrder: state.sortedInfo.columnKey === "name" && state.sortedInfo.order + }, + { + title: t("vendors.fields.favorite"), + dataIndex: "favorite", + key: "favorite" + }, + { + title: t("vendors.fields.cost_center"), + dataIndex: "cost_center", + key: "cost_center", + sorter: (a, b) => alphaSort(a.cost_center, b.cost_center), + sortOrder: + state.sortedInfo.columnKey === "cost_center" && state.sortedInfo.order + }, + { + title: t("vendors.fields.street1"), + dataIndex: "street1", + key: "street1", + width: "10%", + sorter: (a, b) => alphaSort(a.street1, b.street1), + sortOrder: + state.sortedInfo.columnKey === "street1" && state.sortedInfo.order + }, + { + title: t("vendors.fields.city"), + dataIndex: "city", + key: "city" + } + ]; + + const handleTableChange = (pagination, filters, sorter) => { + setState({ ...state, filteredInfo: filters, sortedInfo: sorter }); + }; + + const handleOnRowClick = record => { + if (record) { + setSelectedVendor(record); + return; + } + setSelectedVendor(null); + }; + + //TODO Implement search + return ( +
+ { + return ( + { + console.log(value); + }} + enterButton + /> + ); + }} + size="small" + pagination={{ position: "top" }} + columns={columns.map(item => ({ ...item }))} + rowKey="id" + onChange={handleTableChange} + dataSource={vendors} + rowSelection={{ + onSelect: record => { + setSelectedVendor(record); + }, + type: "radio", + selectedRowKeys: selectedVendor.id || null + }} + onRow={(record, rowIndex) => { + return { + onClick: event => { + handleOnRowClick(record); + } + }; + }} + /> + + ); +} diff --git a/client/src/components/vendors-list/vendors-list.container.jsx b/client/src/components/vendors-list/vendors-list.container.jsx new file mode 100644 index 000000000..d2fc5c288 --- /dev/null +++ b/client/src/components/vendors-list/vendors-list.container.jsx @@ -0,0 +1,32 @@ +import React from "react"; +import { useQuery } from "react-apollo"; +import AlertComponent from "../../components/alert/alert.component"; +import { QUERY_ALL_VENDORS, QUERY_VENDOR_BY_ID } from "../../graphql/vendors.queries"; +import VendorsListComponent from "./vendors-list.component"; + +export default function VendorsListContainer({ selectedVendorState }) { + const [selectedVendor, setSelectedVendor] = selectedVendorState; + const { loading, error, data, refetch } = useQuery(QUERY_ALL_VENDORS, { + fetchPolicy: "network-only" + }); + + const vendorDetail = useQuery(QUERY_VENDOR_BY_ID, { + fetchPolicy: "network-only", + variables: { id: selectedVendor.id }, + skip: !selectedVendor.id + }); + + if (error) return ; + return ( +
+ + {JSON.stringify(vendorDetail && vendorDetail.data)} +
+ ); +} diff --git a/client/src/graphql/vendors.queries.js b/client/src/graphql/vendors.queries.js new file mode 100644 index 000000000..35853b526 --- /dev/null +++ b/client/src/graphql/vendors.queries.js @@ -0,0 +1,48 @@ +import { gql } from "apollo-boost"; + +export const QUERY_VENDOR_BY_ID = gql` + query QUERY_VENDOR_BY_ID($id: uuid!) { + vendors_by_pk(id: $id) { + zip + terms + taxid + street2 + state + prompt_discount + name + id + favorite + email + due_date + display_name + discount + country + cost_center + city + street1 + } + } +`; + +export const UPDATE_VEHICLE = gql` + mutation UPDATE_VEHICLE($vehId: uuid!, $vehicle: vehicles_set_input!) { + update_vehicles(where: { id: { _eq: $vehId } }, _set: $vehicle) { + returning { + id + } + } + } +`; + +export const QUERY_ALL_VENDORS = gql` + query QUERY_ALL_VENDORS { + vendors { + name + id + favorite + street1 + cost_center + city + } + } +`; diff --git a/client/src/pages/manage/manage.page.jsx b/client/src/pages/manage/manage.page.jsx index 60467e16c..9c04acbec 100644 --- a/client/src/pages/manage/manage.page.jsx +++ b/client/src/pages/manage/manage.page.jsx @@ -40,6 +40,9 @@ const OwnersDetailContainer = lazy(() => import("../owners-detail/owners-detail.page.container") ); const ShopPage = lazy(() => import("../shop/shop.page.component")); +const ShopVendorPageContainer = lazy(() => + import("../shop-vendor/shop-vendor.page.container") +); const { Header, Content, Footer } = Layout; @@ -118,6 +121,11 @@ export default function Manage({ match }) { /> + diff --git a/client/src/pages/shop-vendor/shop-vendor.page.component.jsx b/client/src/pages/shop-vendor/shop-vendor.page.component.jsx new file mode 100644 index 000000000..1f4eb05a8 --- /dev/null +++ b/client/src/pages/shop-vendor/shop-vendor.page.component.jsx @@ -0,0 +1,10 @@ +import React from "react"; +import VendorsListContainer from "../../components/vendors-list/vendors-list.container"; + +export default function ShopVendorPageComponent({ selectedVendorState }) { + return ( +
+ +
+ ); +} diff --git a/client/src/pages/shop-vendor/shop-vendor.page.container.jsx b/client/src/pages/shop-vendor/shop-vendor.page.container.jsx new file mode 100644 index 000000000..2ecf0273d --- /dev/null +++ b/client/src/pages/shop-vendor/shop-vendor.page.container.jsx @@ -0,0 +1,17 @@ +import React, { useEffect, useState } from "react"; +import { useTranslation } from "react-i18next"; +import ShopVendorPageComponent from "./shop-vendor.page.component"; + +export default function ShopVendorPageContainer() { + const { t } = useTranslation(); + useEffect(() => { + document.title = t("titles.shop_vendors"); + }, [t]); + + const selectedVendorState = useState({}); + return ( +
+ +
+ ); +} diff --git a/client/src/translations/en_us/common.json b/client/src/translations/en_us/common.json index 0ed3fbc99..33ed17d5e 100644 --- a/client/src/translations/en_us/common.json +++ b/client/src/translations/en_us/common.json @@ -302,6 +302,8 @@ "owners": "Owners", "schedule": "Schedule", "shop": "My Shop", + "shop_config": "Configuration", + "shop_vendors": "Vendors", "vehicles": "Vehicles" }, "jobsdetail": { @@ -391,6 +393,7 @@ "profile": "My Profile | $t(titles.app)", "schedule": "Schedule | $t(titles.app)", "shop": "My Shop | $t(titles.app)", + "shop_vendors": "Vendors | $t(titles.app)", "vehicledetail": "Vehicle Details {{vehicle}} | $t(titles.app)", "vehicles": "All Vehicles | $t(titles.app)" }, @@ -436,6 +439,15 @@ "successes": { "save": "Vehicle saved successfully." } + }, + "vendors": { + "fields": { + "city": "City", + "cost_center": "Cost Center", + "favorite": "Favorite?", + "name": "Vendor Name", + "street1": "Street" + } } } } diff --git a/client/src/translations/es/common.json b/client/src/translations/es/common.json index aee8c0f36..dc49761a0 100644 --- a/client/src/translations/es/common.json +++ b/client/src/translations/es/common.json @@ -302,6 +302,8 @@ "owners": "propietarios", "schedule": "Programar", "shop": "Mi tienda", + "shop_config": "Configuración", + "shop_vendors": "Vendedores", "vehicles": "Vehículos" }, "jobsdetail": { @@ -391,6 +393,7 @@ "profile": "Mi perfil | $t(titles.app)", "schedule": "Horario | $t(titles.app)", "shop": "Mi tienda | $t(titles.app)", + "shop_vendors": "Vendedores | $t(titles.app)", "vehicledetail": "Detalles del vehículo {{vehicle}} | $t(titles.app)", "vehicles": "Todos los vehiculos | $t(titles.app)" }, @@ -436,6 +439,15 @@ "successes": { "save": "Vehículo guardado con éxito." } + }, + "vendors": { + "fields": { + "city": "ciudad", + "cost_center": "Centro de costos", + "favorite": "¿Favorito?", + "name": "Nombre del vendedor", + "street1": "calle" + } } } } diff --git a/client/src/translations/fr/common.json b/client/src/translations/fr/common.json index a139aec87..eca19c791 100644 --- a/client/src/translations/fr/common.json +++ b/client/src/translations/fr/common.json @@ -302,6 +302,8 @@ "owners": "Propriétaires", "schedule": "Programme", "shop": "Mon magasin", + "shop_config": "Configuration", + "shop_vendors": "Vendeurs", "vehicles": "Véhicules" }, "jobsdetail": { @@ -391,6 +393,7 @@ "profile": "Mon profil | $t(titles.app)", "schedule": "Horaire | $t(titles.app)", "shop": "Mon magasin | $t(titles.app)", + "shop_vendors": "Vendeurs | $t(titles.app)", "vehicledetail": "Détails du véhicule {{vehicle} | $t(titles.app)", "vehicles": "Tous les véhicules | $t(titles.app)" }, @@ -436,6 +439,15 @@ "successes": { "save": "Le véhicule a été enregistré avec succès." } + }, + "vendors": { + "fields": { + "city": "Ville", + "cost_center": "Centre de coûts", + "favorite": "Préféré?", + "name": "Nom du vendeur", + "street1": "rue" + } } } } diff --git a/hasura/migrations/1581626650166_alter_table_public_vendors_add_column_cost_center/down.yaml b/hasura/migrations/1581626650166_alter_table_public_vendors_add_column_cost_center/down.yaml new file mode 100644 index 000000000..4dfd3d0c2 --- /dev/null +++ b/hasura/migrations/1581626650166_alter_table_public_vendors_add_column_cost_center/down.yaml @@ -0,0 +1,3 @@ +- args: + sql: ALTER TABLE "public"."vendors" DROP COLUMN "cost_center"; + type: run_sql diff --git a/hasura/migrations/1581626650166_alter_table_public_vendors_add_column_cost_center/up.yaml b/hasura/migrations/1581626650166_alter_table_public_vendors_add_column_cost_center/up.yaml new file mode 100644 index 000000000..820cc3acf --- /dev/null +++ b/hasura/migrations/1581626650166_alter_table_public_vendors_add_column_cost_center/up.yaml @@ -0,0 +1,3 @@ +- args: + sql: ALTER TABLE "public"."vendors" ADD COLUMN "cost_center" text NOT NULL; + type: run_sql diff --git a/hasura/migrations/1581626683086_alter_table_public_vendors_add_column_favorite/down.yaml b/hasura/migrations/1581626683086_alter_table_public_vendors_add_column_favorite/down.yaml new file mode 100644 index 000000000..09a6eda1f --- /dev/null +++ b/hasura/migrations/1581626683086_alter_table_public_vendors_add_column_favorite/down.yaml @@ -0,0 +1,3 @@ +- args: + sql: ALTER TABLE "public"."vendors" DROP COLUMN "favorite"; + type: run_sql diff --git a/hasura/migrations/1581626683086_alter_table_public_vendors_add_column_favorite/up.yaml b/hasura/migrations/1581626683086_alter_table_public_vendors_add_column_favorite/up.yaml new file mode 100644 index 000000000..768e11f52 --- /dev/null +++ b/hasura/migrations/1581626683086_alter_table_public_vendors_add_column_favorite/up.yaml @@ -0,0 +1,4 @@ +- args: + sql: ALTER TABLE "public"."vendors" ADD COLUMN "favorite" boolean NOT NULL DEFAULT + false; + type: run_sql diff --git a/hasura/migrations/1581630600157_update_permission_user_public_table_vendors/down.yaml b/hasura/migrations/1581630600157_update_permission_user_public_table_vendors/down.yaml new file mode 100644 index 000000000..6551fb338 --- /dev/null +++ b/hasura/migrations/1581630600157_update_permission_user_public_table_vendors/down.yaml @@ -0,0 +1,45 @@ +- args: + role: user + table: + name: vendors + schema: public + type: drop_insert_permission +- args: + permission: + check: + bodyshop: + associations: + _and: + - user: + authid: + _eq: X-Hasura-User-Id + - active: + _eq: true + columns: + - due_date + - discount + - prompt_discount + - city + - country + - display_name + - email + - name + - state + - street1 + - street2 + - taxid + - terms + - zip + - created_at + - updated_at + - bodyshopid + - id + localPresets: + - key: "" + value: "" + set: {} + role: user + table: + name: vendors + schema: public + type: create_insert_permission diff --git a/hasura/migrations/1581630600157_update_permission_user_public_table_vendors/up.yaml b/hasura/migrations/1581630600157_update_permission_user_public_table_vendors/up.yaml new file mode 100644 index 000000000..d9f4efe71 --- /dev/null +++ b/hasura/migrations/1581630600157_update_permission_user_public_table_vendors/up.yaml @@ -0,0 +1,47 @@ +- args: + role: user + table: + name: vendors + schema: public + type: drop_insert_permission +- args: + permission: + check: + bodyshop: + associations: + _and: + - user: + authid: + _eq: X-Hasura-User-Id + - active: + _eq: true + columns: + - id + - created_at + - updated_at + - bodyshopid + - name + - street1 + - street2 + - city + - state + - zip + - country + - email + - taxid + - discount + - prompt_discount + - due_date + - terms + - display_name + - cost_center + - favorite + localPresets: + - key: "" + value: "" + set: {} + role: user + table: + name: vendors + schema: public + type: create_insert_permission diff --git a/hasura/migrations/1581630604954_update_permission_user_public_table_vendors/down.yaml b/hasura/migrations/1581630604954_update_permission_user_public_table_vendors/down.yaml new file mode 100644 index 000000000..942a75880 --- /dev/null +++ b/hasura/migrations/1581630604954_update_permission_user_public_table_vendors/down.yaml @@ -0,0 +1,43 @@ +- args: + role: user + table: + name: vendors + schema: public + type: drop_select_permission +- args: + permission: + allow_aggregations: false + columns: + - due_date + - discount + - prompt_discount + - city + - country + - display_name + - email + - name + - state + - street1 + - street2 + - taxid + - terms + - zip + - created_at + - updated_at + - bodyshopid + - id + computed_fields: [] + filter: + bodyshop: + associations: + _and: + - user: + authid: + _eq: X-Hasura-User-Id + - active: + _eq: true + role: user + table: + name: vendors + schema: public + type: create_select_permission diff --git a/hasura/migrations/1581630604954_update_permission_user_public_table_vendors/up.yaml b/hasura/migrations/1581630604954_update_permission_user_public_table_vendors/up.yaml new file mode 100644 index 000000000..48f129b36 --- /dev/null +++ b/hasura/migrations/1581630604954_update_permission_user_public_table_vendors/up.yaml @@ -0,0 +1,45 @@ +- args: + role: user + table: + name: vendors + schema: public + type: drop_select_permission +- args: + permission: + allow_aggregations: false + columns: + - favorite + - due_date + - discount + - prompt_discount + - city + - cost_center + - country + - display_name + - email + - name + - state + - street1 + - street2 + - taxid + - terms + - zip + - created_at + - updated_at + - bodyshopid + - id + computed_fields: [] + filter: + bodyshop: + associations: + _and: + - user: + authid: + _eq: X-Hasura-User-Id + - active: + _eq: true + role: user + table: + name: vendors + schema: public + type: create_select_permission diff --git a/hasura/migrations/1581630611638_update_permission_user_public_table_vendors/down.yaml b/hasura/migrations/1581630611638_update_permission_user_public_table_vendors/down.yaml new file mode 100644 index 000000000..069ef986f --- /dev/null +++ b/hasura/migrations/1581630611638_update_permission_user_public_table_vendors/down.yaml @@ -0,0 +1,45 @@ +- args: + role: user + table: + name: vendors + schema: public + type: drop_update_permission +- args: + permission: + columns: + - due_date + - discount + - prompt_discount + - city + - country + - display_name + - email + - name + - state + - street1 + - street2 + - taxid + - terms + - zip + - created_at + - updated_at + - bodyshopid + - id + filter: + bodyshop: + associations: + _and: + - user: + authid: + _eq: X-Hasura-User-Id + - active: + _eq: true + localPresets: + - key: "" + value: "" + set: {} + role: user + table: + name: vendors + schema: public + type: create_update_permission diff --git a/hasura/migrations/1581630611638_update_permission_user_public_table_vendors/up.yaml b/hasura/migrations/1581630611638_update_permission_user_public_table_vendors/up.yaml new file mode 100644 index 000000000..50a77d8ce --- /dev/null +++ b/hasura/migrations/1581630611638_update_permission_user_public_table_vendors/up.yaml @@ -0,0 +1,47 @@ +- args: + role: user + table: + name: vendors + schema: public + type: drop_update_permission +- args: + permission: + columns: + - favorite + - due_date + - discount + - prompt_discount + - city + - cost_center + - country + - display_name + - email + - name + - state + - street1 + - street2 + - taxid + - terms + - zip + - created_at + - updated_at + - bodyshopid + - id + filter: + bodyshop: + associations: + _and: + - user: + authid: + _eq: X-Hasura-User-Id + - active: + _eq: true + localPresets: + - key: "" + value: "" + set: {} + role: user + table: + name: vendors + schema: public + type: create_update_permission