Compare commits

..

2 Commits

Author SHA1 Message Date
Patrick Fic
b5a2be9392 Package updates. 2022-04-18 10:27:06 -07:00
Patrick Fic
df1e15be60 All package upgrades. 2022-04-13 17:46:46 -07:00
141 changed files with 3643 additions and 13529 deletions

View File

@@ -1,21 +0,0 @@
{
"env": {
"es6": true,
"node": true
},
"extends": "eslint:recommended",
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly"
},
"parserOptions": {
"ecmaVersion": 2018,
"sourceType": "module"
},
"rules": {
"no-console": "off"
},
"settings": {},
"plugins": ["cypress"]
}

View File

@@ -1,4 +1,4 @@
<babeledit_project version="1.2" be_version="2.7.1"> <babeledit_project be_version="2.7.1" version="1.2">
<!-- <!--
BabelEdit project file BabelEdit project file
@@ -1243,69 +1243,6 @@
<folder_node> <folder_node>
<name>messages</name> <name>messages</name>
<children> <children>
<concept_node>
<name>admin_jobmarkexported</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>
<name>admin_jobmarkforreexport</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>
<name>admin_jobunvoid</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>billposted</name> <name>billposted</name>
<definition_loaded>false</definition_loaded> <definition_loaded>false</definition_loaded>
@@ -2674,27 +2611,6 @@
</translation> </translation>
</translations> </translations>
</concept_node> </concept_node>
<concept_node>
<name>calculatedcreditsnotreceived</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>creditsnotreceived</name> <name>creditsnotreceived</name>
<definition_loaded>false</definition_loaded> <definition_loaded>false</definition_loaded>
@@ -4535,48 +4451,6 @@
</translation> </translation>
</translations> </translations>
</concept_node> </concept_node>
<concept_node>
<name>localmediaserverhttp</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>
<name>localmediaservernetwork</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>logo_img_footer_margin</name> <name>logo_img_footer_margin</name>
<definition_loaded>false</definition_loaded> <definition_loaded>false</definition_loaded>
@@ -5862,27 +5736,6 @@
</translation> </translation>
</translations> </translations>
</concept_node> </concept_node>
<concept_node>
<name>list-ready</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>partsqueue</name> <name>partsqueue</name>
<definition_loaded>false</definition_loaded> <definition_loaded>false</definition_loaded>
@@ -7776,27 +7629,6 @@
</translation> </translation>
</translations> </translations>
</concept_node> </concept_node>
<concept_node>
<name>additional_board_statuses</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>color</name> <name>color</name>
<definition_loaded>false</definition_loaded> <definition_loaded>false</definition_loaded>
@@ -8196,27 +8028,6 @@
</translation> </translation>
</translations> </translations>
</concept_node> </concept_node>
<concept_node>
<name>ready_statuses</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>
</children> </children>
</folder_node> </folder_node>
<concept_node> <concept_node>
@@ -8303,27 +8114,6 @@
</translation> </translation>
</translations> </translations>
</concept_node> </concept_node>
<concept_node>
<name>uselocalmediaserver</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>website</name> <name>website</name>
<definition_loaded>false</definition_loaded> <definition_loaded>false</definition_loaded>
@@ -8990,48 +8780,6 @@
</translation> </translation>
</translations> </translations>
</concept_node> </concept_node>
<concept_node>
<name>md_to_emails</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>
<name>md_to_emails_emails</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>messagingpresets</name> <name>messagingpresets</name>
<definition_loaded>false</definition_loaded> <definition_loaded>false</definition_loaded>
@@ -13316,27 +13064,6 @@
</translation> </translation>
</translations> </translations>
</concept_node> </concept_node>
<concept_node>
<name>openinexplorer</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>reassign_limitexceeded</name> <name>reassign_limitexceeded</name>
<definition_loaded>false</definition_loaded> <definition_loaded>false</definition_loaded>
@@ -14122,27 +13849,6 @@
</translation> </translation>
</translations> </translations>
</concept_node> </concept_node>
<concept_node>
<name>external_id</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>first_name</name> <name>first_name</name>
<definition_loaded>false</definition_loaded> <definition_loaded>false</definition_loaded>
@@ -14640,27 +14346,6 @@
</translation> </translation>
</translations> </translations>
</concept_node> </concept_node>
<concept_node>
<name>priorsuccesfulexport</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>
</children> </children>
</folder_node> </folder_node>
</children> </children>
@@ -16177,27 +15862,6 @@
</translation> </translation>
</translations> </translations>
</concept_node> </concept_node>
<concept_node>
<name>refresh</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>required</name> <name>required</name>
<definition_loaded>false</definition_loaded> <definition_loaded>false</definition_loaded>
@@ -23483,27 +23147,6 @@
</concept_node> </concept_node>
</children> </children>
</folder_node> </folder_node>
<concept_node>
<name>partsstatus</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>pas</name> <name>pas</name>
<definition_loaded>false</definition_loaded> <definition_loaded>false</definition_loaded>
@@ -23656,27 +23299,6 @@
</concept_node> </concept_node>
</children> </children>
</folder_node> </folder_node>
<concept_node>
<name>queued_for_parts</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>rate_ats</name> <name>rate_ats</name>
<definition_loaded>false</definition_loaded> <definition_loaded>false</definition_loaded>
@@ -27285,27 +26907,6 @@
</translation> </translation>
</translations> </translations>
</concept_node> </concept_node>
<concept_node>
<name>calculatedcreditsnotreceived</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>creditmemos</name> <name>creditmemos</name>
<definition_loaded>false</definition_loaded> <definition_loaded>false</definition_loaded>
@@ -30039,27 +29640,6 @@
</translation> </translation>
</translations> </translations>
</concept_node> </concept_node>
<concept_node>
<name>readyjobs</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>recent</name> <name>recent</name>
<definition_loaded>false</definition_loaded> <definition_loaded>false</definition_loaded>
@@ -32563,27 +32143,6 @@
</translation> </translation>
</translations> </translations>
</concept_node> </concept_node>
<concept_node>
<name>orderinhouse</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>
</children> </children>
</folder_node> </folder_node>
</children> </children>
@@ -32746,48 +32305,6 @@
</translation> </translation>
</translations> </translations>
</concept_node> </concept_node>
<concept_node>
<name>saving</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>
<name>updating</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>
</children> </children>
</folder_node> </folder_node>
<folder_node> <folder_node>
@@ -32856,27 +32373,6 @@
</translation> </translation>
</translations> </translations>
</concept_node> </concept_node>
<concept_node>
<name>cm_received</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>comments</name> <name>comments</name>
<definition_loaded>false</definition_loaded> <definition_loaded>false</definition_loaded>
@@ -33302,27 +32798,6 @@
</translation> </translation>
</translations> </translations>
</concept_node> </concept_node>
<concept_node>
<name>mark_as_received</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>newpartsorder</name> <name>newpartsorder</name>
<definition_loaded>false</definition_loaded> <definition_loaded>false</definition_loaded>
@@ -33517,27 +32992,6 @@
</translation> </translation>
</translations> </translations>
</concept_node> </concept_node>
<concept_node>
<name>line_updated</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>received</name> <name>received</name>
<definition_loaded>false</definition_loaded> <definition_loaded>false</definition_loaded>
@@ -35413,27 +34867,6 @@
</translation> </translation>
</translations> </translations>
</concept_node> </concept_node>
<concept_node>
<name>filing_coversheet_landscape</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>filing_coversheet_portrait</name> <name>filing_coversheet_portrait</name>
<definition_loaded>false</definition_loaded> <definition_loaded>false</definition_loaded>
@@ -36821,32 +36254,6 @@
</concept_node> </concept_node>
</children> </children>
</folder_node> </folder_node>
<folder_node>
<name>special</name>
<children>
<concept_node>
<name>attendance_detail_csv</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>
</children>
</folder_node>
<folder_node> <folder_node>
<name>subjects</name> <name>subjects</name>
<children> <children>
@@ -37258,27 +36665,6 @@
<folder_node> <folder_node>
<name>labels</name> <name>labels</name>
<children> <children>
<concept_node>
<name>actual_in</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>alert</name> <name>alert</name>
<definition_loaded>false</definition_loaded> <definition_loaded>false</definition_loaded>
@@ -37730,27 +37116,6 @@
</translation> </translation>
</translations> </translations>
</concept_node> </concept_node>
<concept_node>
<name>partsstatus</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>production_note</name> <name>production_note</name>
<definition_loaded>false</definition_loaded> <definition_loaded>false</definition_loaded>
@@ -42446,27 +41811,6 @@
</translation> </translation>
</translations> </translations>
</concept_node> </concept_node>
<concept_node>
<name>jobs-ready</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>owner-detail</name> <name>owner-detail</name>
<definition_loaded>false</definition_loaded> <definition_loaded>false</definition_loaded>
@@ -43477,27 +42821,6 @@
</translation> </translation>
</translations> </translations>
</concept_node> </concept_node>
<concept_node>
<name>readyjobs</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>resetpassword</name> <name>resetpassword</name>
<definition_loaded>false</definition_loaded> <definition_loaded>false</definition_loaded>

View File

@@ -3,49 +3,53 @@
"version": "0.2.1", "version": "0.2.1",
"private": true, "private": true,
"proxy": "http://localhost:4000", "proxy": "http://localhost:4000",
"browser": {
"fs": false,
"path": false,
"os": false
},
"dependencies": { "dependencies": {
"@apollo/client": "^3.5.10", "@apollo/client": "^3.5.10",
"@asseinfo/react-kanban": "^2.2.0", "@asseinfo/react-kanban": "^2.2.0",
"@craco/craco": "^6.4.3", "@craco/craco": "^6.4.3",
"@fingerprintjs/fingerprintjs": "^3.3.3", "@fingerprintjs/fingerprintjs": "^3.3.3",
"@jsreport/browser-client": "^3.1.0",
"@sentry/react": "^6.19.6", "@sentry/react": "^6.19.6",
"@sentry/tracing": "^6.19.6", "@sentry/tracing": "^6.19.6",
"@splitsoftware/splitio-react": "^1.4.0", "@splitsoftware/splitio-react": "^1.4.0",
"@stripe/react-stripe-js": "^1.7.1", "@stripe/react-stripe-js": "^1.7.1",
"@stripe/stripe-js": "^1.27.0", "@stripe/stripe-js": "^1.27.0",
"@tanem/react-nprogress": "^4.0.12", "@tanem/react-nprogress": "^5.0.0",
"antd": "^4.19.5", "antd": "^4.19.5",
"apollo-link-logger": "^2.0.0", "apollo-link-logger": "^2.0.0",
"axios": "^0.26.1", "axios": "^0.26.1",
"craco-less": "^1.20.0", "craco-less": "^2.0.0",
"dinero.js": "^1.9.1", "dinero.js": "^1.9.1",
"dotenv": "^16.0.0", "dotenv": "^16.0.0",
"enquire-js": "^0.2.1", "enquire-js": "^0.2.1",
"env-cmd": "^10.1.0", "env-cmd": "^10.1.0",
"exifr": "^7.1.3", "exifr": "^7.1.3",
"firebase": "^9.6.11", "firebase": "^9.6.10",
"graphql": "^16.3.0", "graphql": "^16.3.0",
"i18next": "^21.6.16", "i18next": "^21.6.16",
"i18next-browser-languagedetector": "^6.1.4", "i18next-browser-languagedetector": "^6.1.4",
"jsoneditor": "^9.7.4", "jsoneditor": "^9.7.4",
"jsreport-browser-client-dist": "^1.3.0",
"libphonenumber-js": "^1.9.51", "libphonenumber-js": "^1.9.51",
"logrocket": "^2.2.1", "logrocket": "^2.2.1",
"markerjs2": "^2.21.1", "markerjs2": "^2.21.0",
"moment-business-days": "^1.2.0", "moment-business-days": "^1.2.0",
"moment-timezone": "^0.5.34", "moment-timezone": "^0.5.34",
"normalize-url": "^7.0.3",
"phone": "^3.1.15", "phone": "^3.1.15",
"preval.macro": "^5.0.0", "preval.macro": "^5.0.0",
"prop-types": "^15.8.1", "prop-types": "^15.8.1",
"query-string": "^7.1.1", "query-string": "^7.1.1",
"rc-queue-anim": "^2.0.0", "rc-queue-anim": "^2.0.0",
"rc-scroll-anim": "^2.7.6", "rc-scroll-anim": "^2.7.6",
"react": "^17.0.2", "react": "^18.0.0",
"react-big-calendar": "^0.38.2", "react-big-calendar": "^0.40.0",
"react-color": "^2.19.3", "react-color": "^2.19.3",
"react-cookie": "^4.1.1", "react-cookie": "^4.1.1",
"react-dom": "^17.0.2", "react-dom": "^18.0.0",
"react-drag-listview": "^0.1.9", "react-drag-listview": "^0.1.9",
"react-grid-gallery": "^0.5.5", "react-grid-gallery": "^0.5.5",
"react-grid-layout": "^1.3.4", "react-grid-layout": "^1.3.4",
@@ -70,18 +74,18 @@
"styled-components": "^5.3.5", "styled-components": "^5.3.5",
"subscriptions-transport-ws": "^0.11.0", "subscriptions-transport-ws": "^0.11.0",
"web-vitals": "^2.1.4", "web-vitals": "^2.1.4",
"workbox-background-sync": "^6.5.2", "workbox-background-sync": "^6.5.3",
"workbox-broadcast-update": "^6.5.2", "workbox-broadcast-update": "^6.5.3",
"workbox-cacheable-response": "^6.5.2", "workbox-cacheable-response": "^6.5.3",
"workbox-core": "^6.5.2", "workbox-core": "^6.5.3",
"workbox-expiration": "^6.5.2", "workbox-expiration": "^6.5.3",
"workbox-google-analytics": "^6.5.2", "workbox-google-analytics": "^6.5.3",
"workbox-navigation-preload": "^6.5.2", "workbox-navigation-preload": "^6.5.3",
"workbox-precaching": "^6.5.2", "workbox-precaching": "^6.5.3",
"workbox-range-requests": "^6.5.2", "workbox-range-requests": "^6.5.3",
"workbox-routing": "^6.5.2", "workbox-routing": "^6.5.3",
"workbox-strategies": "^6.5.2", "workbox-strategies": "^6.5.3",
"workbox-streams": "^6.5.2", "workbox-streams": "^6.5.3",
"yauzl": "^2.10.0" "yauzl": "^2.10.0"
}, },
"scripts": { "scripts": {
@@ -120,9 +124,9 @@
"devDependencies": { "devDependencies": {
"@sentry/webpack-plugin": "^1.18.8", "@sentry/webpack-plugin": "^1.18.8",
"@testing-library/cypress": "^8.0.2", "@testing-library/cypress": "^8.0.2",
"cypress": "^9.5.3", "cypress": "^9.5.4",
"eslint-plugin-cypress": "^2.12.1", "eslint-plugin-cypress": "^2.12.1",
"react-error-overlay": "6.0.10", "react-error-overlay": "6.0.11",
"redux-logger": "^3.0.6", "redux-logger": "^3.0.6",
"source-map-explorer": "^2.5.2" "source-map-explorer": "^2.5.2"
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 262 KiB

View File

@@ -13,7 +13,6 @@ import QboAuthorizeComponent from "../qbo-authorize/qbo-authorize.component";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { createStructuredSelector } from "reselect"; import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors"; import { selectBodyshop } from "../../redux/user/user.selectors";
import ExportLogsCountDisplay from "../export-logs-count-display/export-logs-count-display.component";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop, bodyshop: selectBodyshop,
@@ -28,7 +27,7 @@ export default connect(
mapDispatchToProps mapDispatchToProps
)(AccountingPayablesTableComponent); )(AccountingPayablesTableComponent);
export function AccountingPayablesTableComponent({ bodyshop, loading, bills, refetch }) { export function AccountingPayablesTableComponent({ bodyshop, loading, bills }) {
const { t } = useTranslation(); const { t } = useTranslation();
const [selectedBills, setSelectedBills] = useState([]); const [selectedBills, setSelectedBills] = useState([]);
const [transInProgress, setTransInProgress] = useState(false); const [transInProgress, setTransInProgress] = useState(false);
@@ -132,9 +131,11 @@ export function AccountingPayablesTableComponent({ bodyshop, loading, bills, ref
dataIndex: "attempts", dataIndex: "attempts",
key: "attempts", key: "attempts",
render: (text, record) => ( render: (text, record) => {
<ExportLogsCountDisplay logs={record.exportlogs} /> const success = record.exportlogs.filter((e) => e.successful).length;
), const attempts = record.exportlogs.length;
return `${success}/${attempts}`;
},
}, },
{ {
title: t("general.labels.actions"), title: t("general.labels.actions"),
@@ -149,7 +150,6 @@ export function AccountingPayablesTableComponent({ bodyshop, loading, bills, ref
disabled={transInProgress || !!record.exported} disabled={transInProgress || !!record.exported}
loadingCallback={setTransInProgress} loadingCallback={setTransInProgress}
setSelectedBills={setSelectedBills} setSelectedBills={setSelectedBills}
refetch={refetch}
/> />
</div> </div>
), ),
@@ -182,7 +182,6 @@ export function AccountingPayablesTableComponent({ bodyshop, loading, bills, ref
disabled={transInProgress || selectedBills.length === 0} disabled={transInProgress || selectedBills.length === 0}
loadingCallback={setTransInProgress} loadingCallback={setTransInProgress}
completedCallback={setSelectedBills} completedCallback={setSelectedBills}
refetch={refetch}
/> />
{bodyshop.accountingconfig && bodyshop.accountingconfig.qbo && ( {bodyshop.accountingconfig && bodyshop.accountingconfig.qbo && (
<QboAuthorizeComponent /> <QboAuthorizeComponent />

View File

@@ -13,7 +13,6 @@ import { connect } from "react-redux";
import { createStructuredSelector } from "reselect"; import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors"; import { selectBodyshop } from "../../redux/user/user.selectors";
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component"; import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
import ExportLogsCountDisplay from "../export-logs-count-display/export-logs-count-display.component";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop, bodyshop: selectBodyshop,
@@ -32,7 +31,6 @@ export function AccountingPayablesTableComponent({
bodyshop, bodyshop,
loading, loading,
payments, payments,
refetch,
}) { }) {
const { t } = useTranslation(); const { t } = useTranslation();
const [selectedPayments, setSelectedPayments] = useState([]); const [selectedPayments, setSelectedPayments] = useState([]);
@@ -132,9 +130,11 @@ export function AccountingPayablesTableComponent({
dataIndex: "attempts", dataIndex: "attempts",
key: "attempts", key: "attempts",
render: (text, record) => ( render: (text, record) => {
<ExportLogsCountDisplay logs={record.exportlogs} /> const success = record.exportlogs.filter((e) => e.successful).length;
), const attempts = record.exportlogs.length;
return `${success}/${attempts}`;
},
}, },
{ {
title: t("general.labels.actions"), title: t("general.labels.actions"),
@@ -148,7 +148,6 @@ export function AccountingPayablesTableComponent({
disabled={transInProgress || !!record.exportedat} disabled={transInProgress || !!record.exportedat}
loadingCallback={setTransInProgress} loadingCallback={setTransInProgress}
setSelectedPayments={setSelectedPayments} setSelectedPayments={setSelectedPayments}
refetch={refetch}
/> />
), ),
}, },
@@ -189,7 +188,6 @@ export function AccountingPayablesTableComponent({
disabled={transInProgress || selectedPayments.length === 0} disabled={transInProgress || selectedPayments.length === 0}
loadingCallback={setTransInProgress} loadingCallback={setTransInProgress}
completedCallback={setSelectedPayments} completedCallback={setSelectedPayments}
refetch={refetch}
/> />
{bodyshop.accountingconfig && bodyshop.accountingconfig.qbo && ( {bodyshop.accountingconfig && bodyshop.accountingconfig.qbo && (
<QboAuthorizeComponent /> <QboAuthorizeComponent />

View File

@@ -14,7 +14,6 @@ import { selectBodyshop } from "../../redux/user/user.selectors";
import QboAuthorizeComponent from "../qbo-authorize/qbo-authorize.component"; import QboAuthorizeComponent from "../qbo-authorize/qbo-authorize.component";
import { DateFormatter } from "../../utils/DateFormatter"; import { DateFormatter } from "../../utils/DateFormatter";
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component"; import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
import ExportLogsCountDisplay from "../export-logs-count-display/export-logs-count-display.component";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop, bodyshop: selectBodyshop,
@@ -31,7 +30,6 @@ export function AccountingReceivablesTableComponent({
bodyshop, bodyshop,
loading, loading,
jobs, jobs,
refetch,
}) { }) {
const { t } = useTranslation(); const { t } = useTranslation();
const [selectedJobs, setSelectedJobs] = useState([]); const [selectedJobs, setSelectedJobs] = useState([]);
@@ -141,9 +139,12 @@ export function AccountingReceivablesTableComponent({
title: t("exportlogs.labels.attempts"), title: t("exportlogs.labels.attempts"),
dataIndex: "attempts", dataIndex: "attempts",
key: "attempts", key: "attempts",
render: (text, record) => (
<ExportLogsCountDisplay logs={record.exportlogs} /> render: (text, record) => {
), const success = record.exportlogs.filter((e) => e.successful).length;
const attempts = record.exportlogs.length;
return `${success}/${attempts}`;
},
}, },
{ {
title: t("general.labels.actions"), title: t("general.labels.actions"),
@@ -156,7 +157,6 @@ export function AccountingReceivablesTableComponent({
jobId={record.id} jobId={record.id}
disabled={!!record.date_exported} disabled={!!record.date_exported}
setSelectedJobs={setSelectedJobs} setSelectedJobs={setSelectedJobs}
refetch={refetch}
/> />
<Link to={`/manage/jobs/${record.id}/close`}> <Link to={`/manage/jobs/${record.id}/close`}>
<Button>{t("jobs.labels.viewallocations")}</Button> <Button>{t("jobs.labels.viewallocations")}</Button>
@@ -207,7 +207,6 @@ export function AccountingReceivablesTableComponent({
disabled={transInProgress || selectedJobs.length === 0} disabled={transInProgress || selectedJobs.length === 0}
loadingCallback={setTransInProgress} loadingCallback={setTransInProgress}
completedCallback={setSelectedJobs} completedCallback={setSelectedJobs}
refetch={refetch}
/> />
)} )}
{bodyshop.accountingconfig && bodyshop.accountingconfig.qbo && ( {bodyshop.accountingconfig && bodyshop.accountingconfig.qbo && (

View File

@@ -1,136 +0,0 @@
import { Checkbox, Form, Skeleton, Typography } from "antd";
import React, { useEffect } from "react";
import { useTranslation } from "react-i18next";
import ReadOnlyFormItemComponent from "../form-items-formatted/read-only-form-item.component";
import "./bill-cm-returns-table.styles.scss";
export default function BillCmdReturnsTableComponent({
form,
loadOutstandingReturns,
returnLoading,
returnData,
}) {
const { t } = useTranslation();
useEffect(() => {
if (returnData) {
form.setFieldsValue({
outstanding_returns: returnData.parts_order_lines,
});
}
}, [returnData, form]);
return (
<Form.Item
shouldUpdate={(prev, cur) =>
prev.jobid !== cur.jobid ||
prev.is_credit_memo !== cur.is_credit_memo ||
prev.vendorid !== cur.vendorid
}
noStyle
>
{() => {
const isReturn = form.getFieldValue("is_credit_memo");
if (!isReturn) {
return null;
}
if (returnLoading) return <Skeleton />;
return (
<Form.List name="outstanding_returns">
{(fields, { add, remove, move }) => {
return (
<>
<Typography.Title level={4}>
{t("bills.labels.creditsnotreceived")}
</Typography.Title>
<table className="bill-cm-returns-table">
<thead>
<tr>
<th>{t("parts_orders.fields.line_desc")}</th>
<th>{t("parts_orders.fields.part_type")}</th>
<th>{t("parts_orders.fields.quantity")}</th>
<th>{t("parts_orders.fields.act_price")}</th>
<th>{t("parts_orders.fields.cost")}</th>
<th>{t("parts_orders.labels.mark_as_received")}</th>
</tr>
</thead>
<tbody>
{fields.map((field, index) => (
<tr key={field.key}>
<td>
<Form.Item
// label={t("joblines.fields.line_desc")}
key={`${index}line_desc`}
name={[field.name, "line_desc"]}
>
<ReadOnlyFormItemComponent />
</Form.Item>
</td>
<td>
<Form.Item
span={2}
//label={t("joblines.fields.mod_lb_hrs")}
key={`${index}part_type`}
name={[field.name, "part_type"]}
>
<ReadOnlyFormItemComponent />
</Form.Item>
</td>
<td>
<Form.Item
span={2}
//label={t("joblines.fields.mod_lb_hrs")}
key={`${index}quantity`}
name={[field.name, "quantity"]}
>
<ReadOnlyFormItemComponent />
</Form.Item>
</td>
<td>
<Form.Item
span={2}
//label={t("joblines.fields.mod_lb_hrs")}
key={`${index}act_price`}
name={[field.name, "act_price"]}
>
<ReadOnlyFormItemComponent type="currency" />
</Form.Item>
</td>
<td>
<Form.Item
span={2}
//label={t("joblines.fields.mod_lb_hrs")}
key={`${index}cost`}
name={[field.name, "cost"]}
>
<ReadOnlyFormItemComponent type="currency" />
</Form.Item>
</td>
<td>
<Form.Item
span={2}
//label={t("joblines.fields.mod_lb_hrs")}
key={`${index}cm_received`}
name={[field.name, "cm_received"]}
valuePropName="checked"
>
<Checkbox />
</Form.Item>
</td>
</tr>
))}
</tbody>
</table>
</>
);
}}
</Form.List>
);
}}
</Form.Item>
);
}

View File

@@ -1,19 +0,0 @@
.bill-cm-returns-table {
table-layout: fixed;
width: 100%;
th,
td {
padding: 8px;
text-align: left;
border-bottom: 1px solid #ddd;
.ant-form-item {
margin-bottom: 0px !important;
}
}
tr:hover {
background-color: #f5f5f5;
}
}

View File

@@ -12,29 +12,27 @@ import moment from "moment";
import queryString from "query-string"; import queryString from "query-string";
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { connect } from "react-redux"; import { useLocation, useHistory } from "react-router-dom";
import { useHistory, useLocation } from "react-router-dom";
import { createStructuredSelector } from "reselect";
import { import {
DELETE_BILL_LINE, DELETE_BILL_LINE,
INSERT_NEW_BILL_LINES, INSERT_NEW_BILL_LINES,
UPDATE_BILL_LINE, UPDATE_BILL_LINE,
} from "../../graphql/bill-lines.queries"; } from "../../graphql/bill-lines.queries";
import { QUERY_BILL_BY_PK, UPDATE_BILL } from "../../graphql/bills.queries"; import { QUERY_BILL_BY_PK, UPDATE_BILL } from "../../graphql/bills.queries";
import { insertAuditTrail } from "../../redux/application/application.actions";
import { setModalContext } from "../../redux/modals/modals.actions";
import { selectBodyshop } from "../../redux/user/user.selectors";
import AuditTrailMapping from "../../utils/AuditTrailMappings";
import AlertComponent from "../alert/alert.component"; import AlertComponent from "../alert/alert.component";
import BillFormContainer from "../bill-form/bill-form.container"; import BillFormContainer from "../bill-form/bill-form.container";
import BillMarkExportedButton from "../bill-mark-exported-button/bill-mark-exported-button.component";
import BillReeportButtonComponent from "../bill-reexport-button/bill-reexport-button.component";
import JobDocumentsGallery from "../jobs-documents-gallery/jobs-documents-gallery.container"; import JobDocumentsGallery from "../jobs-documents-gallery/jobs-documents-gallery.container";
import JobsDocumentsLocalGallery from "../jobs-documents-local-gallery/jobs-documents-local-gallery.container";
import LoadingSkeleton from "../loading-skeleton/loading-skeleton.component"; import LoadingSkeleton from "../loading-skeleton/loading-skeleton.component";
import BillReeportButtonComponent from "../bill-reexport-button/bill-reexport-button.component";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { setModalContext } from "../../redux/modals/modals.actions";
import { insertAuditTrail } from "../../redux/application/application.actions";
import AuditTrailMapping from "../../utils/AuditTrailMappings";
import BillMarkExportedButton from "../bill-mark-exported-button/bill-mark-exported-button.component";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop, //currentUser: selectCurrentUser
}); });
const mapDispatchToProps = (dispatch) => ({ const mapDispatchToProps = (dispatch) => ({
setPartsOrderContext: (context) => setPartsOrderContext: (context) =>
@@ -51,7 +49,6 @@ export default connect(
export function BillDetailEditcontainer({ export function BillDetailEditcontainer({
setPartsOrderContext, setPartsOrderContext,
insertAuditTrail, insertAuditTrail,
bodyshop,
}) { }) {
const search = queryString.parse(useLocation().search); const search = queryString.parse(useLocation().search);
const history = useHistory(); const history = useHistory();
@@ -268,21 +265,12 @@ export function BillDetailEditcontainer({
layout="vertical" layout="vertical"
> >
<BillFormContainer form={form} billEdit disabled={exported} /> <BillFormContainer form={form} billEdit disabled={exported} />
<JobDocumentsGallery
{bodyshop.uselocalmediaserver ? ( jobId={data ? data.bills_by_pk.jobid : null}
<JobsDocumentsLocalGallery billId={search.billid}
job={{ id: data ? data.bills_by_pk.jobid : null }} documentsList={data ? data.bills_by_pk.documents : []}
invoice_number={data ? data.bills_by_pk.invoice_number : null} billsCallback={refetch}
vendorid={data ? data.bills_by_pk.vendorid : null} />
/>
) : (
<JobDocumentsGallery
jobId={data ? data.bills_by_pk.jobid : null}
billId={search.billid}
documentsList={data ? data.bills_by_pk.documents : []}
billsCallback={refetch}
/>
)}
</Form> </Form>
</> </>
)} )}

View File

@@ -11,7 +11,6 @@ import {
QUERY_JOB_LBR_ADJUSTMENTS, QUERY_JOB_LBR_ADJUSTMENTS,
UPDATE_JOB, UPDATE_JOB,
} from "../../graphql/jobs.queries"; } from "../../graphql/jobs.queries";
import { MUTATION_MARK_RETURN_RECEIVED } from "../../graphql/parts-orders.queries";
import { insertAuditTrail } from "../../redux/application/application.actions"; import { insertAuditTrail } from "../../redux/application/application.actions";
import { toggleModalVisible } from "../../redux/modals/modals.actions"; import { toggleModalVisible } from "../../redux/modals/modals.actions";
import { selectBillEnterModal } from "../../redux/modals/modals.selectors"; import { selectBillEnterModal } from "../../redux/modals/modals.selectors";
@@ -24,7 +23,6 @@ import AuditTrailMapping from "../../utils/AuditTrailMappings";
import BillFormContainer from "../bill-form/bill-form.container"; import BillFormContainer from "../bill-form/bill-form.container";
import { CalculateBillTotal } from "../bill-form/bill-form.totals.utility"; import { CalculateBillTotal } from "../bill-form/bill-form.totals.utility";
import { handleUpload } from "../documents-upload/documents-upload.utility"; import { handleUpload } from "../documents-upload/documents-upload.utility";
import { handleUpload as handleLocalUpload } from "../documents-local-upload/documents-local-upload.utility";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
billEnterModal: selectBillEnterModal, billEnterModal: selectBillEnterModal,
@@ -49,7 +47,6 @@ function BillEnterModalContainer({
const [enterAgain, setEnterAgain] = useState(false); const [enterAgain, setEnterAgain] = useState(false);
const [insertBill] = useMutation(INSERT_NEW_BILL); const [insertBill] = useMutation(INSERT_NEW_BILL);
const [updateJobLines] = useMutation(UPDATE_JOB_LINE); const [updateJobLines] = useMutation(UPDATE_JOB_LINE);
const [updatePartsOrderLines] = useMutation(MUTATION_MARK_RETURN_RECEIVED);
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const client = useApolloClient(); const client = useApolloClient();
@@ -79,8 +76,7 @@ function BillEnterModalContainer({
} }
setLoading(true); setLoading(true);
const { upload, location, outstanding_returns, ...remainingValues } = const { upload, location, ...remainingValues } = values;
values;
let adjustmentsToInsert = {}; let adjustmentsToInsert = {};
@@ -160,25 +156,6 @@ function BillEnterModalContainer({
}); });
} }
const markPolReceived =
outstanding_returns &&
outstanding_returns.filter((o) => o.cm_received === true);
if (markPolReceived && markPolReceived.length > 0) {
const r2 = await updatePartsOrderLines({
variables: { partsLineIds: markPolReceived.map((p) => p.id) },
});
if (!!r2.errors) {
setLoading(false);
setEnterAgain(false);
notification["error"]({
message: t("parts_orders.errors.updating", {
message: JSON.stringify(r2.errors),
}),
});
}
}
if (!!r1.errors) { if (!!r1.errors) {
setLoading(false); setLoading(false);
setEnterAgain(false); setEnterAgain(false);
@@ -211,33 +188,19 @@ function BillEnterModalContainer({
///////////////////////// /////////////////////////
if (upload && upload.length > 0) { if (upload && upload.length > 0) {
//insert Each of the documents? //insert Each of the documents?
upload.forEach((u) => {
if (bodyshop.uselocalmediaserver) { handleUpload(
upload.forEach((u) => { { file: u.originFileObj },
handleLocalUpload({ {
ev: { file: u.originFileObj }, bodyshop: bodyshop,
context: { uploaded_by: currentUser.email,
jobid: values.jobid, jobId: values.jobid,
invoice_number: remainingValues.invoice_number, billId: billId,
vendorid: remainingValues.vendorid, tagsArray: null,
}, callback: null,
}); }
}); );
} else { });
upload.forEach((u) => {
handleUpload(
{ file: u.originFileObj },
{
bodyshop: bodyshop,
uploaded_by: currentUser.email,
jobId: values.jobid,
billId: billId,
tagsArray: null,
callback: null,
}
);
});
}
} }
/////////////////////////// ///////////////////////////
setLoading(false); setLoading(false);

View File

@@ -47,7 +47,6 @@ export function BillFormComponent({
billEdit, billEdit,
disableInvNumber, disableInvNumber,
job, job,
loadOutstandingReturns,
}) { }) {
const { t } = useTranslation(); const { t } = useTranslation();
const client = useApolloClient(); const client = useApolloClient();
@@ -59,14 +58,6 @@ export function BillFormComponent({
); );
const handleVendorSelect = (props, opt) => { const handleVendorSelect = (props, opt) => {
setDiscount(opt.discount); setDiscount(opt.discount);
opt &&
loadOutstandingReturns({
variables: {
jobId: form.getFieldValue("jobid"),
vendorId: opt.value,
},
});
}; };
useEffect(() => { useEffect(() => {
@@ -74,8 +65,8 @@ export function BillFormComponent({
}, [job, form]); }, [job, form]);
useEffect(() => { useEffect(() => {
const vendorId = form.getFieldValue("vendorid"); if (form.getFieldValue("vendorid") && vendorAutoCompleteOptions) {
if (vendorId && vendorAutoCompleteOptions) { const vendorId = form.getFieldValue("vendorid");
const matchingVendors = vendorAutoCompleteOptions.filter( const matchingVendors = vendorAutoCompleteOptions.filter(
(v) => v.id === vendorId (v) => v.id === vendorId
); );
@@ -83,25 +74,10 @@ export function BillFormComponent({
setDiscount(matchingVendors[0].discount); setDiscount(matchingVendors[0].discount);
} }
} }
const jobId = form.getFieldValue("jobid"); if (form.getFieldValue("jobid")) {
if (jobId) { loadLines({ variables: { id: form.getFieldValue("jobid") } });
loadLines({ variables: { id: jobId } });
if (form.getFieldValue("is_credit_memo") && vendorId) {
loadOutstandingReturns({
variables: {
jobId: jobId,
vendorId: vendorId,
},
});
}
} }
}, [ }, [form, setDiscount, vendorAutoCompleteOptions, loadLines]);
form,
loadOutstandingReturns,
setDiscount,
vendorAutoCompleteOptions,
loadLines,
]);
return ( return (
<div> <div>
@@ -131,13 +107,6 @@ export function BillFormComponent({
onBlur={() => { onBlur={() => {
if (form.getFieldValue("jobid") !== null) { if (form.getFieldValue("jobid") !== null) {
loadLines({ variables: { id: form.getFieldValue("jobid") } }); loadLines({ variables: { id: form.getFieldValue("jobid") } });
if (form.getFieldValue("vendorid") !== null)
loadOutstandingReturns({
variables: {
jobId: form.getFieldValue("jobid"),
vendorId: form.getFieldValue("vendorid"),
},
});
} }
}} }}
/> />
@@ -259,22 +228,8 @@ export function BillFormComponent({
rules={[ rules={[
({ getFieldValue }) => ({ ({ getFieldValue }) => ({
validator(rule, value) { validator(rule, value) {
if (
value === true &&
getFieldValue("jobid") &&
getFieldValue("vendorid")
) {
loadOutstandingReturns({
variables: {
jobId: form.getFieldValue("jobid"),
vendorId: form.getFieldValue("vendorid"),
},
});
}
if ( if (
!bodyshop.bill_allow_post_to_closed && !bodyshop.bill_allow_post_to_closed &&
job &&
(job.status === bodyshop.md_ro_statuses.default_invoiced || (job.status === bodyshop.md_ro_statuses.default_invoiced ||
job.status === bodyshop.md_ro_statuses.default_exported || job.status === bodyshop.md_ro_statuses.default_exported ||
job.status === bodyshop.md_ro_statuses.default_void) && job.status === bodyshop.md_ro_statuses.default_void) &&

View File

@@ -6,8 +6,6 @@ import { GET_JOB_LINES_TO_ENTER_BILL } from "../../graphql/jobs-lines.queries";
import { SEARCH_VENDOR_AUTOCOMPLETE } from "../../graphql/vendors.queries"; import { SEARCH_VENDOR_AUTOCOMPLETE } from "../../graphql/vendors.queries";
import { selectBodyshop } from "../../redux/user/user.selectors"; import { selectBodyshop } from "../../redux/user/user.selectors";
import BillFormComponent from "./bill-form.component"; import BillFormComponent from "./bill-form.component";
import BillCmdReturnsTableComponent from "../bill-cm-returns-table/bill-cm-returns-table.component";
import { QUERY_UNRECEIVED_LINES } from "../../graphql/parts-orders.queries";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop, bodyshop: selectBodyshop,
@@ -29,34 +27,20 @@ export function BillFormContainer({
GET_JOB_LINES_TO_ENTER_BILL GET_JOB_LINES_TO_ENTER_BILL
); );
const [loadOutstandingReturns, { loading: returnLoading, data: returnData }] =
useLazyQuery(QUERY_UNRECEIVED_LINES);
return ( return (
<> <BillFormComponent
<BillFormComponent disabled={disabled}
disabled={disabled} form={form}
form={form} billEdit={billEdit}
billEdit={billEdit} vendorAutoCompleteOptions={
vendorAutoCompleteOptions={ VendorAutoCompleteData && VendorAutoCompleteData.vendors
VendorAutoCompleteData && VendorAutoCompleteData.vendors }
} loadLines={loadLines}
loadLines={loadLines} lineData={lineData ? lineData.joblines : []}
lineData={lineData ? lineData.joblines : []} job={lineData ? lineData.jobs_by_pk : null}
job={lineData ? lineData.jobs_by_pk : null} responsibilityCenters={bodyshop.md_responsibility_centers || null}
responsibilityCenters={bodyshop.md_responsibility_centers || null} disableInvNumber={disableInvNumber}
disableInvNumber={disableInvNumber} />
loadOutstandingReturns={loadOutstandingReturns}
/>
{!billEdit && (
<BillCmdReturnsTableComponent
form={form}
loadOutstandingReturns={loadOutstandingReturns}
returnLoading={returnLoading}
returnData={returnData}
/>
)}
</>
); );
} }
export default connect(mapStateToProps, null)(BillFormContainer); export default connect(mapStateToProps, null)(BillFormContainer);

View File

@@ -43,8 +43,6 @@ export function BillsListTableComponent({
}); });
// const search = queryString.parse(useLocation().search); // const search = queryString.parse(useLocation().search);
// const selectedBill = search.billid; // const selectedBill = search.billid;
const [searchText, setSearchText] = useState("");
const Templates = TemplateList("bill"); const Templates = TemplateList("bill");
const bills = billsQuery.data ? billsQuery.data.bills : []; const bills = billsQuery.data ? billsQuery.data.bills : [];
const { refetch } = billsQuery; const { refetch } = billsQuery;
@@ -61,6 +59,7 @@ export function BillsListTableComponent({
record.is_credit_memo || record.vendorid === bodyshop.inhousevendorid record.is_credit_memo || record.vendorid === bodyshop.inhousevendorid
} }
onClick={() => { onClick={() => {
console.log(record);
setPartsOrderContext({ setPartsOrderContext({
actions: {}, actions: {},
context: { context: {
@@ -168,24 +167,6 @@ export function BillsListTableComponent({
setState({ ...state, filteredInfo: filters, sortedInfo: sorter }); setState({ ...state, filteredInfo: filters, sortedInfo: sorter });
}; };
const filteredBills = bills
? searchText === ""
? bills
: bills.filter(
(b) =>
(b.invoice_number || "")
.toLowerCase()
.includes(searchText.toLowerCase()) ||
(b.vendor.name || "")
.toLowerCase()
.includes(searchText.toLowerCase()) ||
(b.total || "")
.toString()
.toLowerCase()
.includes(searchText.toLowerCase())
)
: [];
return ( return (
<Card <Card
title={t("bills.labels.bills")} title={t("bills.labels.bills")}
@@ -226,10 +207,8 @@ export function BillsListTableComponent({
<Input.Search <Input.Search
placeholder={t("general.labels.search")} placeholder={t("general.labels.search")}
value={searchText}
onChange={(e) => { onChange={(e) => {
e.preventDefault(); e.preventDefault();
setSearchText(e.target.value);
}} }}
/> />
</Space> </Space>
@@ -242,7 +221,7 @@ export function BillsListTableComponent({
}} }}
columns={columns} columns={columns}
rowKey="id" rowKey="id"
dataSource={filteredBills} dataSource={bills}
onChange={handleTableChange} onChange={handleTableChange}
/> />
</Card> </Card>

View File

@@ -6,13 +6,12 @@ import { useTranslation } from "react-i18next";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { createStructuredSelector } from "reselect"; import { createStructuredSelector } from "reselect";
import { GET_DOCUMENTS_BY_JOB } from "../../graphql/documents.queries"; import { GET_DOCUMENTS_BY_JOB } from "../../graphql/documents.queries";
import { selectBodyshop } from "../../redux/user/user.selectors";
import AlertComponent from "../alert/alert.component"; import AlertComponent from "../alert/alert.component";
import JobDocumentsGalleryExternal from "../jobs-documents-gallery/jobs-documents-gallery.external.component"; import JobDocumentsGalleryExternal from "../jobs-documents-gallery/jobs-documents-gallery.external.component";
import LoadingSpinner from "../loading-spinner/loading-spinner.component"; import LoadingSpinner from "../loading-spinner/loading-spinner.component";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop, //currentUser: selectCurrentUser
}); });
const mapDispatchToProps = (dispatch) => ({ const mapDispatchToProps = (dispatch) => ({
//setUserLanguage: language => dispatch(setUserLanguage(language)) //setUserLanguage: language => dispatch(setUserLanguage(language))
@@ -20,7 +19,6 @@ const mapDispatchToProps = (dispatch) => ({
export default connect(mapStateToProps, mapDispatchToProps)(ChatMediaSelector); export default connect(mapStateToProps, mapDispatchToProps)(ChatMediaSelector);
export function ChatMediaSelector({ export function ChatMediaSelector({
bodyshop,
selectedMedia, selectedMedia,
setSelectedMedia, setSelectedMedia,
conversation, conversation,
@@ -29,6 +27,7 @@ export function ChatMediaSelector({
const [visible, setVisible] = useState(false); const [visible, setVisible] = useState(false);
const { loading, error, data } = useQuery(GET_DOCUMENTS_BY_JOB, { const { loading, error, data } = useQuery(GET_DOCUMENTS_BY_JOB, {
fetchPolicy: "network-only", fetchPolicy: "network-only",
nextFetchPolicy: "network-only", nextFetchPolicy: "network-only",
variables: { variables: {
@@ -67,8 +66,6 @@ export function ChatMediaSelector({
</div> </div>
); );
if (bodyshop.uselocalmediaserver) return null;
return ( return (
<Popover <Popover
content={ content={

View File

@@ -19,7 +19,7 @@ export function ChatPresetsComponent({ bodyshop, setMessage, className }) {
const menu = ( const menu = (
<Menu> <Menu>
{bodyshop.md_messaging_presets.map((i, idx) => ( {bodyshop.md_messaging_presets.map((i, idx) => (
<Menu.Item onClick={() => setMessage(i.text)} key={idx}> <Menu.Item onClick={() => setMessage(i.text)} onItemHover key={idx}>
{i.label} {i.label}
</Menu.Item> </Menu.Item>
))} ))}

View File

@@ -1,70 +0,0 @@
import { UploadOutlined } from "@ant-design/icons";
import { Upload } from "antd";
import React, { useState } from "react";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import {
selectBodyshop,
selectCurrentUser,
} from "../../redux/user/user.selectors";
import { handleUpload } from "./documents-local-upload.utility";
const mapStateToProps = createStructuredSelector({
currentUser: selectCurrentUser,
bodyshop: selectBodyshop,
});
export function DocumentsLocalUploadComponent({
children,
currentUser,
bodyshop,
job,
vendorid,
invoice_number,
callbackAfterUpload,
}) {
const [fileList, setFileList] = useState([]);
const handleDone = (uid) => {
setTimeout(() => {
setFileList((fileList) => fileList.filter((x) => x.uid !== uid));
}, 2000);
};
return (
<Upload.Dragger
multiple={true}
fileList={fileList}
onChange={(f) => {
if (f.event && f.event.percent === 100) handleDone(f.file.uid);
setFileList(f.fileList);
}}
customRequest={(ev) =>
handleUpload({
ev,
context: {
jobid: job.id,
vendorid,
invoice_number,
callback: callbackAfterUpload,
},
})
}
accept="audio/*, video/*, image/*, .pdf, .doc, .docx, .xls, .xlsx"
>
{children || (
<>
<p className="ant-upload-drag-icon">
<UploadOutlined />
</p>
<p className="ant-upload-text">
Click or drag files to this area to upload.
</p>
</>
)}
</Upload.Dragger>
);
}
export default connect(mapStateToProps, null)(DocumentsLocalUploadComponent);

View File

@@ -1,65 +0,0 @@
import cleanAxios from "../../utils/CleanAxios";
import { store } from "../../redux/store";
import { addMediaForJob } from "../../redux/media/media.actions";
import normalizeUrl from "normalize-url";
export const handleUpload = async ({ ev, context }) => {
const { onError, onSuccess, onProgress, file } = ev;
const { jobid, invoice_number, vendorid, callbackAfterUpload } = context;
var options = {
headers: { "X-Requested-With": "XMLHttpRequest" },
onUploadProgress: (e) => {
if (!!onProgress) onProgress({ percent: (e.loaded / e.total) * 100 });
},
};
const formData = new FormData();
formData.append("jobid", jobid);
if (invoice_number) {
formData.append("invoice_number", invoice_number);
formData.append("vendorid", vendorid);
}
formData.append("file", file);
const bodyshop = store.getState().user.bodyshop;
const imexMediaServerResponse = await cleanAxios.post(
normalizeUrl(
`${bodyshop.localmediaserverhttp}/${
invoice_number ? "bills" : "jobs"
}/upload`
),
formData,
{
...options,
}
);
if (imexMediaServerResponse.status !== 200) {
if (!!onError) {
onError(imexMediaServerResponse.statusText);
}
} else {
onSuccess && onSuccess(file);
store.dispatch(
addMediaForJob({
jobid,
media: imexMediaServerResponse.data.map((d) => {
return {
...d,
selected: false,
src: normalizeUrl(`${bodyshop.localmediaserverhttp}/${d.src}`),
thumbnail: normalizeUrl(
`${bodyshop.localmediaserverhttp}/${d.thumbnail}`
),
};
}),
})
);
}
if (callbackAfterUpload) {
callbackAfterUpload();
}
};

View File

@@ -9,7 +9,6 @@ import {
Space, Space,
Menu, Menu,
Dropdown, Dropdown,
Button,
} from "antd"; } from "antd";
import React from "react"; import React from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@@ -21,13 +20,10 @@ import {
selectBodyshop, selectBodyshop,
selectCurrentUser, selectCurrentUser,
} from "../../redux/user/user.selectors"; } from "../../redux/user/user.selectors";
import { CreateExplorerLinkForJob } from "../../utils/localmedia";
import { selectEmailConfig } from "../../redux/email/email.selectors";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop, bodyshop: selectBodyshop,
currentUser: selectCurrentUser, currentUser: selectCurrentUser,
emailConfig: selectEmailConfig,
}); });
const mapDispatchToProps = (dispatch) => ({ const mapDispatchToProps = (dispatch) => ({
//setUserLanguage: language => dispatch(setUserLanguage(language)) //setUserLanguage: language => dispatch(setUserLanguage(language))
@@ -38,7 +34,6 @@ export default connect(
)(EmailOverlayComponent); )(EmailOverlayComponent);
export function EmailOverlayComponent({ export function EmailOverlayComponent({
emailConfig,
form, form,
selectedMediaState, selectedMediaState,
bodyshop, bodyshop,
@@ -47,12 +42,7 @@ export function EmailOverlayComponent({
const { t } = useTranslation(); const { t } = useTranslation();
const handleClick = ({ item, key, keyPath }) => { const handleClick = ({ item, key, keyPath }) => {
const email = item.props.value; const email = item.props.value;
form.setFieldsValue({ form.setFieldsValue({ to: _.uniq([...form.getFieldValue("to"), email]) });
to: _.uniq([
...form.getFieldValue("to"),
...(typeof email === "string" ? [email] : email),
]),
});
}; };
const menu = ( const menu = (
@@ -65,11 +55,6 @@ export function EmailOverlayComponent({
{`${e.first_name} ${e.last_name}`} {`${e.first_name} ${e.last_name}`}
</Menu.Item> </Menu.Item>
))} ))}
{bodyshop.md_to_emails.map((e, idx) => (
<Menu.Item value={e.emails} key={idx + "group"}>
{e.label}
</Menu.Item>
))}
</Menu> </Menu>
</div> </div>
); );
@@ -158,17 +143,10 @@ export function EmailOverlayComponent({
</Form.Item> </Form.Item>
<Tabs> <Tabs>
{!bodyshop.uselocalmediaserver && ( <Tabs.TabPane tab={t("emails.labels.documents")} key="documents">
<Tabs.TabPane tab={t("emails.labels.documents")} key="documents"> <EmailDocumentsComponent selectedMediaState={selectedMediaState} />
<EmailDocumentsComponent selectedMediaState={selectedMediaState} /> </Tabs.TabPane>
</Tabs.TabPane>
)}
<Tabs.TabPane tab={t("emails.labels.attachments")} key="attachments"> <Tabs.TabPane tab={t("emails.labels.attachments")} key="attachments">
{bodyshop.uselocalmediaserver && emailConfig.jobid && (
<a href={CreateExplorerLinkForJob({ jobid: emailConfig.jobid })}>
<Button>{t("documents.labels.openinexplorer")}</Button>
</a>
)}
<Form.Item <Form.Item
name="fileList" name="fileList"
valuePropName="fileList" valuePropName="fileList"

View File

@@ -1,25 +0,0 @@
import React from "react";
import { WarningOutlined } from "@ant-design/icons";
import { Space, Tooltip } from "antd";
import { useTranslation } from "react-i18next";
const style = {
fontWeight: "bold",
color: "green",
};
export default function ExportLogsCountDisplay({ logs }) {
const success = logs.filter((e) => e.successful).length;
const attempts = logs.length;
const { t } = useTranslation();
return (
<Space style={success > 0 ? style : {}}>
{`${success}/${attempts}`}
{success > 0 && (
<Tooltip title={t("exportlogs.labels.priorsuccesfulexport")}>
<WarningOutlined />
</Tooltip>
)}
</Space>
);
}

View File

@@ -3,7 +3,6 @@ import Icon, {
BarChartOutlined, BarChartOutlined,
CarFilled, CarFilled,
ClockCircleFilled, ClockCircleFilled,
CheckCircleOutlined,
DashboardFilled, DashboardFilled,
DollarCircleFilled, DollarCircleFilled,
ExportOutlined, ExportOutlined,
@@ -109,9 +108,6 @@ function Header({
<Menu.Item key="activejobs" icon={<FileFilled />}> <Menu.Item key="activejobs" icon={<FileFilled />}>
<Link to="/manage/jobs">{t("menus.header.activejobs")}</Link> <Link to="/manage/jobs">{t("menus.header.activejobs")}</Link>
</Menu.Item> </Menu.Item>
<Menu.Item key="readyjobs" icon={<CheckCircleOutlined />}>
<Link to="/manage/jobs/ready">{t("menus.header.readyjobs")}</Link>
</Menu.Item>
<Menu.Item key="parts-queue" icon={<ToolFilled />}> <Menu.Item key="parts-queue" icon={<ToolFilled />}>
<Link to="/manage/partsqueue">{t("menus.header.parts-queue")}</Link> <Link to="/manage/partsqueue">{t("menus.header.parts-queue")}</Link>
</Menu.Item> </Menu.Item>

View File

@@ -49,11 +49,11 @@ export function Jobd3RdPartyModal({ bodyshop, jobId }) {
GenerateDocument( GenerateDocument(
{ {
name: TemplateList("job_special").special_thirdpartypayer.key, name: TemplateList("job_special").thirdpartypayer.key,
variables: { id: jobId }, variables: { id: jobId },
context: restVals, context: restVals,
}, },
{ subject: TemplateList("job_special").special_thirdpartypayer.subject }, { subject: TemplateList("job_special").thirdpartypayer.subject },
sendtype sendtype
); );
}; };

View File

@@ -26,8 +26,6 @@ export default function JobBillsTotalComponent({
let billCms = Dinero(); let billCms = Dinero();
let lbrAdjustments = Dinero(); let lbrAdjustments = Dinero();
let totalReturns = Dinero(); let totalReturns = Dinero();
let totalReturnsMarkedNotReceived = Dinero();
let totalReturnsMarkedReceived = Dinero();
partsOrders.forEach((p) => partsOrders.forEach((p) =>
p.parts_order_lines.forEach((pol) => { p.parts_order_lines.forEach((pol) => {
@@ -37,24 +35,6 @@ export default function JobBillsTotalComponent({
amount: Math.round((pol.act_price || 0) * 100), amount: Math.round((pol.act_price || 0) * 100),
}).multiply(pol.quantity) }).multiply(pol.quantity)
); );
if (pol.cm_received === null) {
return; // Skip this calculation for bills posted prior to the CNR change.
} else {
if (pol.cm_received === false) {
totalReturnsMarkedNotReceived = totalReturnsMarkedNotReceived.add(
Dinero({
amount: Math.round((pol.act_price || 0) * 100),
}).multiply(pol.quantity)
);
} else {
totalReturnsMarkedReceived = totalReturnsMarkedReceived.add(
Dinero({
amount: Math.round((pol.act_price || 0) * 100),
}).multiply(pol.quantity)
);
}
}
} }
}) })
); );
@@ -93,7 +73,7 @@ export default function JobBillsTotalComponent({
const discrepWithLbrAdj = discrepancy.add(lbrAdjustments); const discrepWithLbrAdj = discrepancy.add(lbrAdjustments);
const discrepWithCms = discrepWithLbrAdj.add(totalReturns); const discrepWithCms = discrepWithLbrAdj.add(totalReturns);
const calculatedCreditsNotReceived = totalReturns.subtract(billCms); //billCms is tracked as a negative number. const creditsNotReceived = totalReturns.subtract(billCms); //billCms is tracked as a negative number.
return ( return (
<Row gutter={16}> <Row gutter={16}>
@@ -233,32 +213,6 @@ export default function JobBillsTotalComponent({
value={totalReturns.toFormat()} value={totalReturns.toFormat()}
/> />
</Tooltip> </Tooltip>
<Tooltip
title={
<div
dangerouslySetInnerHTML={{
__html: t(
"jobs.labels.plitooltips.calculatedcreditsnotreceived"
),
}}
/>
}
>
<Statistic
title={t("bills.labels.calculatedcreditsnotreceived")}
valueStyle={{
color:
calculatedCreditsNotReceived.getAmount() <= 0
? "green"
: "red",
}}
value={
calculatedCreditsNotReceived.getAmount() >= 0
? calculatedCreditsNotReceived.toFormat()
: Dinero().toFormat()
}
/>
</Tooltip>
<Tooltip <Tooltip
title={ title={
<div <div
@@ -271,14 +225,11 @@ export default function JobBillsTotalComponent({
<Statistic <Statistic
title={t("bills.labels.creditsnotreceived")} title={t("bills.labels.creditsnotreceived")}
valueStyle={{ valueStyle={{
color: color: creditsNotReceived.getAmount() <= 0 ? "green" : "red",
totalReturnsMarkedNotReceived.getAmount() <= 0
? "green"
: "red",
}} }}
value={ value={
totalReturnsMarkedNotReceived.getAmount() >= 0 creditsNotReceived.getAmount() >= 0
? totalReturnsMarkedNotReceived.toFormat() ? creditsNotReceived.toFormat()
: Dinero().toFormat() : Dinero().toFormat()
} }
/> />

View File

@@ -6,10 +6,8 @@ import React from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { Link, useHistory, useLocation } from "react-router-dom"; import { Link, useHistory, useLocation } from "react-router-dom";
import { createStructuredSelector } from "reselect";
import { QUERY_JOB_CARD_DETAILS } from "../../graphql/jobs.queries"; import { QUERY_JOB_CARD_DETAILS } from "../../graphql/jobs.queries";
import { setModalContext } from "../../redux/modals/modals.actions"; import { setModalContext } from "../../redux/modals/modals.actions";
import { selectBodyshop } from "../../redux/user/user.selectors";
import AlertComponent from "../alert/alert.component"; import AlertComponent from "../alert/alert.component";
import JobSyncButton from "../job-sync-button/job-sync-button.component"; import JobSyncButton from "../job-sync-button/job-sync-button.component";
import JobsDetailHeader from "../jobs-detail-header/jobs-detail-header.component"; import JobsDetailHeader from "../jobs-detail-header/jobs-detail-header.component";
@@ -22,10 +20,6 @@ import JobDetailCardsNotesComponent from "./job-detail-cards.notes.component";
import JobDetailCardsPartsComponent from "./job-detail-cards.parts.component"; import JobDetailCardsPartsComponent from "./job-detail-cards.parts.component";
import JobDetailCardsTotalsComponent from "./job-detail-cards.totals.component"; import JobDetailCardsTotalsComponent from "./job-detail-cards.totals.component";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
});
const mapDispatchToProps = (dispatch) => ({ const mapDispatchToProps = (dispatch) => ({
setPrintCenterContext: (context) => setPrintCenterContext: (context) =>
dispatch(setModalContext({ context: context, modal: "printCenter" })), dispatch(setModalContext({ context: context, modal: "printCenter" })),
@@ -37,7 +31,7 @@ const span = {
lg: { span: 8 }, lg: { span: 8 },
}; };
export function JobDetailCards({ bodyshop, setPrintCenterContext }) { export function JobDetailCards({ setPrintCenterContext }) {
const selectedBreakpoint = Object.entries(Grid.useBreakpoint()) const selectedBreakpoint = Object.entries(Grid.useBreakpoint())
.filter((screen) => !!screen[1]) .filter((screen) => !!screen[1])
.slice(-1)[0]; .slice(-1)[0];
@@ -149,14 +143,12 @@ export function JobDetailCards({ bodyshop, setPrintCenterContext }) {
data={data ? data.jobs_by_pk : null} data={data ? data.jobs_by_pk : null}
/> />
</Col> </Col>
{!bodyshop.uselocalmediaserver && ( <Col {...span}>
<Col {...span}> <JobDetailCardsDocumentsComponent
<JobDetailCardsDocumentsComponent loading={loading}
loading={loading} data={data ? data.jobs_by_pk : null}
data={data ? data.jobs_by_pk : null} />
/> </Col>
</Col>
)}
<Col {...span}> <Col {...span}>
<JobDetailCardsDamageComponent <JobDetailCardsDamageComponent
loading={loading} loading={loading}
@@ -169,4 +161,4 @@ export function JobDetailCards({ bodyshop, setPrintCenterContext }) {
</Drawer> </Drawer>
); );
} }
export default connect(mapStateToProps, mapDispatchToProps)(JobDetailCards); export default connect(null, mapDispatchToProps)(JobDetailCards);

View File

@@ -6,7 +6,6 @@ import {
EditFilled, EditFilled,
PlusCircleTwoTone, PlusCircleTwoTone,
MinusCircleTwoTone, MinusCircleTwoTone,
HomeOutlined,
} from "@ant-design/icons"; } from "@ant-design/icons";
import { useMutation } from "@apollo/client"; import { useMutation } from "@apollo/client";
import { import {
@@ -43,7 +42,6 @@ import _ from "lodash";
import JobCreateIOU from "../job-create-iou/job-create-iou.component"; import JobCreateIOU from "../job-create-iou/job-create-iou.component";
import JobLinesExpander from "./job-lines-expander.component"; import JobLinesExpander from "./job-lines-expander.component";
import { selectBodyshop } from "../../redux/user/user.selectors"; import { selectBodyshop } from "../../redux/user/user.selectors";
import moment from "moment";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop, bodyshop: selectBodyshop,
@@ -56,8 +54,6 @@ const mapDispatchToProps = (dispatch) => ({
dispatch(setModalContext({ context: context, modal: "jobLineEdit" })), dispatch(setModalContext({ context: context, modal: "jobLineEdit" })),
setPartsOrderContext: (context) => setPartsOrderContext: (context) =>
dispatch(setModalContext({ context: context, modal: "partsOrder" })), dispatch(setModalContext({ context: context, modal: "partsOrder" })),
setBillEnterContext: (context) =>
dispatch(setModalContext({ context: context, modal: "billEnter" })),
}); });
export function JobLinesComponent({ export function JobLinesComponent({
@@ -72,7 +68,6 @@ export function JobLinesComponent({
job, job,
setJobLineEditContext, setJobLineEditContext,
form, form,
setBillEnterContext,
}) { }) {
const [deleteJobLine] = useMutation(DELETE_JOB_LINE_BY_PK); const [deleteJobLine] = useMutation(DELETE_JOB_LINE_BY_PK);
@@ -391,62 +386,6 @@ export function JobLinesComponent({
</Space> </Space>
</Tag> </Tag>
)} )}
<Button
disabled={
(job && !job.converted) ||
(selectedLines.length > 0 ? false : true) ||
jobRO ||
technician
}
onClick={() => {
// setPartsOrderContext({
// actions: { refetch: refetch },
// context: {
// jobId: job.id,
// job: job,
// linesToOrder: selectedLines,
// },
// });
setBillEnterContext({
actions: { refetch: refetch },
context: {
disableInvNumber: true,
job: { id: job.id },
bill: {
vendorid: bodyshop.inhousevendorid,
invoice_number: "ih",
isinhouse: true,
date: new moment(),
total: 0,
billlines: selectedLines.map((p) => {
return {
joblineid: p.id,
actual_price: p.act_price,
actual_cost: 0, //p.act_price,
line_desc: p.line_desc,
line_remarks: p.line_remarks,
part_type: p.part_type,
quantity: p.quantity || 1,
applicable_taxes: {
local: false,
state: false,
federal: false,
},
};
}),
},
},
});
//Clear out the selected lines. IO-785
setSelectedLines([]);
}}
>
<HomeOutlined />
{t("parts.actions.orderinhouse")}
{selectedLines.length > 0 && ` (${selectedLines.length})`}
</Button>
<Button <Button
disabled={ disabled={
(job && !job.converted) || (job && !job.converted) ||

View File

@@ -24,7 +24,7 @@ export function JoblinePresetButton({ bodyshop, form }) {
const menu = ( const menu = (
<Menu> <Menu>
{bodyshop.md_jobline_presets.map((i, idx) => ( {bodyshop.md_jobline_presets.map((i, idx) => (
<Menu.Item onClick={() => handleSelect(i)} key={idx}> <Menu.Item onClick={() => handleSelect(i)} onItemHover key={idx}>
{i.label} {i.label}
</Menu.Item> </Menu.Item>
))} ))}

View File

@@ -141,9 +141,7 @@ export function JobLinesUpsertModalComponent({
rules={[ rules={[
({ getFieldValue }) => ({ ({ getFieldValue }) => ({
validator(rule, value) { validator(rule, value) {
if ( if (!!getFieldValue("mod_lbr_ty") === !!value) {
!!getFieldValue("mod_lbr_ty") === (!!value || value === 0)
) {
return Promise.resolve(); return Promise.resolve();
} }
return Promise.reject( return Promise.reject(

View File

@@ -1,80 +0,0 @@
import React, { useMemo } from "react";
import { Row, Col, Tag, Tooltip } from "antd";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
});
const mapDispatchToProps = (dispatch) => ({
//setUserLanguage: language => dispatch(setUserLanguage(language))
});
export default connect(mapStateToProps, mapDispatchToProps)(JobPartsQueueCount);
export function JobPartsQueueCount({ bodyshop, parts }) {
const partsStatus = useMemo(() => {
if (!parts) return null;
return parts.reduce(
(acc, val) => {
if (val.part_type === "PAS" || val.part_type === "PASL") return acc;
acc.total = acc.total + val.count;
acc[val.status] = acc[val.status] + val.count;
return acc;
},
{
total: 0,
null: 0,
[bodyshop.md_order_statuses.default_bo]: 0,
[bodyshop.md_order_statuses.default_ordered]: 0,
[bodyshop.md_order_statuses.default_received]: 0,
[bodyshop.md_order_statuses.default_returned]: 0,
}
);
}, [bodyshop, parts]);
if (!parts) return null;
return (
<Row>
<Col span={4}>
<Tooltip title="Total">
<Tag>{partsStatus.total}</Tag>
</Tooltip>
</Col>
<Col span={4}>
<Tooltip title="No Status">
<Tag color="gold">{partsStatus["null"]}</Tag>
</Tooltip>
</Col>
<Col span={4}>
<Tooltip title={bodyshop.md_order_statuses.default_ordered}>
<Tag color="blue">
{partsStatus[bodyshop.md_order_statuses.default_ordered]}
</Tag>
</Tooltip>
</Col>
<Col span={4}>
<Tooltip title={bodyshop.md_order_statuses.default_received}>
<Tag color="green">
{partsStatus[bodyshop.md_order_statuses.default_received]}
</Tag>
</Tooltip>
</Col>
<Col span={4}>
<Tooltip title={bodyshop.md_order_statuses.default_returned}>
<Tag color="orange">
{partsStatus[bodyshop.md_order_statuses.default_returned]}
</Tag>
</Tooltip>
</Col>
<Col span={4}>
<Tooltip title={bodyshop.md_order_statuses.default_bo}>
<Tag color="red">
{partsStatus[bodyshop.md_order_statuses.default_bo]}
</Tag>
</Tooltip>
</Col>
</Row>
);
}

View File

@@ -1,23 +1,24 @@
import { useMutation } from "@apollo/client"; import { Button, notification } from "antd";
import { Checkbox, notification, Space, Spin } from "antd";
import React, { useState } from "react"; import React, { useState } from "react";
import { useTranslation } from "react-i18next"; import { useMutation } from "@apollo/client";
import { UPDATE_JOB } from "../../graphql/jobs.queries"; import { UPDATE_JOB } from "../../graphql/jobs.queries";
import { useTranslation } from "react-i18next";
export default function JobRemoveFromPartsQueue({ checked, jobId }) { export default function JobRemoveFromPartsQueue({ jobId, refetch }) {
const [updateJob] = useMutation(UPDATE_JOB); const [updateJob] = useMutation(UPDATE_JOB);
const { t } = useTranslation(); const { t } = useTranslation();
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const handleChange = async (e) => { const handleClick = async (e) => {
setLoading(true); setLoading(true);
const result = await updateJob({ const result = await updateJob({
variables: { jobId: jobId, job: { queued_for_parts: e.target.checked } }, variables: { jobId: jobId, job: { queued_for_parts: false } },
}); });
if (!!!result.errors) { if (!!!result.errors) {
notification["success"]({ message: t("jobs.successes.save") }); notification["success"]({ message: t("jobs.successes.save") });
if (refetch) refetch();
} else { } else {
notification["error"]({ notification["error"]({
message: t("jobs.errors.saving", { message: t("jobs.errors.saving", {
@@ -29,9 +30,8 @@ export default function JobRemoveFromPartsQueue({ checked, jobId }) {
}; };
return ( return (
<Space> <Button onClick={handleClick} loading={loading}>
<Checkbox checked={checked} onChange={handleChange} /> {t("general.actions.remove")}
{loading && <Spin size="small" />} </Button>
</Space>
); );
} }

View File

@@ -6,20 +6,17 @@ import { useTranslation } from "react-i18next";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { createStructuredSelector } from "reselect"; import { createStructuredSelector } from "reselect";
import { UPDATE_JOB_STATUS } from "../../graphql/jobs.queries"; import { UPDATE_JOB_STATUS } from "../../graphql/jobs.queries";
import { insertAuditTrail } from "../../redux/application/application.actions";
import { selectBodyshop } from "../../redux/user/user.selectors"; import { selectBodyshop } from "../../redux/user/user.selectors";
import AuditTrailMapping from "../../utils/AuditTrailMappings";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop, bodyshop: selectBodyshop,
}); });
const mapDispatchToProps = (dispatch) => ({ const mapDispatchToProps = (dispatch) => ({
insertAuditTrail: ({ jobid, operation }) => //setUserLanguage: language => dispatch(setUserLanguage(language))
dispatch(insertAuditTrail({ jobid, operation })),
}); });
export default connect(mapStateToProps, mapDispatchToProps)(JobsAdminStatus); export default connect(mapStateToProps, mapDispatchToProps)(JobsAdminStatus);
export function JobsAdminStatus({ insertAuditTrail, bodyshop, job }) { export function JobsAdminStatus({ bodyshop, job }) {
const { t } = useTranslation(); const { t } = useTranslation();
const [mutationUpdateJobstatus] = useMutation(UPDATE_JOB_STATUS); const [mutationUpdateJobstatus] = useMutation(UPDATE_JOB_STATUS);
@@ -29,10 +26,6 @@ export function JobsAdminStatus({ insertAuditTrail, bodyshop, job }) {
}) })
.then((r) => { .then((r) => {
notification["success"]({ message: t("jobs.successes.save") }); notification["success"]({ message: t("jobs.successes.save") });
insertAuditTrail({
jobid: job.id,
operation: AuditTrailMapping.admin_jobstatuschange(status),
});
// refetch(); // refetch();
}) })
.catch((error) => { .catch((error) => {

View File

@@ -7,27 +7,8 @@ import DateTimePicker from "../form-date-time-picker/form-date-time-picker.compo
import LayoutFormRow from "../layout-form-row/layout-form-row.component"; import LayoutFormRow from "../layout-form-row/layout-form-row.component";
import moment from "moment"; import moment from "moment";
import FormDatePicker from "../form-date-picker/form-date-picker.component"; import FormDatePicker from "../form-date-picker/form-date-picker.component";
import AuditTrailMapping from "../../utils/AuditTrailMappings";
import { connect } from "react-redux"; export default function JobsAdminDatesChange({ job }) {
import { createStructuredSelector } from "reselect";
import { insertAuditTrail } from "../../redux/application/application.actions";
const mapStateToProps = createStructuredSelector({
//currentUser: selectCurrentUser
});
const mapDispatchToProps = (dispatch) => ({
insertAuditTrail: ({ jobid, operation }) =>
dispatch(insertAuditTrail({ jobid, operation })),
});
export default connect(
mapStateToProps,
mapDispatchToProps
)(JobsAdminDatesChange);
export function JobsAdminDatesChange({ insertAuditTrail, job }) {
const { t } = useTranslation(); const { t } = useTranslation();
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [form] = Form.useForm(); const [form] = Form.useForm();
@@ -39,23 +20,6 @@ export function JobsAdminDatesChange({ insertAuditTrail, job }) {
variables: { jobId: job.id, job: values }, variables: { jobId: job.id, job: values },
}); });
const changedAuditFields = form.getFieldsValue(
true,
(meta) => meta && meta.touched
);
Object.keys(changedAuditFields).forEach((key) => {
insertAuditTrail({
jobid: job.id,
operation: AuditTrailMapping.admin_jobfieldchange(
key,
changedAuditFields[key] instanceof moment
? moment(changedAuditFields[key]).format("MM/DD/YYYY hh:mm a")
: changedAuditFields[key]
),
});
});
if (!!!result.errors) { if (!!!result.errors) {
notification["success"]({ message: t("jobs.successes.save") }); notification["success"]({ message: t("jobs.successes.save") });
} else { } else {

View File

@@ -8,21 +8,18 @@ import { connect } from "react-redux";
import { createStructuredSelector } from "reselect"; import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors"; import { selectBodyshop } from "../../redux/user/user.selectors";
import moment from "moment"; import moment from "moment";
import AuditTrailMapping from "../../utils/AuditTrailMappings";
import { insertAuditTrail } from "../../redux/application/application.actions";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop, bodyshop: selectBodyshop,
}); });
const mapDispatchToProps = (dispatch) => ({ const mapDispatchToProps = (dispatch) => ({
insertAuditTrail: ({ jobid, operation }) => //setUserLanguage: language => dispatch(setUserLanguage(language))
dispatch(insertAuditTrail({ jobid, operation })),
}); });
export default connect( export default connect(
mapStateToProps, mapStateToProps,
mapDispatchToProps mapDispatchToProps
)(JobAdminMarkReexport); )(JobAdminMarkReexport);
export function JobAdminMarkReexport({ insertAuditTrail, bodyshop, job }) { export function JobAdminMarkReexport({ bodyshop, job }) {
const { t } = useTranslation(); const { t } = useTranslation();
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [markJobForReexport] = useMutation(gql` const [markJobForReexport] = useMutation(gql`
@@ -81,10 +78,6 @@ export function JobAdminMarkReexport({ insertAuditTrail, bodyshop, job }) {
if (!result.errors) { if (!result.errors) {
notification["success"]({ message: t("jobs.successes.save") }); notification["success"]({ message: t("jobs.successes.save") });
insertAuditTrail({
jobid: job.id,
operation: AuditTrailMapping.admin_jobmarkforreexport(),
});
} else { } else {
notification["error"]({ notification["error"]({
message: t("jobs.errors.saving", { message: t("jobs.errors.saving", {
@@ -103,10 +96,6 @@ export function JobAdminMarkReexport({ insertAuditTrail, bodyshop, job }) {
if (!result.errors) { if (!result.errors) {
notification["success"]({ message: t("jobs.successes.save") }); notification["success"]({ message: t("jobs.successes.save") });
insertAuditTrail({
jobid: job.id,
operation: AuditTrailMapping.admin_jobmarkexported(),
});
} else { } else {
notification["error"]({ notification["error"]({
message: t("jobs.errors.saving", { message: t("jobs.errors.saving", {

View File

@@ -4,29 +4,21 @@ import React, { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { createStructuredSelector } from "reselect"; import { createStructuredSelector } from "reselect";
import { insertAuditTrail } from "../../redux/application/application.actions";
import { import {
selectBodyshop, selectBodyshop,
selectCurrentUser, selectCurrentUser,
} from "../../redux/user/user.selectors"; } from "../../redux/user/user.selectors";
import AuditTrailMapping from "../../utils/AuditTrailMappings";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop, bodyshop: selectBodyshop,
currentUser: selectCurrentUser, currentUser: selectCurrentUser,
}); });
const mapDispatchToProps = (dispatch) => ({ const mapDispatchToProps = (dispatch) => ({
insertAuditTrail: ({ jobid, operation }) => //setUserLanguage: language => dispatch(setUserLanguage(language))
dispatch(insertAuditTrail({ jobid, operation })),
}); });
export default connect(mapStateToProps, mapDispatchToProps)(JobsAdminUnvoid); export default connect(mapStateToProps, mapDispatchToProps)(JobsAdminUnvoid);
export function JobsAdminUnvoid({ export function JobsAdminUnvoid({ bodyshop, job, currentUser }) {
insertAuditTrail,
bodyshop,
job,
currentUser,
}) {
const { t } = useTranslation(); const { t } = useTranslation();
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [updateJob] = useMutation(gql` const [updateJob] = useMutation(gql`
@@ -92,11 +84,6 @@ mutation UNVOID_JOB($jobId: uuid!) {
if (!result.errors) { if (!result.errors) {
notification["success"]({ message: t("jobs.successes.save") }); notification["success"]({ message: t("jobs.successes.save") });
insertAuditTrail({
jobid: job.id,
operation: AuditTrailMapping.admin_unvoicejob(),
});
} else { } else {
notification["error"]({ notification["error"]({
message: t("jobs.errors.saving", { message: t("jobs.errors.saving", {

View File

@@ -15,6 +15,7 @@ import { logImEXEvent } from "../../firebase/firebase.utils";
import { INSERT_EXPORT_LOG } from "../../graphql/accounting.queries"; import { INSERT_EXPORT_LOG } from "../../graphql/accounting.queries";
import { useHistory } from "react-router-dom"; import { useHistory } from "react-router-dom";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop, bodyshop: selectBodyshop,
currentUser: selectCurrentUser, currentUser: selectCurrentUser,
@@ -26,7 +27,6 @@ export function JobsCloseExportButton({
jobId, jobId,
disabled, disabled,
setSelectedJobs, setSelectedJobs,
refetch,
}) { }) {
const history = useHistory(); const history = useHistory();
const { t } = useTranslation(); const { t } = useTranslation();
@@ -46,10 +46,13 @@ export function JobsCloseExportButton({
//Check if it's a QBO Setup. //Check if it's a QBO Setup.
let PartnerResponse; let PartnerResponse;
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) { if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) {
PartnerResponse = await axios.post(`/qbo/receivables`, { PartnerResponse = await axios.post(
jobIds: [jobId], `/qbo/receivables`,
elgen: true, {
}); jobIds: [jobId],
},
);
} else { } else {
//Default is QBD //Default is QBD
@@ -114,64 +117,58 @@ export function JobsCloseExportButton({
}); });
}); });
if (!(bodyshop.accountingconfig && bodyshop.accountingconfig.qbo)) { await insertExportLog({
//QBO Logs are handled server side. variables: {
await insertExportLog({ logs: [
variables: { {
logs: [ bodyshopid: bodyshop.id,
{ jobid: jobId,
bodyshopid: bodyshop.id, successful: false,
jobid: jobId, message: JSON.stringify(
successful: false, failedTransactions.map((ft) => ft.errorMessage)
message: JSON.stringify( ),
failedTransactions.map((ft) => ft.errorMessage) useremail: currentUser.email,
), },
useremail: currentUser.email, ],
}, },
], });
},
});
}
} else { } else {
//Insert success export log. //Insert success export log.
if (!(bodyshop.accountingconfig && bodyshop.accountingconfig.qbo)) { await insertExportLog({
//QBO Logs are handled server side. variables: {
await insertExportLog({ logs: [
variables: { {
logs: [ bodyshopid: bodyshop.id,
{ jobid: jobId,
bodyshopid: bodyshop.id, successful: true,
jobid: jobId, useremail: currentUser.email,
successful: true,
useremail: currentUser.email,
},
],
},
});
const jobUpdateResponse = await updateJob({
variables: {
jobId: jobId,
job: {
status: bodyshop.md_ro_statuses.default_exported || "Exported*",
date_exported: new Date(),
}, },
}, ],
}); },
});
if (!jobUpdateResponse.errors) { const jobUpdateResponse = await updateJob({
notification.open({ variables: {
type: "success", jobId: jobId,
key: "jobsuccessexport", job: {
message: t("jobs.successes.exported"), status: bodyshop.md_ro_statuses.default_exported || "Exported*",
}); date_exported: new Date(),
} else { },
notification["error"]({ },
message: t("jobs.errors.exporting", { });
error: JSON.stringify(jobUpdateResponse.error),
}), if (!jobUpdateResponse.errors) {
}); notification.open({
} type: "success",
key: "jobsuccessexport",
message: t("jobs.successes.exported"),
});
} else {
notification["error"]({
message: t("jobs.errors.exporting", {
error: JSON.stringify(jobUpdateResponse.error),
}),
});
} }
if (setSelectedJobs) { if (setSelectedJobs) {
setSelectedJobs((selectedJobs) => { setSelectedJobs((selectedJobs) => {
@@ -179,7 +176,7 @@ export function JobsCloseExportButton({
}); });
} }
} }
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) refetch();
setLoading(false); setLoading(false);
}; };

View File

@@ -146,11 +146,7 @@ export function JobsCreateJobsInfo({ bodyshop, form, selected }) {
</Form.Item> </Form.Item>
</LayoutFormRow> </LayoutFormRow>
</Collapse.Panel> </Collapse.Panel>
<Collapse.Panel <Collapse.Panel forceRender key="claim" header={t("menus.jobsdetail.claimdetail")}>
forceRender
key="claim"
header={t("menus.jobsdetail.claimdetail")}
>
<LayoutFormRow> <LayoutFormRow>
<Form.Item label={t("jobs.fields.loss_desc")} name="loss_desc"> <Form.Item label={t("jobs.fields.loss_desc")} name="loss_desc">
<Input /> <Input />
@@ -197,8 +193,7 @@ export function JobsCreateJobsInfo({ bodyshop, form, selected }) {
</Form.Item> </Form.Item>
</LayoutFormRow> </LayoutFormRow>
</Collapse.Panel> </Collapse.Panel>
<Collapse.Panel <Collapse.Panel forceRender
forceRender
key="financial" key="financial"
header={t("menus.jobsdetail.financials")} header={t("menus.jobsdetail.financials")}
> >
@@ -209,7 +204,7 @@ export function JobsCreateJobsInfo({ bodyshop, form, selected }) {
<CurrencyInput min={0} /> <CurrencyInput min={0} />
</Form.Item> </Form.Item>
<Form.Item label={t("jobs.fields.ded_status")} name="ded_status"> <Form.Item label={t("jobs.fields.ded_status")} name="ded_status">
<Select allowClear> <Select>
<Select.Option value="W"> <Select.Option value="W">
{t("jobs.labels.deductible.waived")} {t("jobs.labels.deductible.waived")}
</Select.Option> </Select.Option>

View File

@@ -97,7 +97,7 @@ export function JobsDetailRates({ jobRO, form, job, bodyshop }) {
</Form.Item> </Form.Item>
<Form.Item <Form.Item
noStyle nostyle
shouldUpdate={(prev, cur) => prev.auto_add_ats !== cur.auto_add_ats} shouldUpdate={(prev, cur) => prev.auto_add_ats !== cur.auto_add_ats}
> >
{() => { {() => {

View File

@@ -1,5 +1,5 @@
import { EditFilled, FileExcelFilled, SyncOutlined } from "@ant-design/icons"; import { FileExcelFilled, EditFilled, SyncOutlined } from "@ant-design/icons";
import { Button, Card, Col, Row, Space } from "antd"; import { Card, Col, Row, Space, Button } from "antd";
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import Gallery from "react-grid-gallery"; import Gallery from "react-grid-gallery";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";

View File

@@ -1,105 +0,0 @@
import { SyncOutlined } from "@ant-design/icons";
import { Button, Card, Space } from "antd";
import React, { useEffect } from "react";
import Gallery from "react-grid-gallery";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import {
getBillMedia,
getJobMedia,
toggleMediaSelected,
} from "../../redux/media/media.actions";
import { selectAllMedia } from "../../redux/media/media.selectors";
import { selectBodyshop } from "../../redux/user/user.selectors";
import { CreateExplorerLinkForJob } from "../../utils/localmedia";
import DocumentsLocalUploadComponent from "../documents-local-upload/documents-local-upload.component";
import JobsDocumentsLocalGalleryReassign from "./jobs-documents-local-gallery.reassign.component";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
allMedia: selectAllMedia,
});
const mapDispatchToProps = (dispatch) => ({
getJobMedia: (id) => dispatch(getJobMedia(id)),
getBillMedia: ({ jobid, invoice_number }) => {
dispatch(getBillMedia({ jobid, invoice_number }));
},
toggleMediaSelected: ({ jobid, filename }) =>
dispatch(toggleMediaSelected({ jobid, filename })),
});
export default connect(
mapStateToProps,
mapDispatchToProps
)(JobsDocumentsLocalGallery);
export function JobsDocumentsLocalGallery({
bodyshop,
toggleMediaSelected,
getJobMedia,
getBillMedia,
allMedia,
job,
invoice_number,
vendorid,
}) {
const { t } = useTranslation();
useEffect(() => {
if (job) {
if (invoice_number) {
getBillMedia({ jobid: job.id, invoice_number });
} else {
getJobMedia(job.id);
}
}
}, [job, invoice_number, getJobMedia, getBillMedia]);
return (
<div>
<Space wrap>
<Button
onClick={() => {
if (job) {
if (invoice_number) {
getBillMedia({ jobid: job.id, invoice_number });
} else {
getJobMedia(job.id);
}
}
}}
>
<SyncOutlined />
</Button>
<a href={CreateExplorerLinkForJob({ jobid: job.id })}>
<Button>{t("documents.labels.openinexplorer")}</Button>
</a>
<JobsDocumentsLocalGalleryReassign jobid={job.id} />
</Space>
<Card>
<DocumentsLocalUploadComponent
job={job}
invoice_number={invoice_number}
vendorid={vendorid}
/>
</Card>
<Card title={t("jobs.labels.documents-images")}>
<Gallery
images={(allMedia && allMedia[job.id]) || []}
backdropClosesModal={true}
onSelectImage={(index, image) => {
toggleMediaSelected({ jobid: job.id, filename: image.filename });
}}
onClickImage={(props) => {
window.open(
props.target.src,
"_blank",
"toolbar=0,location=0,menubar=0"
);
}}
/>
</Card>
</div>
);
}

View File

@@ -1,92 +0,0 @@
import { Button, Form, Popover, Space } from "antd";
import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { getJobMedia } from "../../redux/media/media.actions";
import { selectAllMedia } from "../../redux/media/media.selectors";
import { selectBodyshop } from "../../redux/user/user.selectors";
import cleanAxios from "../../utils/CleanAxios";
import JobSearchSelect from "../job-search-select/job-search-select.component";
const mapStateToProps = createStructuredSelector({
allMedia: selectAllMedia,
bodyshop: selectBodyshop,
});
const mapDispatchToProps = (dispatch) => ({
getJobMedia: (id) => dispatch(getJobMedia(id)),
//setUserLanguage: language => dispatch(setUserLanguage(language))
});
export default connect(
mapStateToProps,
mapDispatchToProps
)(JobsDocumentsLocalGalleryReassign);
export function JobsDocumentsLocalGalleryReassign({
bodyshop,
jobid,
allMedia,
getJobMedia,
}) {
const { t } = useTranslation();
const [form] = Form.useForm();
const [visible, setVisible] = useState(false);
const [loading, setLoading] = useState(false);
const handleFinish = async ({ jobid: newJobid }) => {
setLoading(true);
const selectedDocuments = allMedia[jobid].filter((m) => m.isSelected);
await cleanAxios.post(`${bodyshop.localmediaserverhttp}/jobs/move`, {
from_jobid: jobid,
jobid: newJobid,
files: selectedDocuments.map((f) => f.filename),
});
getJobMedia(jobid);
setVisible(false);
setLoading(false);
};
const popContent = (
<div>
<Form onFinish={handleFinish} layout="vertical" form={form}>
<Form.Item
label={t("documents.labels.newjobid")}
style={{ width: "20rem" }}
rules={[
{
required: true,
//message: t("general.validation.required"),
},
]}
name={"jobid"}
>
<JobSearchSelect />
</Form.Item>
</Form>
<Space>
<Button type="primary" onClick={() => form.submit()}>
{t("general.actions.submit")}
</Button>
<Button onClick={() => setVisible(false)}>
{t("general.actions.cancel")}
</Button>
</Space>
</div>
);
return (
<Popover content={popContent} visible={visible}>
<Button
//disabled={selectedImages.length < 1}
onClick={() => setVisible(true)}
loading={loading}
>
{t("documents.actions.reassign")}
</Button>
</Popover>
);
}

View File

@@ -26,7 +26,6 @@ export function JobsExportAllButton({
disabled, disabled,
loadingCallback, loadingCallback,
completedCallback, completedCallback,
refetch,
}) { }) {
const { t } = useTranslation(); const { t } = useTranslation();
const [updateJob] = useMutation(UPDATE_JOBS); const [updateJob] = useMutation(UPDATE_JOBS);
@@ -40,7 +39,6 @@ export function JobsExportAllButton({
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) { if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) {
PartnerResponse = await axios.post(`/qbo/receivables`, { PartnerResponse = await axios.post(`/qbo/receivables`, {
jobIds: jobIds, jobIds: jobIds,
elgen: true,
}); });
} else { } else {
let QbXmlResponse; let QbXmlResponse;
@@ -85,7 +83,6 @@ export function JobsExportAllButton({
return; return;
} }
} }
console.log("PartnerResponse", PartnerResponse); console.log("PartnerResponse", PartnerResponse);
const groupedData = _.groupBy( const groupedData = _.groupBy(
PartnerResponse.data, PartnerResponse.data,
@@ -109,70 +106,61 @@ export function JobsExportAllButton({
}); });
//Call is not awaited as it is not critical to finish before proceeding. //Call is not awaited as it is not critical to finish before proceeding.
}); });
await insertExportLog({
if (!(bodyshop.accountingconfig && bodyshop.accountingconfig.qbo)) { variables: {
//QBO Logs are handled server side. logs: [
await insertExportLog({ {
variables: { bodyshopid: bodyshop.id,
logs: [ jobid: key,
{ successful: false,
bodyshopid: bodyshop.id, message: JSON.stringify(
jobid: key, failedTransactions.map((ft) => ft.errorMessage)
successful: false, ),
message: JSON.stringify( useremail: currentUser.email,
failedTransactions.map((ft) => ft.errorMessage)
),
useremail: currentUser.email,
},
],
},
});
}
} else {
if (!(bodyshop.accountingconfig && bodyshop.accountingconfig.qbo)) {
//QBO Logs are handled server side.
await insertExportLog({
variables: {
logs: [
{
bodyshopid: bodyshop.id,
jobid: key,
successful: true,
useremail: currentUser.email,
},
],
},
});
const jobUpdateResponse = await updateJob({
variables: {
jobIds: [key],
fields: {
status:
bodyshop.md_ro_statuses.default_exported || "Exported*",
date_exported: new Date(),
}, },
}, ],
}); },
});
} else {
await insertExportLog({
variables: {
logs: [
{
bodyshopid: bodyshop.id,
jobid: key,
successful: true,
useremail: currentUser.email,
},
],
},
});
if (!jobUpdateResponse.errors) { const jobUpdateResponse = await updateJob({
notification.open({ variables: {
type: "success", jobIds: [key],
key: "jobsuccessexport", fields: {
message: t("jobs.successes.exported"), status: bodyshop.md_ro_statuses.default_exported || "Exported*",
}); date_exported: new Date(),
} else { },
notification["error"]({ },
message: t("jobs.errors.exporting", { });
error: JSON.stringify(jobUpdateResponse.error),
}), if (!jobUpdateResponse.errors) {
}); notification.open({
} type: "success",
key: "jobsuccessexport",
message: t("jobs.successes.exported"),
});
} else {
notification["error"]({
message: t("jobs.errors.exporting", {
error: JSON.stringify(jobUpdateResponse.error),
}),
});
} }
} }
}) })
); );
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) refetch();
if (!!completedCallback) completedCallback([]); if (!!completedCallback) completedCallback([]);
if (!!loadingCallback) loadingCallback(false); if (!!loadingCallback) loadingCallback(false);

View File

@@ -1,355 +0,0 @@
import {
ExclamationCircleFilled,
PauseCircleOutlined,
SyncOutlined,
} from "@ant-design/icons";
import { useQuery } from "@apollo/client";
import { Button, Card, Grid, Input, Space, Table } from "antd";
import queryString from "query-string";
import React, { useMemo, useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { Link, useHistory, useLocation } from "react-router-dom";
import { createStructuredSelector } from "reselect";
import { QUERY_ALL_ACTIVE_JOBS } from "../../graphql/jobs.queries";
import { selectBodyshop } from "../../redux/user/user.selectors";
import { onlyUnique } from "../../utils/arrayHelper";
import CurrencyFormatter from "../../utils/CurrencyFormatter";
import { alphaSort } from "../../utils/sorters";
import AlertComponent from "../alert/alert.component";
import ChatOpenButton from "../chat-open-button/chat-open-button.component";
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
});
export function JobsReadyList({ bodyshop }) {
const searchParams = queryString.parse(useLocation().search);
const { selected } = searchParams;
const selectedBreakpoint = Object.entries(Grid.useBreakpoint())
.filter((screen) => !!screen[1])
.slice(-1)[0];
const readyStatuses = useMemo(() => {
if (bodyshop.md_ro_statuses.ready_statuses)
return bodyshop.md_ro_statuses.ready_statuses;
return bodyshop.md_ro_statuses.post_production_statuses.filter(
(s) =>
s !== bodyshop.md_ro_statuses.default_invoiced &&
s !== bodyshop.md_ro_statuses.default_exported
);
}, [bodyshop.md_ro_statuses]);
const { loading, error, data, refetch } = useQuery(QUERY_ALL_ACTIVE_JOBS, {
variables: {
statuses: readyStatuses,
},
fetchPolicy: "network-only",
nextFetchPolicy: "network-only",
});
const [state, setState] = useState({
sortedInfo: {},
filteredInfo: { text: "" },
});
const { t } = useTranslation();
const history = useHistory();
const [searchText, setSearchText] = useState("");
if (error) return <AlertComponent message={error.message} type="error" />;
const jobs = data
? searchText === ""
? data.jobs
: data.jobs.filter(
(j) =>
(j.ro_number || "")
.toString()
.toLowerCase()
.includes(searchText.toLowerCase()) ||
(j.ownr_co_nm || "")
.toLowerCase()
.includes(searchText.toLowerCase()) ||
(j.comments || "")
.toLowerCase()
.includes(searchText.toLowerCase()) ||
(j.ownr_fn || "")
.toLowerCase()
.includes(searchText.toLowerCase()) ||
(j.ownr_ln || "")
.toLowerCase()
.includes(searchText.toLowerCase()) ||
(j.clm_no || "").toLowerCase().includes(searchText.toLowerCase()) ||
(j.plate_no || "")
.toLowerCase()
.includes(searchText.toLowerCase()) ||
(j.v_model_desc || "")
.toLowerCase()
.includes(searchText.toLowerCase()) ||
(j.v_make_desc || "")
.toLowerCase()
.includes(searchText.toLowerCase())
)
: [];
const handleTableChange = (pagination, filters, sorter) => {
setState({ ...state, filteredInfo: filters, sortedInfo: sorter });
};
const handleOnRowClick = (record) => {
if (record) {
if (record.id) {
history.push({
search: queryString.stringify({
...searchParams,
selected: record.id,
}),
});
}
}
};
const columns = [
{
title: t("jobs.fields.ro_number"),
dataIndex: "ro_number",
key: "ro_number",
sorter: (a, b) => alphaSort(a.ro_number, b.ro_number),
sortOrder:
state.sortedInfo.columnKey === "ro_number" && state.sortedInfo.order,
render: (text, record) => (
<Link
to={"/manage/jobs/" + record.id}
onClick={(e) => e.stopPropagation()}
>
<Space>
{record.ro_number || t("general.labels.na")}
{record.production_vars && record.production_vars.alert ? (
<ExclamationCircleFilled className="production-alert" />
) : null}
{record.suspended && (
<PauseCircleOutlined style={{ color: "orangered" }} />
)}
</Space>
</Link>
),
},
{
title: t("jobs.fields.owner"),
dataIndex: "owner",
key: "owner",
ellipsis: true,
responsive: ["md"],
sorter: (a, b) => alphaSort(a.ownr_ln, b.ownr_ln),
sortOrder:
state.sortedInfo.columnKey === "owner" && state.sortedInfo.order,
render: (text, record) => {
return record.owner ? (
<Link
to={"/manage/owners/" + record.owner.id}
onClick={(e) => e.stopPropagation()}
>
<OwnerNameDisplay ownerObject={record} />
</Link>
) : (
<span>
<OwnerNameDisplay ownerObject={record} />
</span>
);
},
},
{
title: t("jobs.fields.ownr_ph1"),
dataIndex: "ownr_ph1",
key: "ownr_ph1",
ellipsis: true,
responsive: ["md"],
render: (text, record) => (
<ChatOpenButton phone={record.ownr_ph1} jobid={record.id} />
),
},
{
title: t("jobs.fields.ownr_ph2"),
dataIndex: "ownr_ph2",
key: "ownr_ph2",
ellipsis: true,
responsive: ["md"],
render: (text, record) => (
<ChatOpenButton phone={record.ownr_ph2} jobid={record.id} />
),
},
{
title: t("jobs.fields.status"),
dataIndex: "status",
key: "status",
ellipsis: true,
sorter: (a, b) => alphaSort(a.status, b.status),
sortOrder:
state.sortedInfo.columnKey === "status" && state.sortedInfo.order,
filters:
(jobs &&
jobs
.map((j) => j.status)
.filter(onlyUnique)
.map((s) => {
return {
text: s || "No Status*",
value: [s],
};
})) ||
[],
onFilter: (value, record) => value.includes(record.status),
},
{
title: t("jobs.fields.vehicle"),
dataIndex: "vehicle",
key: "vehicle",
ellipsis: true,
render: (text, record) => {
return record.vehicleid ? (
<Link
to={"/manage/vehicles/" + record.vehicleid}
onClick={(e) => e.stopPropagation()}
>
{`${record.v_model_yr || ""} ${record.v_make_desc || ""} ${
record.v_model_desc || ""
}`}
</Link>
) : (
<span>{`${record.v_model_yr || ""} ${record.v_make_desc || ""} ${
record.v_model_desc || ""
}`}</span>
);
},
},
{
title: t("vehicles.fields.plate_no"),
dataIndex: "plate_no",
key: "plate_no",
ellipsis: true,
responsive: ["md"],
sorter: (a, b) => alphaSort(a.plate_no, b.plate_no),
sortOrder:
state.sortedInfo.columnKey === "plate_no" && state.sortedInfo.order,
},
{
title: t("jobs.fields.clm_no"),
dataIndex: "clm_no",
key: "clm_no",
ellipsis: true,
responsive: ["md"],
sorter: (a, b) => alphaSort(a.clm_no, b.clm_no),
sortOrder:
state.sortedInfo.columnKey === "clm_no" && state.sortedInfo.order,
render: (text, record) =>
`${record.clm_no || ""}${
record.po_number ? ` (PO: ${record.po_number})` : ""
}`,
},
{
title: t("jobs.fields.ins_co_nm"),
dataIndex: "ins_co_nm",
key: "ins_co_nm",
ellipsis: true,
responsive: ["md"],
},
{
title: t("jobs.fields.clm_total"),
dataIndex: "clm_total",
key: "clm_total",
responsive: ["md"],
ellipsis: true,
sorter: (a, b) => a.clm_total - b.clm_total,
sortOrder:
state.sortedInfo.columnKey === "clm_total" && state.sortedInfo.order,
render: (text, record) => (
<CurrencyFormatter>{record.clm_total}</CurrencyFormatter>
),
},
{
title: t("jobs.fields.comment"),
dataIndex: "comment",
key: "comment",
ellipsis: true,
responsive: ["md"],
},
// {
// title: t("jobs.fields.owner_owing"),
// dataIndex: "owner_owing",
// key: "owner_owing",
// responsive: ["md"],
// render: (text, record) => (
// <CurrencyFormatter>{record.owner_owing}</CurrencyFormatter>
// ),
// },
];
const scrollMapper = {
xs: true,
sm: true,
md: true,
lg: "100%",
xl: "100%",
xxl: "100%",
};
return (
<Card
title={t("titles.bc.jobs-ready")}
extra={
<Space wrap>
<span>({readyStatuses && readyStatuses.join(", ")})</span>
<Button onClick={() => refetch()}>
<SyncOutlined />
</Button>
<Input.Search
placeholder={t("general.labels.search")}
onChange={(e) => {
setSearchText(e.target.value);
}}
value={searchText}
enterButton
/>
</Space>
}
>
<Table
loading={loading}
pagination={{ defaultPageSize: 50 }}
columns={columns}
rowKey="id"
dataSource={jobs}
scroll={{
x: selectedBreakpoint ? scrollMapper[selectedBreakpoint[0]] : "100%",
}}
rowSelection={{
onSelect: (record) => {
handleOnRowClick(record);
},
selectedRowKeys: [selected],
type: "radio",
}}
onChange={handleTableChange}
onRow={(record, rowIndex) => {
return {
onClick: (event) => {
handleOnRowClick(record);
},
};
}}
/>
</Card>
);
}
export default connect(mapStateToProps, null)(JobsReadyList);

View File

@@ -24,7 +24,7 @@ export function NotesPresetButton({ bodyshop, form }) {
const menu = ( const menu = (
<Menu> <Menu>
{bodyshop.md_notes_presets.map((i, idx) => ( {bodyshop.md_notes_presets.map((i, idx) => (
<Menu.Item onClick={() => handleSelect(i)} key={idx}> <Menu.Item onClick={() => handleSelect(i)} onItemHover key={idx}>
{i.label} {i.label}
</Menu.Item> </Menu.Item>
))} ))}

View File

@@ -1,66 +0,0 @@
import { useMutation } from "@apollo/client";
import { Checkbox, notification, Space, Spin } from "antd";
import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import { MUTATION_UPDATE_PO_CM_REECEIVED } from "../../graphql/parts-orders.queries";
export default function PartsOrderCmReceived({
checked,
orderLineId,
partsOrderId,
}) {
const [updateLine] = useMutation(MUTATION_UPDATE_PO_CM_REECEIVED);
const { t } = useTranslation();
const [loading, setLoading] = useState(false);
const handleChange = async (e) => {
setLoading(true);
const result = await updateLine({
variables: {
partsLineId: orderLineId,
partsOrder: { cm_received: e.target.checked },
},
update(cache) {
cache.modify({
id: cache.identify({
id: partsOrderId,
__typename: "parts_orders",
}),
fields: {
parts_order_lines(ex, { readField }) {
console.log(ex);
return ex.map((lineref) => {
if (orderLineId.id !== readField("id", lineref)) {
lineref.cm_received = e.target.checked;
}
return lineref;
});
},
},
});
},
});
if (!!!result.errors) {
notification["success"]({
message: t("parts_orders.successes.line_updated"),
});
} else {
notification["error"]({
message: t("parts_orders.errors.saving", {
error: JSON.stringify(result.errors),
}),
});
}
setLoading(false);
};
return (
<Space>
<Checkbox checked={checked} onChange={handleChange} />
{loading && <Spin size="small" />}
</Space>
);
}

View File

@@ -1,47 +0,0 @@
import React from "react";
import { Button, Popconfirm } from "antd";
import { DeleteFilled } from "@ant-design/icons";
import { useTranslation } from "react-i18next";
import { DELETE_PARTS_ORDER_LINE } from "../../graphql/parts-orders.queries";
import { useMutation } from "@apollo/client";
export default function PartsOrderDeleteLine({
disabled,
partsLineId,
partsOrderId,
}) {
const { t } = useTranslation();
const [deletePartsOrderLine] = useMutation(DELETE_PARTS_ORDER_LINE);
return (
<Popconfirm
title={t("parts_orders.labels.confirmdelete")}
disabled={disabled}
onConfirm={async () => {
//Delete the parts return.!
await deletePartsOrderLine({
variables: { partsOrderLineId: partsLineId },
update(cache) {
cache.modify({
id: cache.identify({
__typename: "parts_orders",
id: partsOrderId,
}),
fields: {
parts_order_lines(cached, { readField }) {
return cached.filter((c) => {
return readField("id", c) !== partsLineId;
});
},
},
});
},
});
}}
>
<Button disabled={disabled}>
<DeleteFilled />
</Button>
</Popconfirm>
);
}

View File

@@ -29,8 +29,6 @@ import { alphaSort } from "../../utils/sorters";
import { TemplateList } from "../../utils/TemplateConstants"; import { TemplateList } from "../../utils/TemplateConstants";
import DataLabel from "../data-label/data-label.component"; import DataLabel from "../data-label/data-label.component";
import PartsOrderBackorderEta from "../parts-order-backorder-eta/parts-order-backorder-eta.component"; import PartsOrderBackorderEta from "../parts-order-backorder-eta/parts-order-backorder-eta.component";
import PartsOrderCmReceived from "../parts-order-cm-received/parts-order-cm-received.component";
import PartsOrderDeleteLine from "../parts-order-delete-line/parts-order-delete-line.component";
import PartsOrderLineBackorderButton from "../parts-order-line-backorder-button/parts-order-line-backorder-button.component"; import PartsOrderLineBackorderButton from "../parts-order-line-backorder-button/parts-order-line-backorder-button.component";
import PartsReceiveModalContainer from "../parts-receive-modal/parts-receive-modal.container"; import PartsReceiveModalContainer from "../parts-receive-modal/parts-receive-modal.container";
import PrintWrapper from "../print-wrapper/print-wrapper.component"; import PrintWrapper from "../print-wrapper/print-wrapper.component";
@@ -79,7 +77,6 @@ export function PartsOrderListTableComponent({
}); });
const search = queryString.parse(useLocation().search); const search = queryString.parse(useLocation().search);
const selectedpartsorder = search.partsorderid; const selectedpartsorder = search.partsorderid;
const [searchText, setSearchText] = useState("");
const [deletePartsOrder] = useMutation(DELETE_PARTS_ORDER); const [deletePartsOrder] = useMutation(DELETE_PARTS_ORDER);
@@ -349,23 +346,6 @@ export function PartsOrderListTableComponent({
dataIndex: "status", dataIndex: "status",
key: "status", key: "status",
}, },
...(selectedPartsOrderRecord && selectedPartsOrderRecord.return
? [
{
title: t("parts_orders.fields.cm_received"),
dataIndex: "cm_received",
key: "cm_received",
render: (text, record) => (
<PartsOrderCmReceived
orderLineId={record.id}
checked={record.cm_received}
partsorderid={selectedPartsOrderRecord.id}
/>
),
},
]
: []),
{ {
title: t("parts_orders.fields.backordered_on"), title: t("parts_orders.fields.backordered_on"),
dataIndex: "backordered_on", dataIndex: "backordered_on",
@@ -392,21 +372,12 @@ export function PartsOrderListTableComponent({
dataIndex: "actions", dataIndex: "actions",
key: "actions", key: "actions",
render: (text, record) => ( render: (text, record) => (
<Space wrap> <PartsOrderLineBackorderButton
<PartsOrderDeleteLine disabled={jobRO}
disabled={jobRO} partsOrderStatus={record.status}
partsOrderStatus={record.status} partsLineId={record.id}
partsLineId={record.id} jobLineId={record.job_line_id}
partsOrderId={selectedpartsorder} />
jobLineId={record.job_line_id}
/>
<PartsOrderLineBackorderButton
disabled={jobRO}
partsOrderStatus={record.status}
partsLineId={record.id}
jobLineId={record.job_line_id}
/>
</Space>
), ),
}, },
]; ];
@@ -432,21 +403,6 @@ export function PartsOrderListTableComponent({
); );
}; };
const filteredPartsOrders = parts_orders
? searchText === ""
? parts_orders
: parts_orders.filter(
(b) =>
(b.order_number || "")
.toString()
.toLowerCase()
.includes(searchText.toLowerCase()) ||
(b.vendor.name || "")
.toLowerCase()
.includes(searchText.toLowerCase())
)
: [];
return ( return (
<Card <Card
title={t("parts_orders.labels.parts_orders")} title={t("parts_orders.labels.parts_orders")}
@@ -457,10 +413,8 @@ export function PartsOrderListTableComponent({
</Button> </Button>
<Input.Search <Input.Search
placeholder={t("general.labels.search")} placeholder={t("general.labels.search")}
value={searchText}
onChange={(e) => { onChange={(e) => {
e.preventDefault(); e.preventDefault();
setSearchText(e.target.value);
}} }}
/> />
</Space> </Space>
@@ -484,7 +438,7 @@ export function PartsOrderListTableComponent({
}} }}
columns={columns} columns={columns}
rowKey="id" rowKey="id"
dataSource={filteredPartsOrders} dataSource={parts_orders}
onChange={handleTableChange} onChange={handleTableChange}
/> />
</Card> </Card>

View File

@@ -305,7 +305,6 @@ export function PartsOrderModalContainer({
quantity: value.part_qty, quantity: value.part_qty,
job_line_id: isReturn ? value.joblineid : value.id, job_line_id: isReturn ? value.joblineid : value.id,
part_type: value.part_type, part_type: value.part_type,
...(isReturn && { cm_received: false }),
}); });
return acc; return acc;
}, []) }, [])

View File

@@ -27,7 +27,6 @@ export function PayableExportAll({
disabled, disabled,
loadingCallback, loadingCallback,
completedCallback, completedCallback,
refetch,
}) { }) {
const { t } = useTranslation(); const { t } = useTranslation();
const [updateBill] = useMutation(UPDATE_BILLS); const [updateBill] = useMutation(UPDATE_BILLS);
@@ -43,7 +42,6 @@ export function PayableExportAll({
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) { if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) {
PartnerResponse = await axios.post(`/qbo/payables`, { PartnerResponse = await axios.post(`/qbo/payables`, {
bills: billids, bills: billids,
elgen: true,
}); });
} else { } else {
let QbXmlResponse; let QbXmlResponse;
@@ -106,62 +104,57 @@ export function PayableExportAll({
}), }),
}) })
); );
if (!(bodyshop.accountingconfig && bodyshop.accountingconfig.qbo)) {
//QBO Logs are handled server side.
await insertExportLog({
variables: {
logs: [
{
bodyshopid: bodyshop.id,
billid: key,
successful: false,
message: JSON.stringify(
failedTransactions.map((ft) => ft.errorMessage)
),
useremail: currentUser.email,
},
],
},
});
}
} else {
if (!(bodyshop.accountingconfig && bodyshop.accountingconfig.qbo)) {
//QBO Logs are handled server side.
await insertExportLog({
variables: {
logs: [
{
bodyshopid: bodyshop.id,
billid: key,
successful: true,
useremail: currentUser.email,
},
],
},
});
const billUpdateResponse = await updateBill({ await insertExportLog({
variables: { variables: {
billIdList: [key], logs: [
bill: { {
exported: true, bodyshopid: bodyshop.id,
exported_at: new Date(), billid: key,
successful: false,
message: JSON.stringify(
failedTransactions.map((ft) => ft.errorMessage)
),
useremail: currentUser.email,
}, },
],
},
});
} else {
await insertExportLog({
variables: {
logs: [
{
bodyshopid: bodyshop.id,
billid: key,
successful: true,
useremail: currentUser.email,
},
],
},
});
const billUpdateResponse = await updateBill({
variables: {
billIdList: [key],
bill: {
exported: true,
exported_at: new Date(),
}, },
},
});
if (!!!billUpdateResponse.errors) {
notification.open({
type: "success",
key: "billsuccessexport",
message: t("bills.successes.exported"),
});
} else {
notification["error"]({
message: t("bills.errors.exporting", {
error: JSON.stringify(billUpdateResponse.error),
}),
}); });
if (!!!billUpdateResponse.errors) {
notification.open({
type: "success",
key: "billsuccessexport",
message: t("bills.successes.exported"),
});
} else {
notification["error"]({
message: t("bills.errors.exporting", {
error: JSON.stringify(billUpdateResponse.error),
}),
});
}
} }
} }
})() })()
@@ -171,8 +164,6 @@ export function PayableExportAll({
await Promise.all(proms); await Promise.all(proms);
if (!!completedCallback) completedCallback([]); if (!!completedCallback) completedCallback([]);
if (!!loadingCallback) loadingCallback(false); if (!!loadingCallback) loadingCallback(false);
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) refetch();
setLoading(false); setLoading(false);
}; };

View File

@@ -26,7 +26,6 @@ export function PayableExportButton({
disabled, disabled,
loadingCallback, loadingCallback,
setSelectedBills, setSelectedBills,
refetch,
}) { }) {
const { t } = useTranslation(); const { t } = useTranslation();
const [updateBill] = useMutation(UPDATE_BILLS); const [updateBill] = useMutation(UPDATE_BILLS);
@@ -44,7 +43,6 @@ export function PayableExportButton({
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) { if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) {
PartnerResponse = await axios.post(`/qbo/payables`, { PartnerResponse = await axios.post(`/qbo/payables`, {
bills: [billId], bills: [billId],
elgen: true,
}); });
} else { } else {
//Default is QBD //Default is QBD
@@ -102,72 +100,64 @@ export function PayableExportButton({
}), }),
}) })
); );
if (!(bodyshop.accountingconfig && bodyshop.accountingconfig.qbo)) { await insertExportLog({
//QBO Logs are handled server side. variables: {
await insertExportLog({ logs: [
variables: { {
logs: [ bodyshopid: bodyshop.id,
{ billid: billId,
bodyshopid: bodyshop.id, successful: false,
billid: billId, message: JSON.stringify(
successful: false, failedTransactions.map((ft) => ft.errorMessage)
message: JSON.stringify( ),
failedTransactions.map((ft) => ft.errorMessage) useremail: currentUser.email,
), },
useremail: currentUser.email, ],
}, },
], });
},
});
}
} }
if (successfulTransactions.length > 0) { if (successfulTransactions.length > 0) {
if (!(bodyshop.accountingconfig && bodyshop.accountingconfig.qbo)) { await insertExportLog({
//QBO Logs are handled server side. variables: {
await insertExportLog({ logs: [
variables: { {
logs: [ bodyshopid: bodyshop.id,
{ billid: billId,
bodyshopid: bodyshop.id, successful: true,
billid: billId, useremail: currentUser.email,
successful: true,
useremail: currentUser.email,
},
],
},
});
const billUpdateResponse = await updateBill({
variables: {
billIdList: successfulTransactions.map(
(st) =>
st[
bodyshop.accountingconfig && bodyshop.accountingconfig.qbo
? "billid"
: "id"
]
),
bill: {
exported: true,
exported_at: new Date(),
}, },
],
},
});
const billUpdateResponse = await updateBill({
variables: {
billIdList: successfulTransactions.map(
(st) =>
st[
bodyshop.accountingconfig && bodyshop.accountingconfig.qbo
? "billid"
: "id"
]
),
bill: {
exported: true,
exported_at: new Date(),
}, },
},
});
if (!!!billUpdateResponse.errors) {
notification.open({
type: "success",
key: "billsuccessexport",
message: t("bills.successes.exported"),
});
} else {
notification["error"]({
message: t("bills.errors.exporting", {
error: JSON.stringify(billUpdateResponse.error),
}),
}); });
if (!!!billUpdateResponse.errors) {
notification.open({
type: "success",
key: "billsuccessexport",
message: t("bills.successes.exported"),
});
} else {
notification["error"]({
message: t("bills.errors.exporting", {
error: JSON.stringify(billUpdateResponse.error),
}),
});
}
} }
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) refetch();
if (setSelectedBills) { if (setSelectedBills) {
setSelectedBills((selectedBills) => { setSelectedBills((selectedBills) => {
return selectedBills.filter((i) => i !== billId); return selectedBills.filter((i) => i !== billId);

View File

@@ -26,7 +26,6 @@ export function PaymentExportButton({
disabled, disabled,
loadingCallback, loadingCallback,
setSelectedPayments, setSelectedPayments,
refetch,
}) { }) {
const { t } = useTranslation(); const { t } = useTranslation();
const [updatePayment] = useMutation(UPDATE_PAYMENTS); const [updatePayment] = useMutation(UPDATE_PAYMENTS);
@@ -41,7 +40,6 @@ export function PaymentExportButton({
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) { if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) {
PartnerResponse = await axios.post(`/qbo/payments`, { PartnerResponse = await axios.post(`/qbo/payments`, {
payments: [paymentId], payments: [paymentId],
elgen: true,
}); });
} else { } else {
//Default is QBD //Default is QBD
@@ -102,68 +100,63 @@ export function PaymentExportButton({
}), }),
}) })
); );
if (!(bodyshop.accountingconfig && bodyshop.accountingconfig.qbo)) {
//QBO Logs are handled server side.
await insertExportLog({
variables: {
logs: [
{
bodyshopid: bodyshop.id,
paymentid: paymentId,
successful: false,
message: JSON.stringify(
failedTransactions.map((ft) => ft.errorMessage)
),
useremail: currentUser.email,
},
],
},
});
}
} else {
if (!(bodyshop.accountingconfig && bodyshop.accountingconfig.qbo)) {
//QBO Logs are handled server side.
await insertExportLog({
variables: {
logs: [
{
bodyshopid: bodyshop.id,
paymentid: paymentId,
successful: true,
useremail: currentUser.email,
},
],
},
});
const paymentUpdateResponse = await updatePayment({ await insertExportLog({
variables: { variables: {
paymentIdList: successfulTransactions.map( logs: [
(st) => {
st[ bodyshopid: bodyshop.id,
bodyshop.accountingconfig && bodyshop.accountingconfig.qbo paymentid: paymentId,
? "paymentid" successful: false,
: "id" message: JSON.stringify(
] failedTransactions.map((ft) => ft.errorMessage)
), ),
payment: { useremail: currentUser.email,
exportedat: new Date(),
}, },
],
},
});
} else {
await insertExportLog({
variables: {
logs: [
{
bodyshopid: bodyshop.id,
paymentid: paymentId,
successful: true,
useremail: currentUser.email,
},
],
},
});
const paymentUpdateResponse = await updatePayment({
variables: {
paymentIdList: successfulTransactions.map(
(st) =>
st[
bodyshop.accountingconfig && bodyshop.accountingconfig.qbo
? "paymentid"
: "id"
]
),
payment: {
exportedat: new Date(),
}, },
},
});
if (!!!paymentUpdateResponse.errors) {
notification.open({
type: "success",
key: "paymentsuccessexport",
message: t("payments.successes.exported"),
});
} else {
notification["error"]({
message: t("payments.errors.exporting", {
error: JSON.stringify(paymentUpdateResponse.error),
}),
}); });
if (!!!paymentUpdateResponse.errors) {
notification.open({
type: "success",
key: "paymentsuccessexport",
message: t("payments.successes.exported"),
});
} else {
notification["error"]({
message: t("payments.errors.exporting", {
error: JSON.stringify(paymentUpdateResponse.error),
}),
});
}
} }
if (setSelectedPayments) { if (setSelectedPayments) {
@@ -172,7 +165,7 @@ export function PaymentExportButton({
}); });
} }
} }
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) refetch();
if (!!loadingCallback) loadingCallback(false); if (!!loadingCallback) loadingCallback(false);
setLoading(false); setLoading(false);
}; };

View File

@@ -25,7 +25,6 @@ export function PaymentsExportAllButton({
disabled, disabled,
loadingCallback, loadingCallback,
completedCallback, completedCallback,
refetch
}) { }) {
const { t } = useTranslation(); const { t } = useTranslation();
const [updatePayments] = useMutation(UPDATE_PAYMENTS); const [updatePayments] = useMutation(UPDATE_PAYMENTS);
@@ -39,7 +38,6 @@ export function PaymentsExportAllButton({
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) { if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) {
PartnerResponse = await axios.post(`/qbo/payments`, { PartnerResponse = await axios.post(`/qbo/payments`, {
payments: paymentIds, payments: paymentIds,
elgen: true,
}); });
} else { } else {
let QbXmlResponse; let QbXmlResponse;
@@ -94,61 +92,54 @@ export function PaymentsExportAllButton({
}), }),
}) })
); );
if (!(bodyshop.accountingconfig && bodyshop.accountingconfig.qbo)) { await insertExportLog({
//QBO Logs are handled server side. variables: {
await insertExportLog({ logs: [
variables: { {
logs: [ bodyshopid: bodyshop.id,
{ paymentid: key,
bodyshopid: bodyshop.id, successful: false,
paymentid: key, message: JSON.stringify(
successful: false, failedTransactions.map((ft) => ft.errorMessage)
message: JSON.stringify( ),
failedTransactions.map((ft) => ft.errorMessage) useremail: currentUser.email,
),
useremail: currentUser.email,
},
],
},
});
}
} else {
if (!(bodyshop.accountingconfig && bodyshop.accountingconfig.qbo)) {
//QBO Logs are handled server side.
await insertExportLog({
variables: {
logs: [
{
bodyshopid: bodyshop.id,
paymentid: key,
successful: true,
useremail: currentUser.email,
},
],
},
});
const paymentUpdateResponse = await updatePayments({
variables: {
paymentIdList: [key],
payment: {
exportedat: new Date(),
}, },
],
},
});
} else {
await insertExportLog({
variables: {
logs: [
{
bodyshopid: bodyshop.id,
paymentid: key,
successful: true,
useremail: currentUser.email,
},
],
},
});
const paymentUpdateResponse = await updatePayments({
variables: {
paymentIdList: [key],
payment: {
exportedat: new Date(),
}, },
},
});
if (!!!paymentUpdateResponse.errors) {
notification.open({
type: "success",
key: "paymentsuccessexport",
message: t("payments.successes.exported"),
});
} else {
notification["error"]({
message: t("payments.errors.exporting", {
error: JSON.stringify(paymentUpdateResponse.error),
}),
}); });
if (!!!paymentUpdateResponse.errors) {
notification.open({
type: "success",
key: "paymentsuccessexport",
message: t("payments.successes.exported"),
});
} else {
notification["error"]({
message: t("payments.errors.exporting", {
error: JSON.stringify(paymentUpdateResponse.error),
}),
});
}
} }
} }
})() })()
@@ -157,7 +148,6 @@ export function PaymentsExportAllButton({
await Promise.all(proms); await Promise.all(proms);
if (!!completedCallback) completedCallback([]); if (!!completedCallback) completedCallback([]);
if (!!loadingCallback) loadingCallback(false); if (!!loadingCallback) loadingCallback(false);
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) refetch();
setLoading(false); setLoading(false);
}; };

View File

@@ -1,7 +1,6 @@
import { import {
CalendarOutlined, CalendarOutlined,
EyeFilled, EyeFilled,
DownloadOutlined,
PauseCircleOutlined, PauseCircleOutlined,
} from "@ant-design/icons"; } from "@ant-design/icons";
import { Card, Col, Row, Space } from "antd"; import { Card, Col, Row, Space } from "antd";
@@ -15,7 +14,6 @@ import ProductionSubletsManageComponent from "../production-sublets-manage/produ
import "./production-board-card.styles.scss"; import "./production-board-card.styles.scss";
import moment from "moment"; import moment from "moment";
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component"; import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
import JobPartsQueueCount from "../job-parts-queue-count/job-parts-queue-count.component";
export default function ProductionBoardCard( export default function ProductionBoardCard(
technician, technician,
@@ -159,16 +157,6 @@ export default function ProductionBoardCard(
</Row> </Row>
</Col> </Col>
)} */} )} */}
{cardSettings && cardSettings.actual_in && card.actual_in && (
<Col span={cardSettings && cardSettings.compact ? 24 : 12}>
<Space>
<DownloadOutlined />
<DateTimeFormatter format="MM/DD">
{card.actual_in}
</DateTimeFormatter>
</Space>
</Col>
)}
{cardSettings && {cardSettings &&
cardSettings.scheduled_completion && cardSettings.scheduled_completion &&
card.scheduled_completion && ( card.scheduled_completion && (
@@ -200,11 +188,6 @@ export default function ProductionBoardCard(
)} )}
</Col> </Col>
)} )}
{cardSettings && cardSettings.partsstatus && (
<Col span={24}>
<JobPartsQueueCount parts={card.joblines_status} />
</Col>
)}
</Row> </Row>
</Card> </Card>
); );

View File

@@ -97,13 +97,6 @@ export default function ProductionBoardKanbanCardSettings({
> >
<Switch /> <Switch />
</Form.Item> </Form.Item>
<Form.Item
valuePropName="checked"
label={t("production.labels.actual_in")}
name="actual_in"
>
<Switch />
</Form.Item>
</Col> </Col>
<Col span={12}> <Col span={12}>
<Form.Item <Form.Item
@@ -138,13 +131,6 @@ export default function ProductionBoardKanbanCardSettings({
> >
<Switch /> <Switch />
</Form.Item> </Form.Item>
<Form.Item
valuePropName="checked"
label={t("production.labels.partsstatus")}
name="partsstatus"
>
<Switch />
</Form.Item>
<Form.Item <Form.Item
valuePropName="checked" valuePropName="checked"
label={t("production.labels.stickyheader")} label={t("production.labels.stickyheader")}

View File

@@ -51,10 +51,7 @@ export function ProductionBoardKanbanComponent({
const { t } = useTranslation(); const { t } = useTranslation();
useEffect(() => { useEffect(() => {
const boardData = createBoardData( const boardData = createBoardData(
[ bodyshop.md_ro_statuses.production_statuses,
...bodyshop.md_ro_statuses.production_statuses,
...(bodyshop.md_ro_statuses.additional_board_statuses || []),
],
data, data,
filter filter
); );
@@ -64,7 +61,13 @@ export function ProductionBoardKanbanComponent({
}); });
setBoardLanes(boardData); setBoardLanes(boardData);
setIsMoving(false); setIsMoving(false);
}, [data, setBoardLanes, setIsMoving, bodyshop.md_ro_statuses, filter]); }, [
data,
setBoardLanes,
setIsMoving,
bodyshop.md_ro_statuses.production_statuses,
filter,
]);
const client = useApolloClient(); const client = useApolloClient();

View File

@@ -23,7 +23,6 @@ import ProductionlistColumnTouchTime from "./prodution-list-columns.touchtime.co
import ProductionListColumnComment from "./production-list-columns.comment.component"; import ProductionListColumnComment from "./production-list-columns.comment.component";
import ProductionListColumnPartsReceived from "./production-list-columns.partsreceived.component"; import ProductionListColumnPartsReceived from "./production-list-columns.partsreceived.component";
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component"; import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
import JobPartsQueueCount from "../job-parts-queue-count/job-parts-queue-count.component";
const r = ({ technician, state, activeStatuses, bodyshop }) => { const r = ({ technician, state, activeStatuses, bodyshop }) => {
return [ return [
@@ -491,14 +490,6 @@ const r = ({ technician, state, activeStatuses, bodyshop }) => {
<ProductionListColumnPartsReceived record={record} /> <ProductionListColumnPartsReceived record={record} />
), ),
}, },
{
title: i18n.t("jobs.fields.partsstatus"),
dataIndex: "partsstatus",
key: "partsstatus",
render: (text, record) => (
<JobPartsQueueCount parts={record.joblines_status} record={record} />
),
},
]; ];
}; };
export default r; export default r;

View File

@@ -21,11 +21,9 @@ import OwnerNameDisplay from "../owner-name-display/owner-name-display.component
import { connect } from "react-redux"; import { connect } from "react-redux";
import { createStructuredSelector } from "reselect"; import { createStructuredSelector } from "reselect";
import { setModalContext } from "../../redux/modals/modals.actions"; import { setModalContext } from "../../redux/modals/modals.actions";
import ScoreboardAddButton from "../job-scoreboard-add-button/job-scoreboard-add-button.component";
import { selectBodyshop } from "../../redux/user/user.selectors";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop, //currentUser: selectCurrentUser
}); });
const mapDispatchToProps = (dispatch) => ({ const mapDispatchToProps = (dispatch) => ({
setPrintCenterContext: (context) => setPrintCenterContext: (context) =>
@@ -36,11 +34,7 @@ export default connect(
mapDispatchToProps mapDispatchToProps
)(ProductionListDetail); )(ProductionListDetail);
export function ProductionListDetail({ export function ProductionListDetail({ jobs, setPrintCenterContext }) {
bodyshop,
jobs,
setPrintCenterContext,
}) {
const search = queryString.parse(useLocation().search); const search = queryString.parse(useLocation().search);
const history = useHistory(); const history = useHistory();
const { selected } = search; const { selected } = search;
@@ -65,7 +59,7 @@ export function ProductionListDetail({
<PageHeader <PageHeader
title={theJob.ro_number} title={theJob.ro_number}
extra={ extra={
<Space wrap> <Space>
<ProductionRemoveButton jobId={theJob.id} />{" "} <ProductionRemoveButton jobId={theJob.id} />{" "}
<Button <Button
onClick={() => { onClick={() => {
@@ -82,7 +76,6 @@ export function ProductionListDetail({
<PrinterFilled /> <PrinterFilled />
{t("jobs.actions.printCenter")} {t("jobs.actions.printCenter")}
</Button> </Button>
<ScoreboardAddButton job={data ? data.jobs_by_pk : {}} />
</Space> </Space>
} }
/> />
@@ -149,12 +142,11 @@ export function ProductionListDetail({
loading={loading} loading={loading}
data={data ? data.jobs_by_pk : null} data={data ? data.jobs_by_pk : null}
/> />
{!bodyshop.uselocalmediaserver && (
<JobDetailCardsDocumentsComponent <JobDetailCardsDocumentsComponent
loading={loading} loading={loading}
data={data ? data.jobs_by_pk : null} data={data ? data.jobs_by_pk : null}
/> />
)}
</div> </div>
)} )}
</Drawer> </Drawer>

View File

@@ -1,42 +1,13 @@
import React, { useState } from "react"; import React from "react";
import { Dropdown, Button, Table, Space, Card, Input } from "antd"; import { Dropdown, Button, Table, Space } from "antd";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import ScoreboardRemoveButton from "../scoreboard-remove-button/scorebard-remove-button.component"; import ScoreboardRemoveButton from "../scoreboard-remove-button/scorebard-remove-button.component";
import { DateFormatter } from "../../utils/DateFormatter"; import { DateFormatter } from "../../utils/DateFormatter";
import ScoreboardEntryEdit from "../scoreboard-entry-edit/scoreboard-entry-edit.component"; import ScoreboardEntryEdit from "../scoreboard-entry-edit/scoreboard-entry-edit.component";
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
export default function ScoreboardJobsList({ scoreBoardlist }) { export default function ScoreboardJobsList({ scoreBoardlist }) {
const { t } = useTranslation(); const { t } = useTranslation();
const [searchText, setSearchText] = useState("");
const jobs = scoreBoardlist
? searchText === ""
? scoreBoardlist
: scoreBoardlist.filter(
(sb) =>
(sb.job.ro_number || "")
.toString()
.toLowerCase()
.includes(searchText.toLowerCase()) ||
(sb.job.ownr_co_nm || "")
.toLowerCase()
.includes(searchText.toLowerCase()) ||
(sb.job.ownr_fn || "")
.toLowerCase()
.includes(searchText.toLowerCase()) ||
(sb.job.ownr_ln || "")
.toLowerCase()
.includes(searchText.toLowerCase()) ||
(sb.job.v_model_desc || "")
.toLowerCase()
.includes(searchText.toLowerCase()) ||
(sb.job.v_make_desc || "")
.toLowerCase()
.includes(searchText.toLowerCase())
)
: [];
const columns = [ const columns = [
{ {
@@ -49,25 +20,7 @@ export default function ScoreboardJobsList({ scoreBoardlist }) {
</Link> </Link>
), ),
}, },
{
title: t("jobs.fields.owner"),
dataIndex: "owner",
key: "owner",
ellipsis: true,
render: (text, record) => <OwnerNameDisplay ownerObject={record.job} />,
},
{
title: t("jobs.fields.vehicle"),
dataIndex: "vehicle",
key: "vehicle",
ellipsis: true,
render: (text, record) => (
<span>{`${record.job.v_model_yr || ""} ${
record.job.v_make_desc || ""
} ${record.job.v_model_desc || ""}`}</span>
),
},
{ {
title: t("scoreboard.fields.date"), title: t("scoreboard.fields.date"),
dataIndex: "date", dataIndex: "date",
@@ -98,29 +51,17 @@ export default function ScoreboardJobsList({ scoreBoardlist }) {
]; ];
const overlay = ( const overlay = (
<Card <div style={{ width: "50vw", padding: "1rem" }}>
style={{ maxWidth: "90vw", padding: "1rem" }}
onClick={(e) => e.stopPropagation()}
extra={
<Input.Search
placeholder={t("general.labels.search")}
onChange={(e) => {
setSearchText(e.target.value);
}}
value={searchText}
enterButton
onClick={(e) => e.stopPropagation()}
/>
}
>
<Table <Table
pagination={false} pagination={false}
columns={columns} columns={columns}
rowKey="id" rowKey="id"
dataSource={jobs} dataSource={scoreBoardlist}
scroll={{ x: true, y: "15rem" }}
style={{ padding: "1rem" }}
onClick={(e) => e.stopPropagation()} onClick={(e) => e.stopPropagation()}
/> />
</Card> </div>
); );
return ( return (

View File

@@ -25,6 +25,10 @@ export function ScoreboardTargetsTable({ bodyshop, scoreBoardlist }) {
const values = useMemo(() => { const values = useMemo(() => {
const dateHash = _.groupBy(scoreBoardlist, "date"); const dateHash = _.groupBy(scoreBoardlist, "date");
console.log(
"🚀 ~ file: scoreboard-targets-table.component.jsx ~ line 31 ~ values ~ dateHash",
dateHash
);
let ret = { let ret = {
todayBody: 0, todayBody: 0,
@@ -67,6 +71,10 @@ export function ScoreboardTargetsTable({ bodyshop, scoreBoardlist }) {
return ret; return ret;
}, [scoreBoardlist]); }, [scoreBoardlist]);
console.log(
"🚀 ~ file: scoreboard-targets-table.component.jsx ~ line 51 ~ values ~ values",
values
);
return ( return (
<Card <Card

View File

@@ -328,12 +328,6 @@ export function ShopEmployeesFormComponent({ bodyshop }) {
> >
<Input /> <Input />
</Form.Item> </Form.Item>
<Form.Item
label={t("employees.fields.external_id")}
name="external_id"
>
<Input />
</Form.Item>
</LayoutFormRow> </LayoutFormRow>
<Form.List name={["rates"]}> <Form.List name={["rates"]}>
{(fields, { add, remove, move }) => { {(fields, { add, remove, move }) => {

View File

@@ -584,25 +584,6 @@ export default function ShopInfoGeneral({ form }) {
> >
<Switch /> <Switch />
</Form.Item> </Form.Item>
<Form.Item
name={["uselocalmediaserver"]}
label={t("bodyshop.fields.uselocalmediaserver")}
valuePropName="checked"
>
<Switch />
</Form.Item>
<Form.Item
name={["localmediaserverhttp"]}
label={t("bodyshop.fields.localmediaserverhttp")}
>
<Input />
</Form.Item>
<Form.Item
name={["localmediaservernetwork"]}
label={t("bodyshop.fields.localmediaservernetwork")}
>
<Input />
</Form.Item>
</LayoutFormRow> </LayoutFormRow>
<LayoutFormRow grow header={t("bodyshop.labels.messagingpresets")}> <LayoutFormRow grow header={t("bodyshop.labels.messagingpresets")}>
<Form.List name={["md_messaging_presets"]}> <Form.List name={["md_messaging_presets"]}>
@@ -1412,60 +1393,6 @@ export default function ShopInfoGeneral({ form }) {
}} }}
</Form.List> </Form.List>
</LayoutFormRow> </LayoutFormRow>
<LayoutFormRow grow header={t("bodyshop.labels.md_to_emails")}>
<Form.List name={["md_to_emails"]}>
{(fields, { add, remove, move }) => {
return (
<div>
{fields.map((field, index) => (
<Form.Item key={field.key}>
<LayoutFormRow noDivider>
<Form.Item
label={t("general.labels.label")}
key={`${index}label`}
name={[field.name, "label"]}
>
<Input />
</Form.Item>
<Form.Item
label={t("bodyshop.labels.md_to_emails_emails")}
key={`${index}emails`}
name={[field.name, "emails"]}
>
<Select mode="tags" tokenSeparators={[",", ";"]} />
</Form.Item>
<Space>
<DeleteFilled
onClick={() => {
remove(field.name);
}}
/>
<FormListMoveArrows
move={move}
index={index}
total={fields.length}
/>
</Space>
</LayoutFormRow>
</Form.Item>
))}
<Form.Item>
<Button
type="dashed"
onClick={() => {
add();
}}
style={{ width: "100%" }}
>
{t("general.actions.add")}
</Button>
</Form.Item>
</div>
);
}}
</Form.List>
</LayoutFormRow>
</div> </div>
); );
} }

View File

@@ -165,18 +165,6 @@ export default function ShopInfoRbacComponent({ form }) {
> >
<InputNumber /> <InputNumber />
</Form.Item> </Form.Item>
<Form.Item
label={t("bodyshop.fields.rbac.jobs.list-ready")}
rules={[
{
required: true,
//message: t("general.validation.required"),
},
]}
name={["md_rbac", "jobs:list-ready"]}
>
<InputNumber />
</Form.Item>
<Form.Item <Form.Item
label={t("bodyshop.fields.rbac.jobs.admin")} label={t("bodyshop.fields.rbac.jobs.admin")}
rules={[ rules={[

View File

@@ -134,44 +134,6 @@ export function ShopInfoROStatusComponent({ bodyshop, form }) {
))} ))}
</Select> </Select>
</Form.Item> </Form.Item>
<Form.Item
name={["md_ro_statuses", "ready_statuses"]}
label={t("bodyshop.fields.statuses.ready_statuses")}
rules={[
{
//required: true,
//message: t("general.validation.required"),
type: "array",
},
]}
>
<Select mode="multiple">
{options.map((item, idx) => (
<Select.Option key={idx} value={item}>
{item}
</Select.Option>
))}
</Select>
</Form.Item>
<Form.Item
name={["md_ro_statuses", "additional_board_statuses"]}
label={t("bodyshop.fields.statuses.additional_board_statuses")}
rules={[
{
//required: true,
//message: t("general.validation.required"),
type: "array",
},
]}
>
<Select mode="multiple">
{options.map((item, idx) => (
<Select.Option key={idx} value={item}>
{item}
</Select.Option>
))}
</Select>
</Form.Item>
<LayoutFormRow noDivider> <LayoutFormRow noDivider>
<Form.Item <Form.Item
label={t("bodyshop.fields.statuses.default_scheduled")} label={t("bodyshop.fields.statuses.default_scheduled")}

View File

@@ -237,11 +237,7 @@ export function TimeTicketModalComponent({
return Promise.reject( return Promise.reject(
t("timetickets.validation.clockoffwithoutclockon") t("timetickets.validation.clockoffwithoutclockon")
); );
if ( if (value && !value.isSameOrAfter(clockon))
value &&
value.isSameOrAfter &&
!value.isSameOrAfter(clockon)
)
return Promise.reject( return Promise.reject(
t("timetickets.validation.clockoffmustbeafterclockon") t("timetickets.validation.clockoffmustbeafterclockon")
); );

View File

@@ -1,42 +0,0 @@
import { Button } from "antd";
import queryString from "query-string";
import React, { useState } from "react";
import { useLocation } from "react-router-dom";
import { GenerateDocument } from "../../utils/RenderTemplate";
import { TemplateList } from "../../utils/TemplateConstants";
import { useTranslation } from "react-i18next";
import moment from "moment";
const AttendanceCsv = TemplateList("special").attendance_detail_csv;
export default function TimeTicketsAttendanceTable() {
const searchParams = queryString.parse(useLocation().search);
const { start, end } = searchParams;
const { t } = useTranslation();
const [loading, setLoading] = useState(false);
const handleClick = async () => {
setLoading(true);
await GenerateDocument(
{
name: AttendanceCsv.key,
variables: {
start: start
? start
: moment().startOf("week").subtract(7, "days").format("YYYY-MM-DD"),
end: end ? end : moment().endOf("week").format("YYYY-MM-DD"),
},
},
{},
"text"
);
setLoading(false);
};
return (
<Button loading={loading} onClick={handleClick}>
{t("printcenter.special.attendance_detail_csv")}
</Button>
);
}

View File

@@ -86,7 +86,6 @@ export const QUERY_BILLS_BY_JOBID = gql`
job_line_id job_line_id
part_type part_type
cost cost
cm_received
jobline { jobline {
id id
part_type part_type
@@ -125,7 +124,7 @@ export const QUERY_BILLS_BY_JOBID = gql`
applicable_taxes applicable_taxes
deductedfromlbr deductedfromlbr
lbr_adjustment lbr_adjustment
jobline { jobline{
oem_partno oem_partno
part_type part_type
} }
@@ -165,7 +164,7 @@ export const QUERY_BILL_BY_PK = gql`
cost_center cost_center
quantity quantity
joblineid joblineid
jobline { jobline{
oem_partno oem_partno
part_type part_type
} }

View File

@@ -106,10 +106,6 @@ export const QUERY_BODYSHOP = gql`
last_name_first last_name_first
md_parts_order_comment md_parts_order_comment
bill_allow_post_to_closed bill_allow_post_to_closed
md_to_emails
uselocalmediaserver
localmediaserverhttp
localmediaservernetwork
employees { employees {
user_email user_email
id id
@@ -118,7 +114,6 @@ export const QUERY_BODYSHOP = gql`
last_name last_name
employee_number employee_number
rates rates
external_id
} }
} }
} }
@@ -214,10 +209,6 @@ export const UPDATE_SHOP = gql`
last_name_first last_name_first
md_parts_order_comment md_parts_order_comment
bill_allow_post_to_closed bill_allow_post_to_closed
md_to_emails
uselocalmediaserver
localmediaserverhttp
localmediaservernetwork
employees { employees {
id id
first_name first_name
@@ -226,7 +217,6 @@ export const UPDATE_SHOP = gql`
employee_number employee_number
rates rates
user_email user_email
external_id
} }
} }
} }

View File

@@ -25,7 +25,6 @@ export const QUERY_EMPLOYEE_BY_ID = gql`
rates rates
pin pin
user_email user_email
external_id
employee_vacations(order_by: { start: desc }) { employee_vacations(order_by: { start: desc }) {
id id
start start

View File

@@ -50,13 +50,25 @@ export const QUERY_PARTS_QUEUE = gql`
$limit: Int $limit: Int
$order: [jobs_order_by!] $order: [jobs_order_by!]
) { ) {
jobs_aggregate(where: { _and: [{ status: { _in: $statuses } }] }) { jobs_aggregate(
where: {
_and: [
{ status: { _in: $statuses } }
{ queued_for_parts: { _eq: true } }
]
}
) {
aggregate { aggregate {
count(distinct: true) count(distinct: true)
} }
} }
jobs( jobs(
where: { _and: [{ status: { _in: $statuses } }] } where: {
_and: [
{ status: { _in: $statuses } }
{ queued_for_parts: { _eq: true } }
]
}
offset: $offset offset: $offset
limit: $limit limit: $limit
order_by: $order order_by: $order
@@ -87,12 +99,6 @@ export const QUERY_PARTS_QUEUE = gql`
updated_at updated_at
vehicleid vehicleid
ownerid ownerid
queued_for_parts
joblines_status {
count
part_type
status
}
} }
} }
`; `;
@@ -845,11 +851,6 @@ export const QUERY_JOB_CARD_DETAILS = gql`
count count
status status
} }
joblines {
id
mod_lbr_ty
mod_lb_hrs
}
owner { owner {
id id
allow_text_message allow_text_message
@@ -1049,7 +1050,6 @@ export const UPDATE_JOB = gql`
production_vars production_vars
lbr_adjustments lbr_adjustments
suspended suspended
queued_for_parts
} }
} }
} }

View File

@@ -72,7 +72,7 @@ export const QUERY_PARTS_ORDER_OEC = gql`
part_type part_type
} }
job { job {
bodyshop { bodyshop{
shopname shopname
bill_tax_rates bill_tax_rates
} }
@@ -292,30 +292,6 @@ export const DELETE_PARTS_ORDER = gql`
} }
`; `;
export const DELETE_PARTS_ORDER_LINE = gql`
mutation DELETE_PARTS_ORDER_LINE($partsOrderLineId: uuid!) {
delete_parts_order_lines_by_pk(id: $partsOrderLineId) {
id
}
}
`;
export const MUTATION_UPDATE_PO_CM_REECEIVED = gql`
mutation MUTATION_UPDATE_PO_CM_REECEIVED(
$partsLineId: uuid!
$partsOrder: parts_order_lines_set_input
) {
update_parts_order_lines(
where: { id: { _eq: $partsLineId } }
_set: $partsOrder
) {
returning {
id
cm_received
}
}
}
`;
export const MUTATION_UPDATE_BO_ETA = gql` export const MUTATION_UPDATE_BO_ETA = gql`
mutation MUTATION_UPDATE_BO_ETA( mutation MUTATION_UPDATE_BO_ETA(
$partsLineId: uuid! $partsLineId: uuid!
@@ -363,36 +339,3 @@ export const MUTATION_BACKORDER_PART_LINE = gql`
} }
} }
`; `;
export const QUERY_UNRECEIVED_LINES = gql`
query QUERY_UNRECEIVED_LINES($jobId: uuid!, $vendorId: uuid!) {
parts_order_lines(
where: {
parts_order: { jobid: { _eq: $jobId }, vendorid: { _eq: $vendorId } }
cm_received: { _neq: true }
}
) {
cm_received
id
line_desc
quantity
act_price
cost
oem_partno
}
}
`;
export const MUTATION_MARK_RETURN_RECEIVED = gql`
mutation MUTATION_MARK_RETURN_RECEIVED($partsLineIds: [uuid!]!) {
update_parts_order_lines(
where: { id: { _in: $partsLineIds } }
_set: { cm_received: true }
) {
returning {
id
cm_received
}
}
}
`;

View File

@@ -13,12 +13,6 @@ export const SUBSCRIPTION_SCOREBOARD = gql`
job { job {
id id
ro_number ro_number
ownr_fn
ownr_ln
ownr_co_nm
v_make_desc
v_model_desc
v_model_yr
} }
} }
} }

View File

@@ -3,7 +3,7 @@ import * as Sentry from "@sentry/react";
import "antd/dist/antd.less"; import "antd/dist/antd.less";
import Dinero from "dinero.js"; import Dinero from "dinero.js";
import React from "react"; import React from "react";
import ReactDOM from "react-dom"; import { createRoot } from "react-dom/client";
import { Provider } from "react-redux"; import { Provider } from "react-redux";
import { BrowserRouter } from "react-router-dom"; import { BrowserRouter } from "react-router-dom";
import { PersistGate } from "redux-persist/integration/react"; import { PersistGate } from "redux-persist/integration/react";
@@ -39,7 +39,9 @@ if (process.env.NODE_ENV !== "development") {
}); });
} }
ReactDOM.render( const container = document.getElementById("root");
const root = createRoot(container); // createRoot(container!) if you use TypeScript
root.render(
<Provider store={store}> <Provider store={store}>
<BrowserRouter> <BrowserRouter>
<PersistGate <PersistGate
@@ -49,48 +51,7 @@ ReactDOM.render(
<AppContainer /> <AppContainer />
</PersistGate> </PersistGate>
</BrowserRouter> </BrowserRouter>
</Provider>, </Provider>
document.getElementById("root")
); );
// const onServiceWorkerUpdate = (registration) => {
// console.log("onServiceWorkerUpdate", registration);
// const btn = (
// <Space flex>
// <Button
// onClick={async () => {
// window.open("https://imex-online.noticeable.news/", "_blank");
// }}
// >
// {i18n.t("general.actions.viewreleasenotes")}
// </Button>
// <Button
// type="primary"
// onClick={async () => {
// if (registration && registration.waiting) {
// await registration.unregister();
// // Makes Workbox call skipWaiting()
// registration.waiting.postMessage({ type: "SKIP_WAITING" });
// // Once the service worker is unregistered, we can reload the page to let
// // the browser download a fresh copy of our app (invalidating the cache)
// window.location.reload();
// }
// }}
// >
// {i18n.t("general.actions.refresh")}
// </Button>
// </Space>
// );
// notification.open({
// icon: <AlertOutlined />,
// message: i18n.t("general.messages.newversiontitle"),
// description: i18n.t("general.messages.newversionmessage"),
// duration: 0,
// btn,
// key: "updateavailable",
// });
// };
// serviceWorkerRegistration.register({ onUpdate: onServiceWorkerUpdate });
reportWebVitals(); reportWebVitals();

View File

@@ -1,9 +1,9 @@
import React from "react"; import React from 'react';
import { Button, Space } from "antd"; import { Button } from 'antd';
import { DownOutlined } from "@ant-design/icons"; import { DownOutlined } from '@ant-design/icons';
import QueueAnim from "rc-queue-anim"; import QueueAnim from 'rc-queue-anim';
import TweenOne from "rc-tween-one"; import TweenOne from 'rc-tween-one';
import { isImg } from "./utils"; import { isImg } from './utils';
class Banner extends React.PureComponent { class Banner extends React.PureComponent {
render() { render() {
@@ -15,12 +15,12 @@ class Banner extends React.PureComponent {
<div {...currentProps} {...dataSource.wrapper}> <div {...currentProps} {...dataSource.wrapper}>
<QueueAnim <QueueAnim
key="QueueAnim" key="QueueAnim"
type={["bottom", "top"]} type={['bottom', 'top']}
delay={200} delay={200}
{...dataSource.textWrapper} {...dataSource.textWrapper}
> >
<div key="title" {...dataSource.title}> <div key="title" {...dataSource.title}>
{typeof dataSource.title.children === "string" && {typeof dataSource.title.children === 'string' &&
dataSource.title.children.match(isImg) ? ( dataSource.title.children.match(isImg) ? (
<img src={dataSource.title.children} width="100%" alt="img" /> <img src={dataSource.title.children} width="100%" alt="img" />
) : ( ) : (
@@ -30,18 +30,13 @@ class Banner extends React.PureComponent {
<div key="content" {...dataSource.content}> <div key="content" {...dataSource.content}>
{dataSource.content.children} {dataSource.content.children}
</div> </div>
<Space wrap> <Button ghost key="button" {...dataSource.button}>
<Button ghost key="button" {...dataSource.button}> {dataSource.button.children}
{dataSource.button.children} </Button>
</Button>
<Button type="primary" key="button2" {...dataSource.button2}>
{dataSource.button2.children}
</Button>
</Space>
</QueueAnim> </QueueAnim>
<TweenOne <TweenOne
animation={{ animation={{
y: "-=20", y: '-=20',
yoyo: true, yoyo: true,
repeat: -1, repeat: -1,
duration: 1000, duration: 1000,

View File

@@ -74,26 +74,26 @@ export const Nav00DataSource = {
// }, // },
// ], // ],
// }, // },
// { {
// name: "item1", name: "item1",
// className: "header0-item", className: "header0-item",
// children: { children: {
// href: "#", href: "#",
// children: [ children: [
// { children: i18n.t("landing.labels.features"), name: "text" }, { children: i18n.t("landing.labels.features"), name: "text" },
// ], ],
// }, },
// }, },
// { {
// name: "item2", name: "item2",
// className: "header0-item", className: "header0-item",
// children: { children: {
// href: "#", href: "#",
// children: [ children: [
// { children: i18n.t("landing.labels.pricing"), name: "text" }, { children: i18n.t("landing.labels.pricing"), name: "text" },
// ], ],
// }, },
// }, },
{ {
name: "item3", name: "item3",
className: "header0-item", className: "header0-item",
@@ -124,12 +124,7 @@ export const Banner00DataSource = {
button: { button: {
className: "banner0-button", className: "banner0-button",
children: i18n.t("landing.hero.button"), children: i18n.t("landing.hero.button"),
href: "https://imexsystems.ca/products/imex-online", href: "https://imexsystems.ca",
},
button2: {
className: "banner0-button2",
children: i18n.t("landing.labels.managemyshop"),
href: "/signin",
}, },
}; };
export const Content40DataSource = { export const Content40DataSource = {
@@ -1038,22 +1033,22 @@ export const Footer10DataSource = {
childWrapper: { childWrapper: {
children: [ children: [
{ {
href: "https://imexsystems.ca/privacy", href: "/privacy",
name: "link0", name: "link0",
children: i18n.t("landing.footer.company.privacypolicy"), children: i18n.t("landing.footer.company.privacypolicy"),
}, },
// { {
// href: "/about", href: "/about",
// name: "link1", name: "link1",
// children: i18n.t("landing.footer.company.about"), children: i18n.t("landing.footer.company.about"),
// }, },
{ {
href: "/disclaimer", href: "/disclaimer",
name: "link2", name: "link2",
children: i18n.t("landing.footer.company.disclaimers"), children: i18n.t("landing.footer.company.disclaimers"),
}, },
{ {
href: "https://imexsystems.ca/schedule-a-demo/", href: "https://thinkimex.com",
name: "link3", name: "link3",
children: i18n.t("landing.footer.company.contact"), children: i18n.t("landing.footer.company.contact"),
}, },
@@ -1068,7 +1063,7 @@ export const Footer10DataSource = {
className: "copyright", className: "copyright",
children: ( children: (
<span> <span>
©2022 <a href="http://imexsystems.ca">ImEX Systems</a> used under ©2021 <a href="http://imexsystems.ca">ImEX Systems</a> used under
license. license.
</span> </span>
), ),

View File

@@ -4,27 +4,27 @@ import { enquireScreen } from "enquire-js";
import React from "react"; import React from "react";
import Banner0 from "./Banner0"; import Banner0 from "./Banner0";
// import Content4 from "./Content4"; // import Content4 from "./Content4";
//import Content0 from "./Content0"; import Content0 from "./Content0";
//import Content1 from "./Content1"; import Content1 from "./Content1";
import { import {
Banner00DataSource, Banner00DataSource,
// Content40DataSource, // Content40DataSource,
//Content00DataSource, Content00DataSource,
//Content10DataSource, Content10DataSource,
// Pricing11DataSource, // Pricing11DataSource,
// Content30DataSource, // Content30DataSource,
// Content120DataSource, // Content120DataSource,
Footer10DataSource, Footer10DataSource,
// Nav00DataSource, Nav00DataSource,
//Pricing20DataSource, Pricing20DataSource,
} from "./data.source"; } from "./data.source";
// import Pricing1 from "./Pricing1"; // import Pricing1 from "./Pricing1";
// import Content3 from "./Content3"; // import Content3 from "./Content3";
// import Content12 from "./Content12"; // import Content12 from "./Content12";
import Footer1 from "./Footer1"; import Footer1 from "./Footer1";
import "./less/antMotionStyle.less"; import "./less/antMotionStyle.less";
// import Nav0 from "./Nav0"; import Nav0 from "./Nav0";
//import Pricing2 from "./Pricing2"; import Pricing2 from "./Pricing2";
let isMobile; let isMobile;
enquireScreen((b) => { enquireScreen((b) => {
@@ -62,64 +62,64 @@ export default class Home extends React.Component {
render() { render() {
const children = [ const children = [
// <Nav0 <Nav0
// id="Nav0_0" id="Nav0_0"
// key="Nav0_0" key="Nav0_0"
// dataSource={Nav00DataSource} dataSource={Nav00DataSource}
// isMobile={this.state.isMobile} isMobile={this.state.isMobile}
// />, />,
<Banner0 <Banner0
id="Banner0_0" id="Banner0_0"
key="Banner0_0" key="Banner0_0"
dataSource={Banner00DataSource} dataSource={Banner00DataSource}
isMobile={this.state.isMobile} isMobile={this.state.isMobile}
/>, />,
// ...(process.env.NODE_ENV !== "production" ...(process.env.NODE_ENV !== "production"
// ? [ ? [
// // <Content4 // <Content4
// // id="Content4_0" // id="Content4_0"
// // key="Content4_0" // key="Content4_0"
// // dataSource={Content40DataSource} // dataSource={Content40DataSource}
// // isMobile={this.state.isMobile} // isMobile={this.state.isMobile}
// // />, // />,
// <Content1 <Content1
// id="Content1_0" id="Content1_0"
// key="Content1_0" key="Content1_0"
// dataSource={Content10DataSource} dataSource={Content10DataSource}
// isMobile={this.state.isMobile} isMobile={this.state.isMobile}
// />, />,
// <Content0 <Content0
// id="Content0_0" id="Content0_0"
// key="Content0_0" key="Content0_0"
// dataSource={Content00DataSource} dataSource={Content00DataSource}
// isMobile={this.state.isMobile} isMobile={this.state.isMobile}
// />, />,
// <Pricing2 <Pricing2
// id="Pricing2_0" id="Pricing2_0"
// key="Pricing2_0" key="Pricing2_0"
// dataSource={Pricing20DataSource} dataSource={Pricing20DataSource}
// isMobile={this.state.isMobile} isMobile={this.state.isMobile}
// />, />,
// // <Pricing1 // <Pricing1
// // id="Pricing1_1" // id="Pricing1_1"
// // key="Pricing1_1" // key="Pricing1_1"
// // dataSource={Pricing11DataSource} // dataSource={Pricing11DataSource}
// // isMobile={this.state.isMobile} // isMobile={this.state.isMobile}
// // />, // />,
// // <Content3 // <Content3
// // id="Content3_0" // id="Content3_0"
// // key="Content3_0" // key="Content3_0"
// // dataSource={Content30DataSource} // dataSource={Content30DataSource}
// // isMobile={this.state.isMobile} // isMobile={this.state.isMobile}
// // />, // />,
// // <Content12 // <Content12
// // id="Content12_0" // id="Content12_0"
// // key="Content12_0" // key="Content12_0"
// // dataSource={Content120DataSource} // dataSource={Content120DataSource}
// // isMobile={this.state.isMobile} // isMobile={this.state.isMobile}
// // />, // />,
// ] ]
// : []), : []),
<Footer1 <Footer1
id="Footer1_0" id="Footer1_0"
key="Footer1_0" key="Footer1_0"

View File

@@ -6,7 +6,7 @@
position: relative; position: relative;
text-align: center; text-align: center;
border-color: #666; border-color: #666;
background-image: url("../../assets/banner4.jpg"); background-image: url("../../assets/banner1.jpeg");
background-size: cover; background-size: cover;
background-attachment: fixed; background-attachment: fixed;
background-position: center; background-position: center;
@@ -60,28 +60,6 @@
width: auto; width: auto;
} }
} }
& &-button2 {
border: 1px solid #fff;
color: #fff;
// background: transparent;
box-shadow: 0 0 0 transparent;
font-size: 16px;
height: 40px;
transition: background 0.45s @ease-out, box-shadow 0.45s @ease-out;
&:hover {
color: #fff;
border-color: #fff;
background: rgba(255, 255, 255, 0.1);
box-shadow: 0 0 10px rgba(50, 250, 255, 0.75);
}
&:focus {
color: #fff;
border-color: #fff;
}
&.queue-anim-leaving {
width: auto;
}
}
& &-icon { & &-icon {
bottom: 20px; bottom: 20px;
font-size: 24px; font-size: 24px;

View File

@@ -45,7 +45,7 @@ export function AccountingPayablesContainer({
checkPartnerStatus(bodyshop, true); checkPartnerStatus(bodyshop, true);
}, [t, setBreadcrumbs, setSelectedHeader, bodyshop]); }, [t, setBreadcrumbs, setSelectedHeader, bodyshop]);
const { loading, error, data, refetch } = useQuery(QUERY_BILLS_FOR_EXPORT, { const { loading, error, data } = useQuery(QUERY_BILLS_FOR_EXPORT, {
fetchPolicy: "network-only", fetchPolicy: "network-only",
nextFetchPolicy: "network-only", nextFetchPolicy: "network-only",
}); });
@@ -73,7 +73,6 @@ export function AccountingPayablesContainer({
<AccountingPayablesTable <AccountingPayablesTable
loadaing={loading} loadaing={loading}
bills={data ? data.bills : []} bills={data ? data.bills : []}
refetch={refetch}
/> />
</RbacWrapper> </RbacWrapper>
</div> </div>

View File

@@ -44,13 +44,10 @@ export function AccountingPaymentsContainer({
checkPartnerStatus(bodyshop, true); checkPartnerStatus(bodyshop, true);
}, [t, setBreadcrumbs, setSelectedHeader, bodyshop]); }, [t, setBreadcrumbs, setSelectedHeader, bodyshop]);
const { loading, error, data, refetch } = useQuery( const { loading, error, data } = useQuery(QUERY_PAYMENTS_FOR_EXPORT, {
QUERY_PAYMENTS_FOR_EXPORT, fetchPolicy: "network-only",
{ nextFetchPolicy: "network-only",
fetchPolicy: "network-only", });
nextFetchPolicy: "network-only",
}
);
if (error) return <AlertComponent message={error.message} type="error" />; if (error) return <AlertComponent message={error.message} type="error" />;
const noPath = const noPath =
@@ -73,7 +70,6 @@ export function AccountingPaymentsContainer({
<AccountingPaymentsTable <AccountingPaymentsTable
loadaing={loading} loadaing={loading}
payments={data ? data.payments : []} payments={data ? data.payments : []}
refetch={refetch}
/> />
</RbacWrapper> </RbacWrapper>
</div> </div>

View File

@@ -44,7 +44,7 @@ export function AccountingReceivablesContainer({
checkPartnerStatus(bodyshop, true); checkPartnerStatus(bodyshop, true);
}, [t, setBreadcrumbs, setSelectedHeader, bodyshop]); }, [t, setBreadcrumbs, setSelectedHeader, bodyshop]);
const { loading, error, data, refetch } = useQuery(QUERY_JOBS_FOR_EXPORT, { const { loading, error, data } = useQuery(QUERY_JOBS_FOR_EXPORT, {
variables: { variables: {
invoicedStatus: bodyshop.md_ro_statuses.default_invoiced || "Invoiced*", invoicedStatus: bodyshop.md_ro_statuses.default_invoiced || "Invoiced*",
}, },
@@ -75,7 +75,6 @@ export function AccountingReceivablesContainer({
<AccountingReceivablesTable <AccountingReceivablesTable
loadaing={loading} loadaing={loading}
jobs={data ? data.jobs : []} jobs={data ? data.jobs : []}
refetch={refetch}
/> />
</RbacWrapper> </RbacWrapper>
</div> </div>

View File

@@ -6,7 +6,6 @@ import Icon, {
PrinterFilled, PrinterFilled,
ToolFilled, ToolFilled,
HistoryOutlined, HistoryOutlined,
SyncOutlined,
} from "@ant-design/icons"; } from "@ant-design/icons";
import { import {
Button, Button,
@@ -50,7 +49,6 @@ import { selectBodyshop } from "../../redux/user/user.selectors";
import JobAuditTrail from "../../components/job-audit-trail/job-audit-trail.component"; import JobAuditTrail from "../../components/job-audit-trail/job-audit-trail.component";
import AuditTrailMapping from "../../utils/AuditTrailMappings"; import AuditTrailMapping from "../../utils/AuditTrailMappings";
import { insertAuditTrail } from "../../redux/application/application.actions"; import { insertAuditTrail } from "../../redux/application/application.actions";
import JobsDocumentsLocalGallery from "../../components/jobs-documents-local-gallery/jobs-documents-local-gallery.container";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop, bodyshop: selectBodyshop,
@@ -63,7 +61,6 @@ const mapDispatchToProps = (dispatch) => ({
dispatch(insertAuditTrail({ jobid, operation })), dispatch(insertAuditTrail({ jobid, operation })),
}); });
export function JobsDetailPage({ export function JobsDetailPage({
bodyshop,
setPrintCenterContext, setPrintCenterContext,
jobRO, jobRO,
job, job,
@@ -181,15 +178,6 @@ export function JobsDetailPage({
const menuExtra = ( const menuExtra = (
<Space wrap> <Space wrap>
<Button
onClick={() => {
refetch();
}}
key="refresh"
>
<SyncOutlined />
{t("general.labels.refresh")}
</Button>
<JobsChangeStatus job={job} /> <JobsChangeStatus job={job} />
<JobSyncButton job={job} /> <JobSyncButton job={job} />
<Button <Button
@@ -346,11 +334,7 @@ export function JobsDetailPage({
} }
key="documents" key="documents"
> >
{bodyshop.uselocalmediaserver ? ( <JobsDocumentsGalleryContainer jobId={job.id} />
<JobsDocumentsLocalGallery job={job} />
) : (
<JobsDocumentsGalleryContainer jobId={job.id} />
)}
</Tabs.TabPane> </Tabs.TabPane>
<Tabs.TabPane <Tabs.TabPane
tab={ tab={

View File

@@ -1,36 +0,0 @@
import React, { useEffect } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import JobDetailCards from "../../components/job-detail-cards/job-detail-cards.component";
import JobsReadyList from "../../components/jobs-ready-list/jobs-ready-list.component";
import RbacWrapper from "../../components/rbac-wrapper/rbac-wrapper.component";
import {
setBreadcrumbs,
setSelectedHeader,
} from "../../redux/application/application.actions";
const mapDispatchToProps = (dispatch) => ({
setBreadcrumbs: (breadcrumbs) => dispatch(setBreadcrumbs(breadcrumbs)),
setSelectedHeader: (key) => dispatch(setSelectedHeader(key)),
});
export function JobsReadyPage({ setBreadcrumbs, setSelectedHeader }) {
const { t } = useTranslation();
useEffect(() => {
document.title = t("titles.readyjobs");
setSelectedHeader("readyjobs");
setBreadcrumbs([
{ link: "/manage/jobs", label: t("titles.bc.jobs-ready") },
]);
}, [t, setBreadcrumbs, setSelectedHeader]);
return (
<RbacWrapper action="jobs:list-ready">
<JobsReadyList />
<JobDetailCards />
</RbacWrapper>
);
}
export default connect(null, mapDispatchToProps)(JobsReadyPage);

View File

@@ -127,7 +127,6 @@ const AccountingPayments = lazy(() =>
import("../accounting-payments/accounting-payments.container") import("../accounting-payments/accounting-payments.container")
); );
const AllJobs = lazy(() => import("../jobs-all/jobs-all.container")); const AllJobs = lazy(() => import("../jobs-all/jobs-all.container"));
const ReadyJobs = lazy(() => import("../jobs-ready/jobs-ready.page"));
const JobsClose = lazy(() => import("../jobs-close/jobs-close.container")); const JobsClose = lazy(() => import("../jobs-close/jobs-close.container"));
const JobsAdmin = lazy(() => import("../jobs-admin/jobs-admin.page")); const JobsAdmin = lazy(() => import("../jobs-admin/jobs-admin.page"));
const TempDocs = lazy(() => const TempDocs = lazy(() =>
@@ -241,7 +240,6 @@ export function Manage({ match, conflict, bodyshop }) {
component={JobsAdmin} component={JobsAdmin}
/> />
<Route exact path={`${match.path}/jobs/all`} component={AllJobs} /> <Route exact path={`${match.path}/jobs/all`} component={AllJobs} />
<Route exact path={`${match.path}/jobs/ready`} component={ReadyJobs} />
<Route <Route
exact exact
path={`${match.path}/jobs/new`} path={`${match.path}/jobs/new`}

View File

@@ -1,22 +1,23 @@
import { SyncOutlined } from "@ant-design/icons"; import { SyncOutlined } from "@ant-design/icons";
import { useQuery } from "@apollo/client"; import { useQuery } from "@apollo/client";
import { Button, Card, Input, Space, Table } from "antd"; import { Button, Card, Input, Space, Table } from "antd";
import _ from "lodash";
import queryString from "query-string";
import React, { useState } from "react"; import React, { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { Link, useHistory, useLocation } from "react-router-dom"; import { Link, useHistory } from "react-router-dom";
import { createStructuredSelector } from "reselect"; import { createStructuredSelector } from "reselect";
import AlertComponent from "../../components/alert/alert.component"; import AlertComponent from "../../components/alert/alert.component";
import JobPartsQueueCount from "../../components/job-parts-queue-count/job-parts-queue-count.component";
import JobRemoveFromPartsQueue from "../../components/job-remove-from-parst-queue/job-remove-from-parts-queue.component"; import JobRemoveFromPartsQueue from "../../components/job-remove-from-parst-queue/job-remove-from-parts-queue.component";
import OwnerNameDisplay from "../../components/owner-name-display/owner-name-display.component";
import { QUERY_PARTS_QUEUE } from "../../graphql/jobs.queries"; import { QUERY_PARTS_QUEUE } from "../../graphql/jobs.queries";
import { selectBodyshop } from "../../redux/user/user.selectors"; import { selectBodyshop } from "../../redux/user/user.selectors";
import { onlyUnique } from "../../utils/arrayHelper"; import { onlyUnique } from "../../utils/arrayHelper";
import CurrencyFormatter from "../../utils/CurrencyFormatter";
import { TimeAgoFormatter } from "../../utils/DateFormatter"; import { TimeAgoFormatter } from "../../utils/DateFormatter";
import { alphaSort, dateSort } from "../../utils/sorters"; import { alphaSort } from "../../utils/sorters";
import { useLocation } from "react-router-dom";
import queryString from "query-string";
import _ from "lodash";
import OwnerNameDisplay from "../../components/owner-name-display/owner-name-display.component";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop, bodyshop: selectBodyshop,
@@ -24,25 +25,20 @@ const mapStateToProps = createStructuredSelector({
export function PartsQueuePageComponent({ bodyshop }) { export function PartsQueuePageComponent({ bodyshop }) {
const searchParams = queryString.parse(useLocation().search); const searchParams = queryString.parse(useLocation().search);
const { const { page, sortcolumn, sortorder, statusFilters } = searchParams;
//page,
sortcolumn,
sortorder,
statusFilters,
} = searchParams;
const history = useHistory(); const history = useHistory();
const { loading, error, data, refetch } = useQuery(QUERY_PARTS_QUEUE, { const { loading, error, data, refetch } = useQuery(QUERY_PARTS_QUEUE, {
fetchPolicy: "network-only", fetchPolicy: "network-only",
nextFetchPolicy: "network-only", nextFetchPolicy: "network-only",
variables: { variables: {
// offset: page ? (page - 1) * 25 : 0, offset: page ? (page - 1) * 25 : 0,
// limit: 25, limit: 25,
statuses: (statusFilters && JSON.parse(statusFilters)) || statuses: (statusFilters && JSON.parse(statusFilters)) ||
bodyshop.md_ro_statuses.active_statuses || ["Open", "Open*"], bodyshop.md_ro_statuses.active_statuses || ["Open", "Open*"],
order: [ order: [
{ {
[sortcolumn || "ro_number"]: sortorder [sortcolumn || "updated_at"]: sortorder
? sortorder === "descend" ? sortorder === "descend"
? "desc" ? "desc"
: "asc" : "asc"
@@ -89,7 +85,7 @@ export function PartsQueuePageComponent({ bodyshop }) {
: []; : [];
const handleTableChange = (pagination, filters, sorter) => { const handleTableChange = (pagination, filters, sorter) => {
// searchParams.page = pagination.current; searchParams.page = pagination.current;
searchParams.sortcolumn = sorter.columnKey; searchParams.sortcolumn = sorter.columnKey;
searchParams.sortorder = sorter.order; searchParams.sortorder = sorter.order;
if (filters.status) { if (filters.status) {
@@ -118,10 +114,10 @@ export function PartsQueuePageComponent({ bodyshop }) {
}, },
{ {
title: t("jobs.fields.owner"), title: t("jobs.fields.owner"),
dataIndex: "ownr_ln", dataIndex: "owner",
key: "ownr_ln", key: "owner",
sorter: (a, b) => alphaSort(a.ownr_ln, b.ownr_ln), // sorter: (a, b) => alphaSort(a.ownr_ln, b.ownr_ln),
sortOrder: sortcolumn === "ownr_ln" && sortorder, // sortOrder: sortcolumn === "owner" && sortorder,
render: (text, record) => { render: (text, record) => {
return record.ownerid ? ( return record.ownerid ? (
<Link to={"/manage/owners/" + record.ownerid}> <Link to={"/manage/owners/" + record.ownerid}>
@@ -177,16 +173,16 @@ export function PartsQueuePageComponent({ bodyshop }) {
); );
}, },
}, },
// { {
// title: t("vehicles.fields.plate_no"), title: t("vehicles.fields.plate_no"),
// dataIndex: "plate_no", dataIndex: "plate_no",
// key: "plate_no", key: "plate_no",
// sorter: (a, b) => alphaSort(a.plate_no, b.plate_no), sorter: (a, b) => alphaSort(a.plate_no, b.plate_no),
// sortOrder: sortcolumn === "plate_no" && sortorder, sortOrder: sortcolumn === "plate_no" && sortorder,
// render: (text, record) => { render: (text, record) => {
// return record.plate_no ? record.plate_no : ""; return record.plate_no ? record.plate_no : "";
// }, },
// }, },
{ {
title: t("jobs.fields.clm_no"), title: t("jobs.fields.clm_no"),
dataIndex: "clm_no", dataIndex: "clm_no",
@@ -202,49 +198,34 @@ export function PartsQueuePageComponent({ bodyshop }) {
); );
}, },
}, },
// { {
// title: t("jobs.fields.clm_total"), title: t("jobs.fields.clm_total"),
// dataIndex: "clm_total", dataIndex: "clm_total",
// key: "clm_total", key: "clm_total",
// sorter: (a, b) => a.clm_total - b.clm_total, sorter: (a, b) => a.clm_total - b.clm_total,
// sortOrder: sortcolumn === "clm_total" && sortorder, sortOrder: sortcolumn === "clm_total" && sortorder,
// render: (text, record) => { render: (text, record) => {
// return record.clm_total ? ( return record.clm_total ? (
// <CurrencyFormatter>{record.clm_total}</CurrencyFormatter> <CurrencyFormatter>{record.clm_total}</CurrencyFormatter>
// ) : ( ) : (
// t("general.labels.unknown") t("general.labels.unknown")
// ); );
// }, },
// }, },
{ {
title: t("jobs.fields.updated_at"), title: t("jobs.fields.updated_at"),
dataIndex: "updated_at", dataIndex: "updated_at",
key: "updated_at", key: "updated_at",
sorter: (a, b) => dateSort(a.updated_at, b.updated_at),
sortOrder: sortcolumn === "updated_at" && sortorder,
render: (text, record) => ( render: (text, record) => (
<TimeAgoFormatter>{record.updated_at}</TimeAgoFormatter> <TimeAgoFormatter>{record.updated_at}</TimeAgoFormatter>
), ),
}, },
{ {
title: t("jobs.fields.partsstatus"), title: t("general.labels.actions"),
dataIndex: "partsstatus", dataIndex: "actions",
key: "partsstatus", key: "actions",
render: (text, record) => ( render: (text, record) => (
<JobPartsQueueCount parts={record.joblines_status} /> <JobRemoveFromPartsQueue jobId={record.id} refetch={refetch} />
),
},
{
title: t("jobs.fields.queued_for_parts"),
dataIndex: "queued_for_parts",
key: "queued_for_parts",
sorter: (a, b) => a.queued_for_parts - b.queued_for_parts,
sortOrder: sortcolumn === "queued_for_parts" && sortorder,
render: (text, record) => (
<JobRemoveFromPartsQueue
checked={record.queued_for_parts}
jobId={record.id}
/>
), ),
}, },
]; ];
@@ -272,9 +253,9 @@ export function PartsQueuePageComponent({ bodyshop }) {
loading={loading} loading={loading}
pagination={{ pagination={{
position: "top", position: "top",
pageSize: 50, pageSize: 25,
// current: parseInt(page || 1), current: parseInt(page || 1),
// total: data && data.jobs_aggregate.aggregate.count, total: data && data.jobs_aggregate.aggregate.count,
}} }}
columns={columns} columns={columns}
rowKey="id" rowKey="id"

View File

@@ -5,34 +5,15 @@ import JobsDocumentsComponent from "../../components/jobs-documents-gallery/jobs
import LoadingSpinner from "../../components/loading-spinner/loading-spinner.component"; import LoadingSpinner from "../../components/loading-spinner/loading-spinner.component";
import { QUERY_TEMPORARY_DOCS } from "../../graphql/documents.queries"; import { QUERY_TEMPORARY_DOCS } from "../../graphql/documents.queries";
import { connect } from "react-redux"; export default function TemporaryDocsComponent() {
import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors";
import JobsDocumentsLocalGallery from "../../components/jobs-documents-local-gallery/jobs-documents-local-gallery.container";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
});
const mapDispatchToProps = (dispatch) => ({
//setUserLanguage: language => dispatch(setUserLanguage(language))
});
export default connect(
mapStateToProps,
mapDispatchToProps
)(TemporaryDocsComponent);
export function TemporaryDocsComponent({ bodyshop }) {
const { loading, error, data, refetch } = useQuery(QUERY_TEMPORARY_DOCS, { const { loading, error, data, refetch } = useQuery(QUERY_TEMPORARY_DOCS, {
fetchPolicy: "network-only", fetchPolicy: "network-only",
nextFetchPolicy: "network-only", nextFetchPolicy: "network-only",
skip: bodyshop.uselocalmediaserver,
}); });
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" />;
if (bodyshop.uselocalmediaserver) {
return <JobsDocumentsLocalGallery job={{ id: "temporary" }} />;
}
return ( return (
<JobsDocumentsComponent <JobsDocumentsComponent
data={data ? data.documents : []} data={data ? data.documents : []}

View File

@@ -14,7 +14,6 @@ import TimeTicketList from "../../components/time-ticket-list/time-ticket-list.c
import TimeTicketsPayrollTable from "../../components/time-tickets-payroll-table/time-tickets-payroll-table.component"; import TimeTicketsPayrollTable from "../../components/time-tickets-payroll-table/time-tickets-payroll-table.component";
import TimeTicketsSummaryEmployees from "../../components/time-tickets-summary-employees/time-tickets-summary-employees.component"; import TimeTicketsSummaryEmployees from "../../components/time-tickets-summary-employees/time-tickets-summary-employees.component";
import { QUERY_TIME_TICKETS_IN_RANGE } from "../../graphql/timetickets.queries"; import { QUERY_TIME_TICKETS_IN_RANGE } from "../../graphql/timetickets.queries";
import TimeTicketsAttendanceTable from "../../components/time-tickets-attendance-table/time-tickets-attendance-table.component";
import { import {
setBreadcrumbs, setBreadcrumbs,
setSelectedHeader, setSelectedHeader,
@@ -72,7 +71,6 @@ export function TimeTicketsContainer({
timetickets={data ? data.timetickets : []} timetickets={data ? data.timetickets : []}
extra={ extra={
<Space wrap> <Space wrap>
<TimeTicketsAttendanceTable />
<TimeTicketsPayrollTable /> <TimeTicketsPayrollTable />
<TimeTicketsDatesSelector /> <TimeTicketsDatesSelector />
</Space> </Space>

View File

@@ -1,34 +0,0 @@
import MediaActionTypes from "./media.types";
export const getJobMedia = (jobid) => ({
type: MediaActionTypes.GET_MEDIA_FOR_JOB,
payload: jobid,
});
export const getBillMedia = ({ jobid, invoice_number }) => {
console.log("in the action");
return {
type: MediaActionTypes.GET_MEDIA_FOR_BILL,
payload: { jobid, invoice_number },
};
};
export const setJobMedia = ({ jobid, media }) => ({
type: MediaActionTypes.SET_MEDIA_FOR_JOB,
payload: { jobid, media },
});
export const addMediaForJob = ({ jobid, media }) => ({
type: MediaActionTypes.ADD_MEDIA_FOR_JOB,
payload: { jobid, media },
});
export const getJobMediaError = ({ error, message }) => ({
type: MediaActionTypes.GET_MEDIA_FOR_JOB_ERROR,
payload: { error, message },
});
export const toggleMediaSelected = ({ jobid, filename }) => ({
type: MediaActionTypes.TOGGLE_MEDIA_SELECTED,
payload: { jobid, filename },
});

View File

@@ -1,34 +0,0 @@
import MediaActionTypes from "./media.types";
const INITIAL_STATE = { error: null };
const mediaReducer = (state = INITIAL_STATE, action) => {
switch (action.type) {
case MediaActionTypes.SET_MEDIA_FOR_JOB:
return { ...state, [action.payload.jobid]: action.payload.media };
case MediaActionTypes.GET_MEDIA_FOR_JOB_ERROR:
return { ...state, error: action.payload };
case MediaActionTypes.ADD_MEDIA_FOR_JOB:
return {
...state,
[action.payload.jobid]: [
...(state[action.payload.jobid] ? state[action.payload.jobid] : []),
...(action.payload.media || []),
],
};
case MediaActionTypes.TOGGLE_MEDIA_SELECTED:
return {
...state,
[action.payload.jobid]: state[action.payload.jobid].map((p) => {
if (p.filename === action.payload.filename) {
p.isSelected = !p.isSelected;
}
return p;
}),
};
default:
return state;
}
};
export default mediaReducer;

View File

@@ -1,108 +0,0 @@
import { all, call, takeLatest, put, select } from "redux-saga/effects";
import { getJobMediaError, setJobMedia } from "./media.actions";
import MediaActionTypes from "./media.types";
import cleanAxios from "../../utils/CleanAxios";
import normalizeUrl from "normalize-url";
export function* onSetJobMedia() {
yield takeLatest(MediaActionTypes.GET_MEDIA_FOR_JOB, getJobMedia);
}
export function* getJobMedia({ payload: jobid }) {
try {
const localmediaserverhttp = (yield select(
(state) => state.user.bodyshop.localmediaserverhttp
)).trim();
if (localmediaserverhttp && localmediaserverhttp !== "") {
const imagesFetch = yield cleanAxios.post(
`${localmediaserverhttp}/jobs/list`,
{
jobid,
}
);
const documentsFetch = yield cleanAxios.post(
`${localmediaserverhttp}/bills/list`,
{
jobid,
}
);
yield put(
setJobMedia({
jobid,
media: [
...imagesFetch.data.map((d, idx) => {
return {
...d,
src: normalizeUrl(`${localmediaserverhttp}/${d.src}`),
thumbnail: normalizeUrl(
`${localmediaserverhttp}/${d.thumbnail}`
),
isSelected: false,
key: idx,
};
}),
...documentsFetch.data.map((d, idx) => {
return {
...d,
src: normalizeUrl(`${localmediaserverhttp}/${d.src}`),
thumbnail: normalizeUrl(
`${localmediaserverhttp}/${d.thumbnail}`
),
isSelected: false,
key: idx,
};
}),
],
})
);
}
} catch (error) {
yield put(getJobMediaError(error));
}
}
export function* onSetBillMedia() {
yield takeLatest(MediaActionTypes.GET_MEDIA_FOR_BILL, getBillMedia);
}
export function* getBillMedia({ payload: { jobid, invoice_number } }) {
try {
const localmediaserverhttp = (yield select(
(state) => state.user.bodyshop.localmediaserverhttp
)).trim();
if (localmediaserverhttp && localmediaserverhttp !== "") {
const documentsFetch = yield cleanAxios.post(
`${localmediaserverhttp}/bills/list`,
{
jobid,
invoice_number,
}
);
yield put(
setJobMedia({
jobid,
media: [
...documentsFetch.data.map((d, idx) => {
return {
...d,
src: normalizeUrl(`${localmediaserverhttp}/${d.src}`),
thumbnail: normalizeUrl(
`${localmediaserverhttp}/${d.thumbnail}`
),
isSelected: false,
key: idx,
};
}),
],
})
);
}
} catch (error) {
yield put(getJobMediaError(error));
}
}
export function* mediaSagas() {
yield all([call(onSetJobMedia), call(onSetBillMedia)]);
}

View File

@@ -1,5 +0,0 @@
import { createSelector } from "reselect";
const selectMedia = (state) => state.media;
export const selectAllMedia = createSelector([selectMedia], (media) => media);

View File

@@ -1,12 +0,0 @@
const MediaActionTypes = {
SET_MEDIA_FOR_JOB: "SET_MEDIA_FOR_JOB",
GET_MEDIA_FOR_JOB: "GET_MEDIA_FOR_JOB",
GET_MEDIA_FOR_JOB_ERROR: "GET_MEDIA_FOR_JOB_ERROR",
ADD_MEDIA_FOR_JOB: "ADD_MEDIA_FOR_JOB",
TOGGLE_MEDIA_SELECTED: "TOGGLE_MEDIA_SELECTED",
POST_MEDIA_FOR_JOB: "POST_MEDIA_FOR_JOB",
POST_MEDIA_FOR_JOB_SUCCESS: "POST_MEDIA_FOR_JOB_SUCCESS",
POST_MEDIA_FOR_JOB_ERROR: "POST_MEDIA_FOR_JOB_ERROR",
GET_MEDIA_FOR_BILL: "GET_MEDIA_FOR_BILL",
};
export default MediaActionTypes;

View File

@@ -4,7 +4,6 @@ import storage from "redux-persist/lib/storage";
import { withReduxStateSync } from "redux-state-sync"; import { withReduxStateSync } from "redux-state-sync";
import applicationReducer from "./application/application.reducer"; import applicationReducer from "./application/application.reducer";
import emailReducer from "./email/email.reducer"; import emailReducer from "./email/email.reducer";
import mediaReducer from "./media/media.reducer";
import messagingReducer from "./messaging/messaging.reducer"; import messagingReducer from "./messaging/messaging.reducer";
import modalsReducer from "./modals/modals.reducer"; import modalsReducer from "./modals/modals.reducer";
import techReducer from "./tech/tech.reducer"; import techReducer from "./tech/tech.reducer";
@@ -30,7 +29,6 @@ const rootReducer = combineReducers({
modals: modalsReducer, modals: modalsReducer,
application: persistReducer(applicationPersistConfig, applicationReducer), application: persistReducer(applicationPersistConfig, applicationReducer),
tech: techReducer, tech: techReducer,
media: mediaReducer,
}); });
export default withReduxStateSync( export default withReduxStateSync(

View File

@@ -6,7 +6,6 @@ import { emailSagas } from "./email/email.sagas";
import { modalsSagas } from "./modals/modals.sagas"; import { modalsSagas } from "./modals/modals.sagas";
import { applicationSagas } from "./application/application.sagas"; import { applicationSagas } from "./application/application.sagas";
import { techSagas } from "./tech/tech.sagas"; import { techSagas } from "./tech/tech.sagas";
import { mediaSagas } from "./media/media.sagas";
export default function* rootSaga() { export default function* rootSaga() {
yield all([ yield all([
@@ -16,6 +15,5 @@ export default function* rootSaga() {
call(modalsSagas), call(modalsSagas),
call(applicationSagas), call(applicationSagas),
call(techSagas), call(techSagas),
call(mediaSagas),
]); ]);
} }

View File

@@ -97,10 +97,7 @@ const userReducer = (state = INITIAL_STATE, action) => {
}; };
case UserActionTypes.SET_SHOP_DETAILS: case UserActionTypes.SET_SHOP_DETAILS:
return { return { ...state, bodyshop: action.payload };
...state,
bodyshop: action.payload,
};
case UserActionTypes.SIGN_IN_FAILURE: case UserActionTypes.SIGN_IN_FAILURE:
case UserActionTypes.SIGN_OUT_FAILURE: case UserActionTypes.SIGN_OUT_FAILURE:
case UserActionTypes.EMAIL_SIGN_UP_FAILURE: case UserActionTypes.EMAIL_SIGN_UP_FAILURE:

View File

@@ -90,9 +90,6 @@
}, },
"audit_trail": { "audit_trail": {
"messages": { "messages": {
"admin_jobmarkexported": "ADMIN: Job marked as exported.",
"admin_jobmarkforreexport": "ADMIN: Job marked for re-export.",
"admin_jobunvoid": "ADMIN: Job has been unvoided.",
"billposted": "Bill with invoice number {{invoice_number}} posted.", "billposted": "Bill with invoice number {{invoice_number}} posted.",
"billupdated": "Bill with invoice number {{invoice_number}} updated.", "billupdated": "Bill with invoice number {{invoice_number}} updated.",
"jobassignmentchange": "Employee {{name}} assigned to {{operation}}", "jobassignmentchange": "Employee {{name}} assigned to {{operation}}",
@@ -174,8 +171,7 @@
"bill_total": "Bill Total Amount", "bill_total": "Bill Total Amount",
"billcmtotal": "Credit Memos", "billcmtotal": "Credit Memos",
"bills": "Bills", "bills": "Bills",
"calculatedcreditsnotreceived": "Calculated CNR", "creditsnotreceived": "Credits Not Received",
"creditsnotreceived": "Credits Not Marked Received",
"creditsreceived": "Credits Received", "creditsreceived": "Credits Received",
"dedfromlbr": "Labor Adjustments", "dedfromlbr": "Labor Adjustments",
"deleteconfirm": "Are you sure you want to delete this bill? It cannot be undone. If this bill has deductions from labors, manual changes may be required.", "deleteconfirm": "Are you sure you want to delete this bill? It cannot be undone. If this bill has deductions from labors, manual changes may be required.",
@@ -282,8 +278,6 @@
}, },
"last_name_first": "Display Owner Info as <Last>, <First>", "last_name_first": "Display Owner Info as <Last>, <First>",
"lastnumberworkingdays": "Scoreboard - Last Number of Working Days", "lastnumberworkingdays": "Scoreboard - Last Number of Working Days",
"localmediaserverhttp": "Local Media Server - HTTP Path",
"localmediaservernetwork": "Local Media Server - Network Path",
"logo_img_footer_margin": "Footer Margin (px)", "logo_img_footer_margin": "Footer Margin (px)",
"logo_img_header_margin": "Header Margin (px)", "logo_img_header_margin": "Header Margin (px)",
"logo_img_path": "Shop Logo", "logo_img_path": "Shop Logo",
@@ -361,7 +355,6 @@
"intake": "Jobs -> Intake", "intake": "Jobs -> Intake",
"list-active": "Jobs -> List Active", "list-active": "Jobs -> List Active",
"list-all": "Jobs -> List All", "list-all": "Jobs -> List All",
"list-ready": "Jobs -> List Ready",
"partsqueue": "Jobs -> Parts Queue" "partsqueue": "Jobs -> Parts Queue"
}, },
"owners": { "owners": {
@@ -483,7 +476,6 @@
"status": "Status Label", "status": "Status Label",
"statuses": { "statuses": {
"active_statuses": "Active Statuses (Filtering for Active Jobs throughout system)", "active_statuses": "Active Statuses (Filtering for Active Jobs throughout system)",
"additional_board_statuses": "Additional Status to Display on Production Board",
"color": "Color", "color": "Color",
"default_arrived": "Default Arrived Status (Transition to Production)", "default_arrived": "Default Arrived Status (Transition to Production)",
"default_bo": "Default Backordered Status", "default_bo": "Default Backordered Status",
@@ -502,14 +494,12 @@
"post_production_statuses": "Post-Production Statuses", "post_production_statuses": "Post-Production Statuses",
"pre_production_statuses": "Pre-Production Statuses", "pre_production_statuses": "Pre-Production Statuses",
"production_colors": "Production Status Colors", "production_colors": "Production Status Colors",
"production_statuses": "Production Statuses", "production_statuses": "Production Statuses"
"ready_statuses": "Ready Statuses"
}, },
"target_touchtime": "Target Touch Time", "target_touchtime": "Target Touch Time",
"timezone": "Timezone", "timezone": "Timezone",
"tt_allow_post_to_invoiced": "Allow Time Tickets to be posted to Invoiced & Exported Jobs", "tt_allow_post_to_invoiced": "Allow Time Tickets to be posted to Invoiced & Exported Jobs",
"use_fippa": "Use FIPPA for Names on Generated Documents?", "use_fippa": "Use FIPPA for Names on Generated Documents?",
"uselocalmediaserver": "Use Local Media Server?",
"website": "Website", "website": "Website",
"zip_post": "Zip/Postal Code" "zip_post": "Zip/Postal Code"
}, },
@@ -547,8 +537,6 @@
"jobstatuses": "Job Statuses", "jobstatuses": "Job Statuses",
"laborrates": "Labor Rates", "laborrates": "Labor Rates",
"licensing": "Licensing", "licensing": "Licensing",
"md_to_emails": "Preset To Emails",
"md_to_emails_emails": "Emails",
"messagingpresets": "Messaging Presets", "messagingpresets": "Messaging Presets",
"notemplatesavailable": "No templates available to add.", "notemplatesavailable": "No templates available to add.",
"notespresets": "Notes Presets", "notespresets": "Notes Presets",
@@ -827,7 +815,6 @@
"confirmdelete": "Are you sure you want to delete these documents. This CANNOT be undone.", "confirmdelete": "Are you sure you want to delete these documents. This CANNOT be undone.",
"doctype": "Document Type", "doctype": "Document Type",
"newjobid": "Assign to Job", "newjobid": "Assign to Job",
"openinexplorer": "Open in Explorer",
"reassign_limitexceeded": "Reassigning all selected documents will exceed the job storage limit for your shop. ", "reassign_limitexceeded": "Reassigning all selected documents will exceed the job storage limit for your shop. ",
"reassign_limitexceeded_title": "Unable to reassign document(s)", "reassign_limitexceeded_title": "Unable to reassign document(s)",
"storageexceeded": "You've exceeded your storage limit for this job. Please remove documents, or increase your storage plan.", "storageexceeded": "You've exceeded your storage limit for this job. Please remove documents, or increase your storage plan.",
@@ -883,7 +870,6 @@
"base_rate": "Base Rate", "base_rate": "Base Rate",
"cost_center": "Cost Center", "cost_center": "Cost Center",
"employee_number": "Employee Number", "employee_number": "Employee Number",
"external_id": "External Employee ID",
"first_name": "First Name", "first_name": "First Name",
"flat_rate": "Flat Rate (Disabled is Straight Time)", "flat_rate": "Flat Rate (Disabled is Straight Time)",
"hire_date": "Hire Date", "hire_date": "Hire Date",
@@ -919,8 +905,7 @@
"createdat": "Created At" "createdat": "Created At"
}, },
"labels": { "labels": {
"attempts": "Export Attempts", "attempts": "Export Attempts"
"priorsuccesfulexport": "This record has previously been exported successfully. Please make sure it has already been deleted in the target system."
} }
}, },
"general": { "general": {
@@ -1002,7 +987,6 @@
"passwordresetvalidatesuccess_sub": "You may now sign in again using your new password. ", "passwordresetvalidatesuccess_sub": "You may now sign in again using your new password. ",
"passwordsdonotmatch": "The passwords you have entered do not match.", "passwordsdonotmatch": "The passwords you have entered do not match.",
"print": "Print", "print": "Print",
"refresh": "Refresh",
"required": "Required", "required": "Required",
"saturday": "Saturday", "saturday": "Saturday",
"search": "Search...", "search": "Search...",
@@ -1401,7 +1385,6 @@
"prt_tax_rt": "Part Tax Rate", "prt_tax_rt": "Part Tax Rate",
"prt_type": "Part Type" "prt_type": "Part Type"
}, },
"partsstatus": "Parts Status",
"pas": "Sublet", "pas": "Sublet",
"pay_date": "Pay Date", "pay_date": "Pay Date",
"phoneshort": "PH", "phoneshort": "PH",
@@ -1411,7 +1394,6 @@
"production_vars": { "production_vars": {
"note": "Production Note" "note": "Production Note"
}, },
"queued_for_parts": "Queued for Parts",
"rate_ats": "ATS Rate", "rate_ats": "ATS Rate",
"rate_la1": "LA1", "rate_la1": "LA1",
"rate_la2": "LA2", "rate_la2": "LA2",
@@ -1597,15 +1579,14 @@
"partstotal": "Parts Total (ex. Taxes)", "partstotal": "Parts Total (ex. Taxes)",
"plitooltips": { "plitooltips": {
"billtotal": "The total amount of all bill lines that have been posted against this RO (not including credits, taxes, or labor adjustments).", "billtotal": "The total amount of all bill lines that have been posted against this RO (not including credits, taxes, or labor adjustments).",
"calculatedcreditsnotreceived": "The calculated credits not received is derived by subtracting the amount of credit memos entered from the <b>retail</b> total of returns created. This does not take into account whether the credit was marked as received. You can find more information <a href=\"https://help.imex.online/en/article/credits-not-received-changes-1jy9snw\" target=\"_blank\">here</a>.", "creditmemos": "The total amount of all returns created. This amount does not reflect credit memos that have been posted.",
"creditmemos": "The total <b>retail</b> amount of all returns created. This amount does not reflect credit memos that have been posted.", "creditsnotreceived": "The total amount of returns created for this job that do not have a corresponding credit memo posted. An amount greater than $0 indicates that vendors have not provided requested credit memos.",
"creditsnotreceived": "This total reflects the total <b>retail</b> of parts returns lines that have not been explicitly marked as returned when posting a credit memo. You can learn more about this here <a href=\"https://help.imex.online/en/article/credits-not-received-changes-1jy9snw\" target=\"_blank\">here</a>. ",
"discrep1": "If the discrepancy is not $0, you may have one of the following: <br/><br/>\n\n<ul>\n<li>Too many bills/bill lines that have been posted against this RO. Check to make sure every bill posted on this RO is correctly posted and assigned.</li>\n<li>You do not have the latest supplement imported, or, a supplement must be submitted and then imported.</li>\n<li>You have posted a bill line to labor.</li>\n</ul>\n<br/>\n<i>There may be additional issues not listed above that prevent this job from reconciling.</i>", "discrep1": "If the discrepancy is not $0, you may have one of the following: <br/><br/>\n\n<ul>\n<li>Too many bills/bill lines that have been posted against this RO. Check to make sure every bill posted on this RO is correctly posted and assigned.</li>\n<li>You do not have the latest supplement imported, or, a supplement must be submitted and then imported.</li>\n<li>You have posted a bill line to labor.</li>\n</ul>\n<br/>\n<i>There may be additional issues not listed above that prevent this job from reconciling.</i>",
"discrep2": "If the discrepancy is not $0, you may have one of the following: <br/><br/>\n\n<ul>\n<li>Used an incorrect rate when deducting from labor.</li>\n<li>An outstanding imbalance higher in the reconciliation process.</li>\n</ul>\n<br/>\n<i>There may be additional issues not listed above that prevent this job from reconciling.</i>", "discrep2": "If the discrepancy is not $0, you may have one of the following: <br/><br/>\n\n<ul>\n<li>Used an incorrect rate when deducting from labor.</li>\n<li>An outstanding imbalance higher in the reconciliation process.</li>\n</ul>\n<br/>\n<i>There may be additional issues not listed above that prevent this job from reconciling.</i>",
"discrep3": "If the discrepancy is not $0, you may have one of the following: <br/><br/>\n\n<ul>\n<li>A parts order return has not been created.</li>\n<li>An outstanding imbalance higher in the reconciliation process.</li>\n</ul>\n<br/>\n<i>There may be additional issues not listed above that prevent this job from reconciling.</i>", "discrep3": "If the discrepancy is not $0, you may have one of the following: <br/><br/>\n\n<ul>\n<li>Credit memos that have not been received or posted.</li>\n<li>An outstanding imbalance higher in the reconciliation process.</li>\n</ul>\n<br/>\n<i>There may be additional issues not listed above that prevent this job from reconciling.</i>",
"laboradj": "The sum of all bill lines that deducted from labor hours, rather than part prices.", "laboradj": "The sum of all bill lines that deducted from labor hours, rather than part prices.",
"partstotal": "This is the total of all parts and sublet amounts on the vehicle (some of these may require an in-house invoice).<br/>\nItems such as shop and paint materials, labor online lines, etc. are not included in this total.", "partstotal": "This is the total of all parts and sublet amounts on the vehicle (some of these may require an in-house invoice).<br/>\nItems such as shop and paint materials, labor online lines, etc. are not included in this total.",
"totalreturns": "The total <b>retail</b> amount of returns created for this job." "totalreturns": "The total amount of returns created for this job."
}, },
"prt_dsmk_total": "Line Item Adjustment", "prt_dsmk_total": "Line Item Adjustment",
"rates": "Rates", "rates": "Rates",
@@ -1692,15 +1673,15 @@
"name": "ImEX Online", "name": "ImEX Online",
"status": "System Status" "status": "System Status"
}, },
"slogan": "ImEX Systems Inc. is a technology leader in the collision repair industry. We specialize in creating collision repair management systems and bodyshop management systems that lower cycle times and promote efficiency." "slogan": "A whole new kind of shop management system."
}, },
"hero": { "hero": {
"button": "Learn More", "button": "Learn More",
"title": "Shop management reimagined." "title": "A whole new kind of shop management system."
}, },
"labels": { "labels": {
"features": "Features", "features": "Features",
"managemyshop": "Sign In", "managemyshop": "Manage my Shop",
"pricing": "Pricing" "pricing": "Pricing"
}, },
"pricing": { "pricing": {
@@ -1759,7 +1740,6 @@
"phonebook": "Phonebook", "phonebook": "Phonebook",
"productionboard": "Production Board - Visual", "productionboard": "Production Board - Visual",
"productionlist": "Production Board - List", "productionlist": "Production Board - List",
"readyjobs": "Ready Jobs",
"recent": "Recent Items", "recent": "Recent Items",
"reportcenter": "Report Center", "reportcenter": "Report Center",
"rescueme": "Rescue me!", "rescueme": "Rescue me!",
@@ -1924,8 +1904,7 @@
}, },
"parts": { "parts": {
"actions": { "actions": {
"order": "Order Parts", "order": "Order Parts"
"orderinhouse": "Order as In House"
} }
}, },
"parts_orders": { "parts_orders": {
@@ -1938,15 +1917,12 @@
"associatedbills": "This parts order cannot", "associatedbills": "This parts order cannot",
"backordering": "Error backordering part {{message}}.", "backordering": "Error backordering part {{message}}.",
"creating": "Error encountered when creating parts order. ", "creating": "Error encountered when creating parts order. ",
"oec": "Error creating EMS files for OEC. {{error}}", "oec": "Error creating EMS files for OEC. {{error}}"
"saving": "Error saving parts order. {{error}}.",
"updating": "Error updating parts order/parts order line. {{error}}."
}, },
"fields": { "fields": {
"act_price": "Price", "act_price": "Price",
"backordered_eta": "B.O. ETA", "backordered_eta": "B.O. ETA",
"backordered_on": "B.O. On", "backordered_on": "B.O. On",
"cm_received": "CM Received?",
"comments": "Comments", "comments": "Comments",
"cost": "Cost", "cost": "Cost",
"db_price": "List Price", "db_price": "List Price",
@@ -1969,7 +1945,6 @@
"confirmdelete": "Are you sure you want to delete this item? It cannot be recovered. Job line statuses will not be updated and may require manual review. ", "confirmdelete": "Are you sure you want to delete this item? It cannot be recovered. Job line statuses will not be updated and may require manual review. ",
"email": "Send by Email", "email": "Send by Email",
"inthisorder": "Parts in this Order", "inthisorder": "Parts in this Order",
"mark_as_received": "Mark as Received?",
"newpartsorder": "New Parts Order", "newpartsorder": "New Parts Order",
"notyetordered": "This part has not yet been ordered.", "notyetordered": "This part has not yet been ordered.",
"oec": "Order via OEC", "oec": "Order via OEC",
@@ -1981,7 +1956,6 @@
}, },
"successes": { "successes": {
"created": "Parts order created successfully. ", "created": "Parts order created successfully. ",
"line_updated": "Parts return line updated.",
"received": "Parts order received.", "received": "Parts order received.",
"return_created": "Parts return created successfully." "return_created": "Parts return created successfully."
} }
@@ -2103,7 +2077,6 @@
"estimate_detail": "Estimate Details", "estimate_detail": "Estimate Details",
"estimate_followup": "Estimate Followup", "estimate_followup": "Estimate Followup",
"express_repair_checklist": "Express Repair Checklist", "express_repair_checklist": "Express Repair Checklist",
"filing_coversheet_landscape": "Filing Coversheet (Landscape)",
"filing_coversheet_portrait": "Filing Coversheet (Portrait)", "filing_coversheet_portrait": "Filing Coversheet (Portrait)",
"final_invoice": "Final Invoice", "final_invoice": "Final Invoice",
"fippa_authorization": "FIPPA Authorization", "fippa_authorization": "FIPPA Authorization",
@@ -2178,9 +2151,6 @@
"ca_bc_etf_table": "ICBC ETF Table", "ca_bc_etf_table": "ICBC ETF Table",
"exported_payroll": "Payroll Table" "exported_payroll": "Payroll Table"
}, },
"special": {
"attendance_detail_csv": "Attendance Table"
},
"subjects": { "subjects": {
"jobs": { "jobs": {
"parts_order": "Parts Order PO: {{ro_number}} - {{name}}" "parts_order": "Parts Order PO: {{ro_number}} - {{name}}"
@@ -2212,7 +2182,6 @@
"settings": "Error saving board settings: {{error}}" "settings": "Error saving board settings: {{error}}"
}, },
"labels": { "labels": {
"actual_in": "Actual In",
"alert": "Alert", "alert": "Alert",
"alertoff": "Remove alert from job", "alertoff": "Remove alert from job",
"alerton": "Add alert to job", "alerton": "Add alert to job",
@@ -2238,7 +2207,6 @@
"note": "Production Note", "note": "Production Note",
"ownr_nm": "Owner Name", "ownr_nm": "Owner Name",
"paintpriority": "P/P", "paintpriority": "P/P",
"partsstatus": "Parts Status",
"production_note": "Production Note", "production_note": "Production Note",
"refinishhours": "R", "refinishhours": "R",
"scheduled_completion": "Scheduled Completion", "scheduled_completion": "Scheduled Completion",
@@ -2526,7 +2494,6 @@
"jobs-detail": "Job {{number}}", "jobs-detail": "Job {{number}}",
"jobs-intake": "Intake", "jobs-intake": "Intake",
"jobs-new": "Create a New Job", "jobs-new": "Create a New Job",
"jobs-ready": "Ready Jobs",
"owner-detail": "{{name}}", "owner-detail": "{{name}}",
"owners": "Owners", "owners": "Owners",
"parts-queue": "Parts Queue", "parts-queue": "Parts Queue",
@@ -2576,7 +2543,6 @@
"productionboard": "Production - Board", "productionboard": "Production - Board",
"productionlist": "Production Board - List | $t(titles.app)", "productionlist": "Production Board - List | $t(titles.app)",
"profile": "My Profile | $t(titles.app)", "profile": "My Profile | $t(titles.app)",
"readyjobs": "Ready Jobs | $t(titles.app)",
"resetpassword": "Reset Password", "resetpassword": "Reset Password",
"resetpasswordvalidate": "Enter New Password", "resetpasswordvalidate": "Enter New Password",
"schedule": "Schedule | $t(titles.app)", "schedule": "Schedule | $t(titles.app)",

View File

@@ -90,9 +90,6 @@
}, },
"audit_trail": { "audit_trail": {
"messages": { "messages": {
"admin_jobmarkexported": "",
"admin_jobmarkforreexport": "",
"admin_jobunvoid": "",
"billposted": "", "billposted": "",
"billupdated": "", "billupdated": "",
"jobassignmentchange": "", "jobassignmentchange": "",
@@ -174,7 +171,6 @@
"bill_total": "", "bill_total": "",
"billcmtotal": "", "billcmtotal": "",
"bills": "", "bills": "",
"calculatedcreditsnotreceived": "",
"creditsnotreceived": "", "creditsnotreceived": "",
"creditsreceived": "", "creditsreceived": "",
"dedfromlbr": "", "dedfromlbr": "",
@@ -282,8 +278,6 @@
}, },
"last_name_first": "", "last_name_first": "",
"lastnumberworkingdays": "", "lastnumberworkingdays": "",
"localmediaserverhttp": "",
"localmediaservernetwork": "",
"logo_img_footer_margin": "", "logo_img_footer_margin": "",
"logo_img_header_margin": "", "logo_img_header_margin": "",
"logo_img_path": "", "logo_img_path": "",
@@ -361,7 +355,6 @@
"intake": "", "intake": "",
"list-active": "", "list-active": "",
"list-all": "", "list-all": "",
"list-ready": "",
"partsqueue": "" "partsqueue": ""
}, },
"owners": { "owners": {
@@ -483,7 +476,6 @@
"status": "", "status": "",
"statuses": { "statuses": {
"active_statuses": "", "active_statuses": "",
"additional_board_statuses": "",
"color": "", "color": "",
"default_arrived": "", "default_arrived": "",
"default_bo": "", "default_bo": "",
@@ -502,14 +494,12 @@
"post_production_statuses": "", "post_production_statuses": "",
"pre_production_statuses": "", "pre_production_statuses": "",
"production_colors": "", "production_colors": "",
"production_statuses": "", "production_statuses": ""
"ready_statuses": ""
}, },
"target_touchtime": "", "target_touchtime": "",
"timezone": "", "timezone": "",
"tt_allow_post_to_invoiced": "", "tt_allow_post_to_invoiced": "",
"use_fippa": "", "use_fippa": "",
"uselocalmediaserver": "",
"website": "", "website": "",
"zip_post": "" "zip_post": ""
}, },
@@ -547,8 +537,6 @@
"jobstatuses": "", "jobstatuses": "",
"laborrates": "", "laborrates": "",
"licensing": "", "licensing": "",
"md_to_emails": "",
"md_to_emails_emails": "",
"messagingpresets": "", "messagingpresets": "",
"notemplatesavailable": "", "notemplatesavailable": "",
"notespresets": "", "notespresets": "",
@@ -827,7 +815,6 @@
"confirmdelete": "", "confirmdelete": "",
"doctype": "", "doctype": "",
"newjobid": "", "newjobid": "",
"openinexplorer": "",
"reassign_limitexceeded": "", "reassign_limitexceeded": "",
"reassign_limitexceeded_title": "", "reassign_limitexceeded_title": "",
"storageexceeded": "", "storageexceeded": "",
@@ -883,7 +870,6 @@
"base_rate": "Tasa básica", "base_rate": "Tasa básica",
"cost_center": "Centro de costos", "cost_center": "Centro de costos",
"employee_number": "Numero de empleado", "employee_number": "Numero de empleado",
"external_id": "",
"first_name": "Nombre de pila", "first_name": "Nombre de pila",
"flat_rate": "Tarifa plana (deshabilitado es tiempo recto)", "flat_rate": "Tarifa plana (deshabilitado es tiempo recto)",
"hire_date": "Fecha de contratación", "hire_date": "Fecha de contratación",
@@ -919,8 +905,7 @@
"createdat": "" "createdat": ""
}, },
"labels": { "labels": {
"attempts": "", "attempts": ""
"priorsuccesfulexport": ""
} }
}, },
"general": { "general": {
@@ -1002,7 +987,6 @@
"passwordresetvalidatesuccess_sub": "", "passwordresetvalidatesuccess_sub": "",
"passwordsdonotmatch": "", "passwordsdonotmatch": "",
"print": "", "print": "",
"refresh": "",
"required": "", "required": "",
"saturday": "", "saturday": "",
"search": "Buscar...", "search": "Buscar...",
@@ -1401,7 +1385,6 @@
"prt_tax_rt": "", "prt_tax_rt": "",
"prt_type": "" "prt_type": ""
}, },
"partsstatus": "",
"pas": "", "pas": "",
"pay_date": "Fecha de Pay", "pay_date": "Fecha de Pay",
"phoneshort": "PH", "phoneshort": "PH",
@@ -1411,7 +1394,6 @@
"production_vars": { "production_vars": {
"note": "" "note": ""
}, },
"queued_for_parts": "",
"rate_ats": "", "rate_ats": "",
"rate_la1": "Tarifa LA1", "rate_la1": "Tarifa LA1",
"rate_la2": "Tarifa LA2", "rate_la2": "Tarifa LA2",
@@ -1597,7 +1579,6 @@
"partstotal": "", "partstotal": "",
"plitooltips": { "plitooltips": {
"billtotal": "", "billtotal": "",
"calculatedcreditsnotreceived": "",
"creditmemos": "", "creditmemos": "",
"creditsnotreceived": "", "creditsnotreceived": "",
"discrep1": "", "discrep1": "",
@@ -1759,7 +1740,6 @@
"phonebook": "", "phonebook": "",
"productionboard": "", "productionboard": "",
"productionlist": "", "productionlist": "",
"readyjobs": "",
"recent": "", "recent": "",
"reportcenter": "", "reportcenter": "",
"rescueme": "", "rescueme": "",
@@ -1924,8 +1904,7 @@
}, },
"parts": { "parts": {
"actions": { "actions": {
"order": "Pedido de piezas", "order": "Pedido de piezas"
"orderinhouse": ""
} }
}, },
"parts_orders": { "parts_orders": {
@@ -1938,15 +1917,12 @@
"associatedbills": "", "associatedbills": "",
"backordering": "", "backordering": "",
"creating": "Se encontró un error al crear el pedido de piezas.", "creating": "Se encontró un error al crear el pedido de piezas.",
"oec": "", "oec": ""
"saving": "",
"updating": ""
}, },
"fields": { "fields": {
"act_price": "", "act_price": "",
"backordered_eta": "", "backordered_eta": "",
"backordered_on": "", "backordered_on": "",
"cm_received": "",
"comments": "", "comments": "",
"cost": "", "cost": "",
"db_price": "", "db_price": "",
@@ -1969,7 +1945,6 @@
"confirmdelete": "", "confirmdelete": "",
"email": "Enviar por correo electrónico", "email": "Enviar por correo electrónico",
"inthisorder": "Partes en este pedido", "inthisorder": "Partes en este pedido",
"mark_as_received": "",
"newpartsorder": "", "newpartsorder": "",
"notyetordered": "", "notyetordered": "",
"oec": "", "oec": "",
@@ -1981,7 +1956,6 @@
}, },
"successes": { "successes": {
"created": "Pedido de piezas creado con éxito.", "created": "Pedido de piezas creado con éxito.",
"line_updated": "",
"received": "", "received": "",
"return_created": "" "return_created": ""
} }
@@ -2103,7 +2077,6 @@
"estimate_detail": "", "estimate_detail": "",
"estimate_followup": "", "estimate_followup": "",
"express_repair_checklist": "", "express_repair_checklist": "",
"filing_coversheet_landscape": "",
"filing_coversheet_portrait": "", "filing_coversheet_portrait": "",
"final_invoice": "", "final_invoice": "",
"fippa_authorization": "", "fippa_authorization": "",
@@ -2178,9 +2151,6 @@
"ca_bc_etf_table": "", "ca_bc_etf_table": "",
"exported_payroll": "" "exported_payroll": ""
}, },
"special": {
"attendance_detail_csv": ""
},
"subjects": { "subjects": {
"jobs": { "jobs": {
"parts_order": "" "parts_order": ""
@@ -2212,7 +2182,6 @@
"settings": "" "settings": ""
}, },
"labels": { "labels": {
"actual_in": "",
"alert": "", "alert": "",
"alertoff": "", "alertoff": "",
"alerton": "", "alerton": "",
@@ -2238,7 +2207,6 @@
"note": "", "note": "",
"ownr_nm": "", "ownr_nm": "",
"paintpriority": "", "paintpriority": "",
"partsstatus": "",
"production_note": "", "production_note": "",
"refinishhours": "", "refinishhours": "",
"scheduled_completion": "", "scheduled_completion": "",
@@ -2526,7 +2494,6 @@
"jobs-detail": "", "jobs-detail": "",
"jobs-intake": "", "jobs-intake": "",
"jobs-new": "", "jobs-new": "",
"jobs-ready": "",
"owner-detail": "", "owner-detail": "",
"owners": "", "owners": "",
"parts-queue": "", "parts-queue": "",
@@ -2576,7 +2543,6 @@
"productionboard": "", "productionboard": "",
"productionlist": "", "productionlist": "",
"profile": "Mi perfil | $t(titles.app)", "profile": "Mi perfil | $t(titles.app)",
"readyjobs": "",
"resetpassword": "", "resetpassword": "",
"resetpasswordvalidate": "", "resetpasswordvalidate": "",
"schedule": "Horario | $t(titles.app)", "schedule": "Horario | $t(titles.app)",

View File

@@ -90,9 +90,6 @@
}, },
"audit_trail": { "audit_trail": {
"messages": { "messages": {
"admin_jobmarkexported": "",
"admin_jobmarkforreexport": "",
"admin_jobunvoid": "",
"billposted": "", "billposted": "",
"billupdated": "", "billupdated": "",
"jobassignmentchange": "", "jobassignmentchange": "",
@@ -174,7 +171,6 @@
"bill_total": "", "bill_total": "",
"billcmtotal": "", "billcmtotal": "",
"bills": "", "bills": "",
"calculatedcreditsnotreceived": "",
"creditsnotreceived": "", "creditsnotreceived": "",
"creditsreceived": "", "creditsreceived": "",
"dedfromlbr": "", "dedfromlbr": "",
@@ -282,8 +278,6 @@
}, },
"last_name_first": "", "last_name_first": "",
"lastnumberworkingdays": "", "lastnumberworkingdays": "",
"localmediaserverhttp": "",
"localmediaservernetwork": "",
"logo_img_footer_margin": "", "logo_img_footer_margin": "",
"logo_img_header_margin": "", "logo_img_header_margin": "",
"logo_img_path": "", "logo_img_path": "",
@@ -361,7 +355,6 @@
"intake": "", "intake": "",
"list-active": "", "list-active": "",
"list-all": "", "list-all": "",
"list-ready": "",
"partsqueue": "" "partsqueue": ""
}, },
"owners": { "owners": {
@@ -483,7 +476,6 @@
"status": "", "status": "",
"statuses": { "statuses": {
"active_statuses": "", "active_statuses": "",
"additional_board_statuses": "",
"color": "", "color": "",
"default_arrived": "", "default_arrived": "",
"default_bo": "", "default_bo": "",
@@ -502,14 +494,12 @@
"post_production_statuses": "", "post_production_statuses": "",
"pre_production_statuses": "", "pre_production_statuses": "",
"production_colors": "", "production_colors": "",
"production_statuses": "", "production_statuses": ""
"ready_statuses": ""
}, },
"target_touchtime": "", "target_touchtime": "",
"timezone": "", "timezone": "",
"tt_allow_post_to_invoiced": "", "tt_allow_post_to_invoiced": "",
"use_fippa": "", "use_fippa": "",
"uselocalmediaserver": "",
"website": "", "website": "",
"zip_post": "" "zip_post": ""
}, },
@@ -547,8 +537,6 @@
"jobstatuses": "", "jobstatuses": "",
"laborrates": "", "laborrates": "",
"licensing": "", "licensing": "",
"md_to_emails": "",
"md_to_emails_emails": "",
"messagingpresets": "", "messagingpresets": "",
"notemplatesavailable": "", "notemplatesavailable": "",
"notespresets": "", "notespresets": "",
@@ -827,7 +815,6 @@
"confirmdelete": "", "confirmdelete": "",
"doctype": "", "doctype": "",
"newjobid": "", "newjobid": "",
"openinexplorer": "",
"reassign_limitexceeded": "", "reassign_limitexceeded": "",
"reassign_limitexceeded_title": "", "reassign_limitexceeded_title": "",
"storageexceeded": "", "storageexceeded": "",
@@ -883,7 +870,6 @@
"base_rate": "Taux de base", "base_rate": "Taux de base",
"cost_center": "Centre de coûts", "cost_center": "Centre de coûts",
"employee_number": "Numéro d'employé", "employee_number": "Numéro d'employé",
"external_id": "",
"first_name": "Prénom", "first_name": "Prénom",
"flat_rate": "Taux fixe (désactivé est le temps normal)", "flat_rate": "Taux fixe (désactivé est le temps normal)",
"hire_date": "Date d'embauche", "hire_date": "Date d'embauche",
@@ -919,8 +905,7 @@
"createdat": "" "createdat": ""
}, },
"labels": { "labels": {
"attempts": "", "attempts": ""
"priorsuccesfulexport": ""
} }
}, },
"general": { "general": {
@@ -1002,7 +987,6 @@
"passwordresetvalidatesuccess_sub": "", "passwordresetvalidatesuccess_sub": "",
"passwordsdonotmatch": "", "passwordsdonotmatch": "",
"print": "", "print": "",
"refresh": "",
"required": "", "required": "",
"saturday": "", "saturday": "",
"search": "Chercher...", "search": "Chercher...",
@@ -1401,7 +1385,6 @@
"prt_tax_rt": "", "prt_tax_rt": "",
"prt_type": "" "prt_type": ""
}, },
"partsstatus": "",
"pas": "", "pas": "",
"pay_date": "Date d'Pay", "pay_date": "Date d'Pay",
"phoneshort": "PH", "phoneshort": "PH",
@@ -1411,7 +1394,6 @@
"production_vars": { "production_vars": {
"note": "" "note": ""
}, },
"queued_for_parts": "",
"rate_ats": "", "rate_ats": "",
"rate_la1": "Taux LA1", "rate_la1": "Taux LA1",
"rate_la2": "Taux LA2", "rate_la2": "Taux LA2",
@@ -1597,7 +1579,6 @@
"partstotal": "", "partstotal": "",
"plitooltips": { "plitooltips": {
"billtotal": "", "billtotal": "",
"calculatedcreditsnotreceived": "",
"creditmemos": "", "creditmemos": "",
"creditsnotreceived": "", "creditsnotreceived": "",
"discrep1": "", "discrep1": "",
@@ -1759,7 +1740,6 @@
"phonebook": "", "phonebook": "",
"productionboard": "", "productionboard": "",
"productionlist": "", "productionlist": "",
"readyjobs": "",
"recent": "", "recent": "",
"reportcenter": "", "reportcenter": "",
"rescueme": "", "rescueme": "",
@@ -1924,8 +1904,7 @@
}, },
"parts": { "parts": {
"actions": { "actions": {
"order": "Commander des pièces", "order": "Commander des pièces"
"orderinhouse": ""
} }
}, },
"parts_orders": { "parts_orders": {
@@ -1938,15 +1917,12 @@
"associatedbills": "", "associatedbills": "",
"backordering": "", "backordering": "",
"creating": "Erreur rencontrée lors de la création de la commande de pièces.", "creating": "Erreur rencontrée lors de la création de la commande de pièces.",
"oec": "", "oec": ""
"saving": "",
"updating": ""
}, },
"fields": { "fields": {
"act_price": "", "act_price": "",
"backordered_eta": "", "backordered_eta": "",
"backordered_on": "", "backordered_on": "",
"cm_received": "",
"comments": "", "comments": "",
"cost": "", "cost": "",
"db_price": "", "db_price": "",
@@ -1969,7 +1945,6 @@
"confirmdelete": "", "confirmdelete": "",
"email": "Envoyé par email", "email": "Envoyé par email",
"inthisorder": "Pièces dans cette commande", "inthisorder": "Pièces dans cette commande",
"mark_as_received": "",
"newpartsorder": "", "newpartsorder": "",
"notyetordered": "", "notyetordered": "",
"oec": "", "oec": "",
@@ -1981,7 +1956,6 @@
}, },
"successes": { "successes": {
"created": "Commande de pièces créée avec succès.", "created": "Commande de pièces créée avec succès.",
"line_updated": "",
"received": "", "received": "",
"return_created": "" "return_created": ""
} }
@@ -2103,7 +2077,6 @@
"estimate_detail": "", "estimate_detail": "",
"estimate_followup": "", "estimate_followup": "",
"express_repair_checklist": "", "express_repair_checklist": "",
"filing_coversheet_landscape": "",
"filing_coversheet_portrait": "", "filing_coversheet_portrait": "",
"final_invoice": "", "final_invoice": "",
"fippa_authorization": "", "fippa_authorization": "",
@@ -2178,9 +2151,6 @@
"ca_bc_etf_table": "", "ca_bc_etf_table": "",
"exported_payroll": "" "exported_payroll": ""
}, },
"special": {
"attendance_detail_csv": ""
},
"subjects": { "subjects": {
"jobs": { "jobs": {
"parts_order": "" "parts_order": ""
@@ -2212,7 +2182,6 @@
"settings": "" "settings": ""
}, },
"labels": { "labels": {
"actual_in": "",
"alert": "", "alert": "",
"alertoff": "", "alertoff": "",
"alerton": "", "alerton": "",
@@ -2238,7 +2207,6 @@
"note": "", "note": "",
"ownr_nm": "", "ownr_nm": "",
"paintpriority": "", "paintpriority": "",
"partsstatus": "",
"production_note": "", "production_note": "",
"refinishhours": "", "refinishhours": "",
"scheduled_completion": "", "scheduled_completion": "",
@@ -2526,7 +2494,6 @@
"jobs-detail": "", "jobs-detail": "",
"jobs-intake": "", "jobs-intake": "",
"jobs-new": "", "jobs-new": "",
"jobs-ready": "",
"owner-detail": "", "owner-detail": "",
"owners": "", "owners": "",
"parts-queue": "", "parts-queue": "",
@@ -2576,7 +2543,6 @@
"productionboard": "", "productionboard": "",
"productionlist": "", "productionlist": "",
"profile": "Mon profil | $t(titles.app)", "profile": "Mon profil | $t(titles.app)",
"readyjobs": "",
"resetpassword": "", "resetpassword": "",
"resetpasswordvalidate": "", "resetpasswordvalidate": "",
"schedule": "Horaire | $t(titles.app)", "schedule": "Horaire | $t(titles.app)",

View File

@@ -3,17 +3,12 @@ import i18n from "i18next";
const AuditTrailMapping = { const AuditTrailMapping = {
jobstatuschange: (status) => jobstatuschange: (status) =>
i18n.t("audit_trail.messages.jobstatuschange", { status }), i18n.t("audit_trail.messages.jobstatuschange", { status }),
admin_jobstatuschange: (status) =>
"ADMIN: " + i18n.t("audit_trail.messages.jobstatuschange", { status }),
jobsupplement: () => i18n.t("audit_trail.messages.jobsupplement"), jobsupplement: () => i18n.t("audit_trail.messages.jobsupplement"),
jobimported: () => i18n.t("audit_trail.messages.jobimported"), jobimported: () => i18n.t("audit_trail.messages.jobimported"),
jobconverted: (ro_number) => jobconverted: (ro_number) =>
i18n.t("audit_trail.messages.jobconverted", { ro_number }), i18n.t("audit_trail.messages.jobconverted", { ro_number }),
jobfieldchange: (field, value) => jobfieldchange: (field, value) =>
i18n.t("audit_trail.messages.jobfieldchanged", { field, value }), i18n.t("audit_trail.messages.jobfieldchanged", { field, value }),
admin_jobfieldchange: (field, value) =>
"ADMIN: " +
i18n.t("audit_trail.messages.jobfieldchanged", { field, value }),
jobspartsorder: (order_number) => jobspartsorder: (order_number) =>
i18n.t("audit_trail.messages.jobspartsorder", { order_number }), i18n.t("audit_trail.messages.jobspartsorder", { order_number }),
jobspartsreturn: (order_number) => jobspartsreturn: (order_number) =>
@@ -34,11 +29,6 @@ const AuditTrailMapping = {
jobnoteadded: () => i18n.t("audit_trail.messages.jobnoteadded"), jobnoteadded: () => i18n.t("audit_trail.messages.jobnoteadded"),
jobnoteupdated: () => i18n.t("audit_trail.messages.jobnoteupdated"), jobnoteupdated: () => i18n.t("audit_trail.messages.jobnoteupdated"),
jobnotedeleted: () => i18n.t("audit_trail.messages.jobnotedeleted"), jobnotedeleted: () => i18n.t("audit_trail.messages.jobnotedeleted"),
admin_jobunvoid: () => i18n.t("audit_trail.messages.admin_jobunvoid"),
admin_jobmarkforreexport: () =>
i18n.t("audit_trail.messages.admin_jobmarkforreexport"),
admin_jobmarkexported: () =>
i18n.t("audit_trail.messages.admin_jobmarkexported"),
}; };
export default AuditTrailMapping; export default AuditTrailMapping;

View File

@@ -1,7 +1,7 @@
import { gql } from "@apollo/client"; import { gql } from "@apollo/client";
import { notification } from "antd"; import { notification } from "antd";
import axios from "axios"; import axios from "axios";
import jsreport from "jsreport-browser-client-dist"; import jsreport from "@jsreport/browser-client";
import _ from "lodash"; import _ from "lodash";
import moment from "moment"; import moment from "moment";
import { auth } from "../firebase/firebase.utils"; import { auth } from "../firebase/firebase.utils";
@@ -18,14 +18,12 @@ export default async function RenderTemplate(
templateObject, templateObject,
bodyshop, bodyshop,
renderAsHtml = false, renderAsHtml = false,
renderAsExcel = false, renderAsExcel = false
renderAsText = false
) { ) {
//Query assets that match the template name. Must be in format <<templateName>>.query //Query assets that match the template name. Must be in format <<templateName>>.query
let { contextData, useShopSpecificTemplate } = await fetchContextData( let { contextData, useShopSpecificTemplate } = await fetchContextData(
templateObject templateObject
); );
const { ignoreCustomMargins } = Templates[templateObject.name]; const { ignoreCustomMargins } = Templates[templateObject.name];
let reportRequest = { let reportRequest = {
@@ -48,21 +46,19 @@ export default async function RenderTemplate(
marginBottom: marginBottom:
bodyshop.logo_img_path && bodyshop.logo_img_path &&
bodyshop.logo_img_path.footerMargin && bodyshop.logo_img_path.footerMargin &&
bodyshop.logo_img_path.footerMargin > 50 bodyshop.logo_img_path.footerMargin > 36
? bodyshop.logo_img_path.footerMargin ? bodyshop.logo_img_path.footerMargin
: "50px", : "36px",
}, },
}), }),
}), }),
...(renderAsExcel ? { recipe: "html-to-xlsx" } : {}), ...(renderAsExcel ? { recipe: "html-to-xlsx" } : {}),
...(renderAsText ? { recipe: "text" } : {}),
}, },
data: { data: {
...contextData, ...contextData,
...templateObject.variables, ...templateObject.variables,
...templateObject.context, ...templateObject.context,
headerpath: `/${bodyshop.imexshopid}/header.html`, headerpath: `/${bodyshop.imexshopid}/header.html`,
footerpath: `/${bodyshop.imexshopid}/footer.html`,
bodyshop: bodyshop, bodyshop: bodyshop,
offset: bodyshop.timezone, //moment().utcOffset(), offset: bodyshop.timezone, //moment().utcOffset(),
}, },
@@ -160,49 +156,24 @@ export async function RenderTemplates(
marginBottom: marginBottom:
bodyshop.logo_img_path && bodyshop.logo_img_path &&
bodyshop.logo_img_path.footerMargin && bodyshop.logo_img_path.footerMargin &&
bodyshop.logo_img_path.footerMargin > 50 bodyshop.logo_img_path.footerMargin > 36
? bodyshop.logo_img_path.footerMargin ? bodyshop.logo_img_path.footerMargin
: "50px", : "36px",
}, },
}), }),
pdfOperations: [ pdfOperations: templateAndData.map((template) => {
{ return {
template: { template: {
name: "/components/Header-Footer", name: template.useShopSpecificTemplate
recipe: "chrome-pdf", ? `/${bodyshop.imexshopid}/${template.templateObject.name}`
engine: "handlebars", : `/${template.templateObject.name}`,
...(renderAsHtml ? {} : { recipe: "chrome-pdf" }),
}, },
type: "merge", type: "append",
}, mergeWholeDocument: true,
...templateAndData.map((template) => { renderForEveryPage: true,
return { };
template: { }),
chrome: {
marginTop:
bodyshop.logo_img_path &&
bodyshop.logo_img_path.headerMargin &&
bodyshop.logo_img_path.headerMargin > 36
? bodyshop.logo_img_path.headerMargin
: "36px",
marginBottom:
bodyshop.logo_img_path &&
bodyshop.logo_img_path.footerMargin &&
bodyshop.logo_img_path.footerMargin > 50
? bodyshop.logo_img_path.footerMargin
: "50px",
},
name: template.useShopSpecificTemplate
? `/${bodyshop.imexshopid}/${template.templateObject.name}`
: `/${template.templateObject.name}`,
...(renderAsHtml ? {} : { recipe: "chrome-pdf" }),
},
type: "append",
// mergeWholeDocument: true,
// renderForEveryPage: true,
};
}),
],
}, },
data: { data: {
...extend( ...extend(
@@ -213,7 +184,6 @@ export async function RenderTemplates(
// ...rootTemplate.templateObject.variables, // ...rootTemplate.templateObject.variables,
// ...rootTemplate.templateObject.context, // ...rootTemplate.templateObject.context,
headerpath: `/${bodyshop.imexshopid}/header.html`, headerpath: `/${bodyshop.imexshopid}/header.html`,
footerpath: `/${bodyshop.imexshopid}/footer.html`,
bodyshop: bodyshop, bodyshop: bodyshop,
offset: moment().utcOffset(), offset: moment().utcOffset(),
}, },
@@ -256,8 +226,6 @@ export const GenerateDocument = async (
} else if (sendType === "x") { } else if (sendType === "x") {
console.log("excel"); console.log("excel");
await RenderTemplate(template, bodyshop, false, true); await RenderTemplate(template, bodyshop, false, true);
} else if (sendType === "text") {
await RenderTemplate(template, bodyshop, false, false, true);
} else { } else {
await RenderTemplate(template, bodyshop); await RenderTemplate(template, bodyshop);
} }

View File

@@ -314,14 +314,6 @@ export const TemplateList = (type, context) => {
disabled: false, disabled: false,
group: "post", group: "post",
}, },
filing_coversheet_landscape: {
title: i18n.t("printcenter.jobs.filing_coversheet_landscape"),
description: "CASL Authorization",
subject: i18n.t("printcenter.jobs.filing_coversheet_landscape"),
key: "filing_coversheet_landscape",
disabled: false,
group: "post",
},
qc_sheet: { qc_sheet: {
title: i18n.t("printcenter.jobs.qc_sheet"), title: i18n.t("printcenter.jobs.qc_sheet"),
description: "All Jobs Notes", description: "All Jobs Notes",
@@ -484,7 +476,7 @@ export const TemplateList = (type, context) => {
: {}), : {}),
...(!type || type === "job_special" ...(!type || type === "job_special"
? { ? {
special_thirdpartypayer: { thirdpartypayer: {
title: i18n.t("printcenter.jobs.thirdpartypayer"), title: i18n.t("printcenter.jobs.thirdpartypayer"),
description: "CSI invite", description: "CSI invite",
key: "special_thirdpartypayer", key: "special_thirdpartypayer",
@@ -1668,13 +1660,6 @@ export const TemplateList = (type, context) => {
key: "exported_payroll", key: "exported_payroll",
disabled: false, disabled: false,
}, },
attendance_detail_csv: {
title: i18n.t("printcenter.special.attendance_detail_csv"),
description: "Est Detail",
subject: i18n.t("printcenter.special.attendance_detail_csv"),
key: "attendance_detail_csv",
disabled: false,
},
production_by_technician_one: { production_by_technician_one: {
title: i18n.t( title: i18n.t(
"reportcenter.templates.production_by_technician_one" "reportcenter.templates.production_by_technician_one"

View File

@@ -1,6 +0,0 @@
import { store } from "../redux/store";
export function CreateExplorerLinkForJob({ jobid }) {
const bodyshop = store.getState().user.bodyshop;
return `imexmedia://${bodyshop.localmediaservernetwork}/Jobs/${jobid}`;
}

File diff suppressed because it is too large Load Diff

View File

@@ -779,13 +779,6 @@
table: table:
schema: public schema: public
name: timetickets name: timetickets
- name: transitions
using:
foreign_key_constraint_on:
column: bodyshopid
table:
schema: public
name: transitions
- name: vehicles - name: vehicles
using: using:
foreign_key_constraint_on: foreign_key_constraint_on:
@@ -835,8 +828,6 @@
- jc_hourly_rates - jc_hourly_rates
- jobsizelimit - jobsizelimit
- last_name_first - last_name_first
- localmediaserverhttp
- localmediaservernetwork
- logo_img_path - logo_img_path
- md_categories - md_categories
- md_ccc_rates - md_ccc_rates
@@ -860,7 +851,6 @@
- md_referral_sources - md_referral_sources
- md_responsibility_centers - md_responsibility_centers
- md_ro_statuses - md_ro_statuses
- md_to_emails
- messagingservicesid - messagingservicesid
- pbs_configuration - pbs_configuration
- pbs_serialnumber - pbs_serialnumber
@@ -887,7 +877,6 @@
- tt_allow_post_to_invoiced - tt_allow_post_to_invoiced
- updated_at - updated_at
- use_fippa - use_fippa
- uselocalmediaserver
- website - website
- workingdays - workingdays
- zip_post - zip_post
@@ -925,8 +914,6 @@
- intakechecklist - intakechecklist
- jc_hourly_rates - jc_hourly_rates
- last_name_first - last_name_first
- localmediaserverhttp
- localmediaservernetwork
- logo_img_path - logo_img_path
- md_categories - md_categories
- md_ccc_rates - md_ccc_rates
@@ -950,7 +937,6 @@
- md_referral_sources - md_referral_sources
- md_responsibility_centers - md_responsibility_centers
- md_ro_statuses - md_ro_statuses
- md_to_emails
- pbs_configuration - pbs_configuration
- phone - phone
- prodtargethrs - prodtargethrs
@@ -970,7 +956,6 @@
- tt_allow_post_to_invoiced - tt_allow_post_to_invoiced
- updated_at - updated_at
- use_fippa - use_fippa
- uselocalmediaserver
- website - website
- workingdays - workingdays
- zip_post - zip_post
@@ -1961,7 +1946,6 @@
- active - active
- created_at - created_at
- employee_number - employee_number
- external_id
- first_name - first_name
- flat_rate - flat_rate
- hire_date - hire_date
@@ -1980,7 +1964,6 @@
- active - active
- created_at - created_at
- employee_number - employee_number
- external_id
- first_name - first_name
- flat_rate - flat_rate
- hire_date - hire_date
@@ -2009,7 +1992,6 @@
- active - active
- created_at - created_at
- employee_number - employee_number
- external_id
- first_name - first_name
- flat_rate - flat_rate
- hire_date - hire_date
@@ -2614,13 +2596,6 @@
insertion_order: null insertion_order: null
column_mapping: column_mapping:
id: jobid id: jobid
- name: mixdata
using:
foreign_key_constraint_on:
column: jobid
table:
schema: public
name: mixdata
- name: notes - name: notes
using: using:
foreign_key_constraint_on: foreign_key_constraint_on:
@@ -2670,13 +2645,6 @@
table: table:
schema: public schema: public
name: timetickets name: timetickets
- name: transitions
using:
foreign_key_constraint_on:
column: jobid
table:
schema: public
name: transitions
insert_permissions: insert_permissions:
- role: user - role: user
permission: permission:
@@ -3622,84 +3590,6 @@
_eq: X-Hasura-User-Id _eq: X-Hasura-User-Id
- active: - active:
_eq: true _eq: true
- table:
schema: public
name: mixdata
object_relationships:
- name: job
using:
foreign_key_constraint_on: jobid
insert_permissions:
- role: user
permission:
check:
job:
bodyshop:
associations:
_and:
- active:
_eq: true
- user:
authid:
_eq: X-Hasura-User-Id
columns:
- mixdata
- totalliquidcost
- totalsundrycost
- company
- version
- created_at
- updated_at
- id
- jobid
backend_only: false
select_permissions:
- role: user
permission:
columns:
- mixdata
- totalliquidcost
- totalsundrycost
- company
- version
- created_at
- updated_at
- id
- jobid
filter:
job:
bodyshop:
associations:
_and:
- active:
_eq: true
- user:
authid:
_eq: X-Hasura-User-Id
update_permissions:
- role: user
permission:
columns:
- mixdata
- totalliquidcost
- totalsundrycost
- company
- version
- created_at
- updated_at
- id
- jobid
filter:
job:
bodyshop:
associations:
_and:
- active:
_eq: true
- user:
authid:
_eq: X-Hasura-User-Id
check: null
- table: - table:
schema: public schema: public
name: notes name: notes
@@ -3949,7 +3839,6 @@
- act_price - act_price
- backordered_eta - backordered_eta
- backordered_on - backordered_on
- cm_received
- cost - cost
- created_at - created_at
- db_price - db_price
@@ -3970,7 +3859,6 @@
- act_price - act_price
- backordered_eta - backordered_eta
- backordered_on - backordered_on
- cm_received
- cost - cost
- created_at - created_at
- db_price - db_price
@@ -4002,7 +3890,6 @@
- act_price - act_price
- backordered_eta - backordered_eta
- backordered_on - backordered_on
- cm_received
- cost - cost
- created_at - created_at
- db_price - db_price
@@ -4707,93 +4594,6 @@
_eq: X-Hasura-User-Id _eq: X-Hasura-User-Id
- active: - active:
_eq: true _eq: true
- table:
schema: public
name: transitions
object_relationships:
- name: bodyshop
using:
foreign_key_constraint_on: bodyshopid
- name: job
using:
foreign_key_constraint_on: jobid
insert_permissions:
- role: user
permission:
check:
bodyshop:
associations:
_and:
- active:
_eq: true
- user:
authid:
_eq: X-Hasura-User-Id
columns:
- bodyshopid
- created_at
- duration
- end
- id
- jobid
- next_value
- prev_value
- start
- type
- updated_at
- value
backend_only: false
select_permissions:
- role: user
permission:
columns:
- duration
- next_value
- prev_value
- type
- value
- created_at
- end
- start
- updated_at
- bodyshopid
- id
- jobid
filter:
bodyshop:
associations:
_and:
- active:
_eq: true
- user:
authid:
_eq: X-Hasura-User-Id
update_permissions:
- role: user
permission:
columns:
- duration
- next_value
- prev_value
- type
- value
- created_at
- end
- start
- updated_at
- bodyshopid
- id
- jobid
filter:
bodyshop:
associations:
_and:
- active:
_eq: true
- user:
authid:
_eq: X-Hasura-User-Id
check: {}
- table: - table:
schema: public schema: public
name: users name: users

Some files were not shown because too many files have changed in this diff Show More