Added job card functionality + new fields.

This commit is contained in:
Patrick Fic
2020-01-23 12:12:04 -08:00
parent f626966223
commit d1323bed7f
20 changed files with 390 additions and 86 deletions

View File

@@ -374,6 +374,27 @@
</translation> </translation>
</translations> </translations>
</concept_node> </concept_node>
<concept_node>
<name>convert</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>postInvoices</name> <name>postInvoices</name>
<definition_loaded>false</definition_loaded> <definition_loaded>false</definition_loaded>
@@ -720,6 +741,27 @@
</translation> </translation>
</translations> </translations>
</concept_node> </concept_node>
<concept_node>
<name>ownr_ea</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>phone1</name> <name>phone1</name>
<definition_loaded>false</definition_loaded> <definition_loaded>false</definition_loaded>
@@ -741,6 +783,27 @@
</translation> </translation>
</translations> </translations>
</concept_node> </concept_node>
<concept_node>
<name>phoneshort</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>ro_number</name> <name>ro_number</name>
<definition_loaded>false</definition_loaded> <definition_loaded>false</definition_loaded>
@@ -1066,27 +1129,6 @@
</concept_node> </concept_node>
</children> </children>
</folder_node> </folder_node>
<concept_node>
<name>convert</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>documents</name> <name>documents</name>
<definition_loaded>false</definition_loaded> <definition_loaded>false</definition_loaded>

View File

@@ -13,16 +13,23 @@ export default function JobDetailCardsCustomerComponent({ loading, data }) {
extraLink={data?.owner ? `/manage/owners/${data?.owner?.id}` : null}> extraLink={data?.owner ? `/manage/owners/${data?.owner?.id}` : null}>
{data ? ( {data ? (
<span> <span>
<div>{`${data?.ownr_fn ?? <div>{`${data?.ownr_fn ?? ""} ${data.ownr_ln ?? ""}`}</div>
""} ${data.ownr_ln ?? ""}`}</div>
<div> <div>
<PhoneFormatter>{`${data?.ownr_ph1 ?? ""}`}</PhoneFormatter> {t("jobs.fields.phoneshort")}:
<PhoneFormatter>{`${data?.ownr_ph1 ??
t("general.labels.na")}`}</PhoneFormatter>
</div>
<div>
{t("jobs.fields.ownr_ea")}:
{data?.ownr_ea ? (
<a href={`mailto:${data.ownr_ea}`}>
<span>{`${data?.ownr_ea ?? ""}`}</span>
</a>
) : (
t("general.labels.na")
)}
</div> </div>
{data?.ownr_ea ? (
<a href={`mailto:${data.ownr_ea}`}>
<div>{`${data?.ownr_ea ?? ""}`}</div>
</a>
) : null}
<div>{`${data?.owner?.preferred_contact ?? ""}`}</div> <div>{`${data?.owner?.preferred_contact ?? ""}`}</div>
</span> </span>

View File

@@ -1,16 +1,32 @@
import React from "react"; import React from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import CardTemplate from "./job-detail-cards.template.component"; import CardTemplate from "./job-detail-cards.template.component";
import { Carousel } from "antd";
import "./job-detail-cards.styles.scss";
export default function JobDetailCardsDocumentsComponent({ loading, data }) { export default function JobDetailCardsDocumentsComponent({ loading, data }) {
const { t } = useTranslation(); const { t } = useTranslation();
if (!data)
return (
<CardTemplate loading={loading} title={t("jobs.labels.cards.documents")}>
null
</CardTemplate>
);
return ( return (
<CardTemplate loading={loading} title={t("jobs.labels.cards.documents")}> <CardTemplate
{data ? ( loading={loading}
<span> title={t("jobs.labels.cards.documents")}
Documents stuff here. extraLink={`/manage/jobs/${data.id}#documents`}>
</span> {data.documents ? (
<Carousel autoplay>
{data.documents.map(item => (
<div key={item.id}>
<img src={item.thumb_url} />
</div>
))}
</Carousel>
) : null} ) : null}
</CardTemplate> </CardTemplate>
); );

View File

@@ -0,0 +1,11 @@
.ant-carousel .slick-slide {
text-align: center;
height: 160px;
line-height: 160px;
background: #364d79;
overflow: hidden;
}
.ant-carousel .slick-slide h3 {
color: #fff;
}

View File

@@ -124,7 +124,7 @@ function JobTombstone({ job, ...otherProps }) {
}); });
}); });
}}> }}>
{t("jobs.labels.convert")} {t("jobs.actions.convert")}
</Button>, </Button>,
<Button type='primary' key='submit' htmlType='submit'> <Button type='primary' key='submit' htmlType='submit'>
{t("general.labels.save")} {t("general.labels.save")}

View File

@@ -168,14 +168,6 @@ function JobsDocumentsComponent({ shopId, jobId, loading, data }) {
return ( return (
<div className='clearfix'> <div className='clearfix'>
<Button
onClick={() => {
console.log("btn click");
console.log("data", data);
}}>
Test Request
</Button>
<img src={url} alt='test' />
<Upload.Dragger <Upload.Dragger
customRequest={handleUpload} customRequest={handleUpload}
accept='.pdf,.jpg,.jpeg' accept='.pdf,.jpg,.jpeg'

View File

@@ -4,7 +4,7 @@ import { QUERY_SHOP_ID } from "../../graphql/bodyshop.queries";
import { GET_DOCUMENTS_BY_JOB } from "../../graphql/documents.queries"; import { GET_DOCUMENTS_BY_JOB } from "../../graphql/documents.queries";
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";
import JobDocuments from "./jobs-documents.page"; import JobDocuments from "./jobs-documents.component";
export default function JobsDocumentsContainer({ jobId }) { export default function JobsDocumentsContainer({ jobId }) {
const { loading, error, data } = useQuery(GET_DOCUMENTS_BY_JOB, { const { loading, error, data } = useQuery(GET_DOCUMENTS_BY_JOB, {

View File

@@ -5,10 +5,10 @@ import { auth } from "../firebase/firebase.utils";
const errorLink = onError( const errorLink = onError(
({ graphQLErrors, networkError, operation, forward }) => { ({ graphQLErrors, networkError, operation, forward }) => {
let access_token = window.localStorage.getItem("token"); let access_token = window.localStorage.getItem("token");
console.log("graphQLErrors", graphQLErrors); // console.log("graphQLErrors", graphQLErrors);
console.log("networkError", networkError); // console.log("networkError", networkError);
console.log("operation", operation); // console.log("operation", operation);
console.log("forward", forward); // console.log("forward", forward);
let expired = false; let expired = false;
@@ -29,40 +29,45 @@ const errorLink = onError(
if (access_token && access_token !== "undefined") { if (access_token && access_token !== "undefined") {
// Let's refresh token through async request // Let's refresh token through async request
return new Observable(observer => { return new Observable(observer => {
auth.currentUser const unsubscribeFromAuth = auth.onAuthStateChanged(async user => {
.getIdToken(true) console.log("Auth change in error handling.");
.then(function(idToken) { if (user) {
if (!idToken) { user
window.localStorage.removeItem("token"); .getIdToken(true)
return console.log("Refresh token has expired"); .then(function(idToken) {
} if (!idToken) {
console.log("Got a new token", idToken); window.localStorage.removeItem("token");
window.localStorage.setItem("token", idToken); return console.log("Refresh token has expired");
}
console.log("Got a new token", idToken);
window.localStorage.setItem("token", idToken);
// reset the headers // reset the headers
operation.setContext(({ headers = {} }) => ({ operation.setContext(({ headers = {} }) => ({
headers: { headers: {
// Re-add old headers // Re-add old headers
...headers, ...headers,
// Switch out old access token for new one // Switch out old access token for new one
authorization: idToken ? `Bearer ${idToken}` : "" authorization: idToken ? `Bearer ${idToken}` : ""
} }
})); }));
const subscriber = { const subscriber = {
next: observer.next.bind(observer), next: observer.next.bind(observer),
error: observer.error.bind(observer), error: observer.error.bind(observer),
complete: observer.complete.bind(observer) complete: observer.complete.bind(observer)
}; };
console.log("About to resend the request."); console.log("About to resend the request.");
// Retry last failed request // Retry last failed request
forward(operation).subscribe(subscriber); forward(operation).subscribe(subscriber);
}) })
.catch(error => { .catch(error => {
// No refresh or client token available, we force user to login // No refresh or client token available, we force user to login
console.log("Hit an error."); console.log("Hit an error.");
observer.error(error); observer.error(error);
}); });
}
});
}); });
} }
} }

View File

@@ -246,6 +246,10 @@ export const QUERY_JOB_CARD_DETAILS = gql`
updated_at updated_at
claim_total claim_total
ded_amt ded_amt
documents(limit: 3, order_by: { created_at: desc }) {
id
thumb_url
}
vehicle { vehicle {
id id
plate_no plate_no

View File

@@ -31,6 +31,7 @@
"actions": { "actions": {
"addDocuments": "Add Job Documents", "addDocuments": "Add Job Documents",
"addNote": "Add Note", "addNote": "Add Note",
"convert": "Convert",
"postInvoices": "Post Invoices", "postInvoices": "Post Invoices",
"printCenter": "Print Center" "printCenter": "Print Center"
}, },
@@ -51,7 +52,9 @@
"est_number": "Estimate Number", "est_number": "Estimate Number",
"owner": "Owner", "owner": "Owner",
"owner_owing": "Cust. Owes", "owner_owing": "Cust. Owes",
"ownr_ea": "Email",
"phone1": "Phone 1", "phone1": "Phone 1",
"phoneshort": "PH",
"ro_number": "RO #", "ro_number": "RO #",
"status": "Job Status", "status": "Job Status",
"vehicle": "Vehicle" "vehicle": "Vehicle"
@@ -62,7 +65,7 @@
"customer": "Customer Information", "customer": "Customer Information",
"damage": "Area of Damage", "damage": "Area of Damage",
"dates": "Dates", "dates": "Dates",
"documents": "Documents", "documents": "Recent Documents",
"estimator": "Estimator", "estimator": "Estimator",
"filehandler": "File Handler", "filehandler": "File Handler",
"insurance": "Insurance Details", "insurance": "Insurance Details",
@@ -71,7 +74,6 @@
"totals": "Totals", "totals": "Totals",
"vehicle": "Vehicle" "vehicle": "Vehicle"
}, },
"convert": "Convert",
"documents": "Documents", "documents": "Documents",
"lines": "Estimate Lines", "lines": "Estimate Lines",
"notes": "Notes", "notes": "Notes",

View File

@@ -31,6 +31,7 @@
"actions": { "actions": {
"addDocuments": "Agregar documentos de trabajo", "addDocuments": "Agregar documentos de trabajo",
"addNote": "Añadir la nota", "addNote": "Añadir la nota",
"convert": "Convertir",
"postInvoices": "Contabilizar facturas", "postInvoices": "Contabilizar facturas",
"printCenter": "Centro de impresión" "printCenter": "Centro de impresión"
}, },
@@ -51,7 +52,9 @@
"est_number": "Numero Estimado", "est_number": "Numero Estimado",
"owner": "Propietario", "owner": "Propietario",
"owner_owing": "Cust. Debe", "owner_owing": "Cust. Debe",
"ownr_ea": "Email",
"phone1": "Teléfono 1", "phone1": "Teléfono 1",
"phoneshort": "PH",
"ro_number": "RO #", "ro_number": "RO #",
"status": "Estado del trabajo", "status": "Estado del trabajo",
"vehicle": "Vehículo" "vehicle": "Vehículo"
@@ -62,7 +65,7 @@
"customer": "Información al cliente", "customer": "Información al cliente",
"damage": "Área de Daño", "damage": "Área de Daño",
"dates": "fechas", "dates": "fechas",
"documents": "documentos", "documents": "Documentos recientes",
"estimator": "Estimador", "estimator": "Estimador",
"filehandler": "File Handler", "filehandler": "File Handler",
"insurance": "detalles del seguro", "insurance": "detalles del seguro",
@@ -71,7 +74,6 @@
"totals": "Totales", "totals": "Totales",
"vehicle": "Vehículo" "vehicle": "Vehículo"
}, },
"convert": "Convertir",
"documents": "documentos", "documents": "documentos",
"lines": "Líneas estimadas", "lines": "Líneas estimadas",
"notes": "Notas", "notes": "Notas",

View File

@@ -31,6 +31,7 @@
"actions": { "actions": {
"addDocuments": "Ajouter des documents de travail", "addDocuments": "Ajouter des documents de travail",
"addNote": "Ajouter une note", "addNote": "Ajouter une note",
"convert": "Convertir",
"postInvoices": "Poster des factures", "postInvoices": "Poster des factures",
"printCenter": "Centre d'impression" "printCenter": "Centre d'impression"
}, },
@@ -51,7 +52,9 @@
"est_number": "Numéro d'estimation", "est_number": "Numéro d'estimation",
"owner": "Propriétaire", "owner": "Propriétaire",
"owner_owing": "Cust. Owes", "owner_owing": "Cust. Owes",
"ownr_ea": "Email",
"phone1": "Téléphone 1", "phone1": "Téléphone 1",
"phoneshort": "PH",
"ro_number": "RO #", "ro_number": "RO #",
"status": "Statut de l'emploi", "status": "Statut de l'emploi",
"vehicle": "Véhicule" "vehicle": "Véhicule"
@@ -62,7 +65,7 @@
"customer": "Informations client", "customer": "Informations client",
"damage": "Zone de dommages", "damage": "Zone de dommages",
"dates": "Rendez-vous", "dates": "Rendez-vous",
"documents": "Les documents", "documents": "Documents récents",
"estimator": "Estimateur", "estimator": "Estimateur",
"filehandler": "Gestionnaire de fichiers", "filehandler": "Gestionnaire de fichiers",
"insurance": "Détails de l'assurance", "insurance": "Détails de l'assurance",
@@ -71,7 +74,6 @@
"totals": "Totaux", "totals": "Totaux",
"vehicle": "Véhicule" "vehicle": "Véhicule"
}, },
"convert": "Convertir",
"documents": "Les documents", "documents": "Les documents",
"lines": "Estimer les lignes", "lines": "Estimer les lignes",
"notes": "Remarques", "notes": "Remarques",

View File

@@ -0,0 +1,3 @@
- args:
sql: ALTER TABLE "public"."documents" DROP COLUMN "key";
type: run_sql

View File

@@ -0,0 +1,3 @@
- args:
sql: ALTER TABLE "public"."documents" ADD COLUMN "key" text NOT NULL DEFAULT '0';
type: run_sql

View File

@@ -0,0 +1,36 @@
- args:
role: user
table:
name: documents
schema: public
type: drop_insert_permission
- args:
permission:
check:
job:
bodyshop:
associations:
_and:
- user:
authid:
_eq: X-Hasura-User-Id
- active:
_eq: true
columns:
- name
- thumb_url
- uploaded_by
- url
- created_at
- updated_at
- id
- jobid
localPresets:
- key: ""
value: ""
set: {}
role: user
table:
name: documents
schema: public
type: create_insert_permission

View File

@@ -0,0 +1,37 @@
- args:
role: user
table:
name: documents
schema: public
type: drop_insert_permission
- args:
permission:
check:
job:
bodyshop:
associations:
_and:
- user:
authid:
_eq: X-Hasura-User-Id
- active:
_eq: true
columns:
- created_at
- id
- jobid
- key
- name
- thumb_url
- updated_at
- uploaded_by
- url
localPresets:
- key: ""
value: ""
set: {}
role: user
table:
name: documents
schema: public
type: create_insert_permission

View File

@@ -0,0 +1,34 @@
- args:
role: user
table:
name: documents
schema: public
type: drop_select_permission
- args:
permission:
allow_aggregations: false
columns:
- name
- thumb_url
- uploaded_by
- url
- created_at
- updated_at
- id
- jobid
computed_fields: []
filter:
job:
bodyshop:
associations:
_and:
- user:
authid:
_eq: X-Hasura-User-Id
- active:
_eq: true
role: user
table:
name: documents
schema: public
type: create_select_permission

View File

@@ -0,0 +1,35 @@
- args:
role: user
table:
name: documents
schema: public
type: drop_select_permission
- args:
permission:
allow_aggregations: false
columns:
- created_at
- id
- jobid
- key
- name
- thumb_url
- updated_at
- uploaded_by
- url
computed_fields: []
filter:
job:
bodyshop:
associations:
_and:
- user:
authid:
_eq: X-Hasura-User-Id
- active:
_eq: true
role: user
table:
name: documents
schema: public
type: create_select_permission

View File

@@ -0,0 +1,36 @@
- args:
role: user
table:
name: documents
schema: public
type: drop_update_permission
- args:
permission:
columns:
- name
- thumb_url
- uploaded_by
- url
- created_at
- updated_at
- id
- jobid
filter:
job:
bodyshop:
associations:
_and:
- user:
authid:
_eq: X-Hasura-User-Id
- active:
_eq: true
localPresets:
- key: ""
value: ""
set: {}
role: user
table:
name: documents
schema: public
type: create_update_permission

View File

@@ -0,0 +1,37 @@
- args:
role: user
table:
name: documents
schema: public
type: drop_update_permission
- args:
permission:
columns:
- created_at
- id
- jobid
- key
- name
- thumb_url
- updated_at
- uploaded_by
- url
filter:
job:
bodyshop:
associations:
_and:
- user:
authid:
_eq: X-Hasura-User-Id
- active:
_eq: true
localPresets:
- key: ""
value: ""
set: {}
role: user
table:
name: documents
schema: public
type: create_update_permission