Compare commits
65 Commits
feature/20
...
feature/20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3e1663bf18 | ||
|
|
9a60149d75 | ||
|
|
54b483333f | ||
|
|
990ec1a553 | ||
|
|
6bd49a461e | ||
|
|
0d30fc0e32 | ||
|
|
7ce4264309 | ||
|
|
5385e6918b | ||
|
|
a8ad65000d | ||
|
|
ae9ca0ac3b | ||
|
|
9fd23e9181 | ||
|
|
a288a1a2a4 | ||
|
|
33e2201524 | ||
|
|
34422dfef7 | ||
|
|
c6635845f5 | ||
|
|
e770232e1d | ||
|
|
51dcf3a7c6 | ||
|
|
afd745917d | ||
|
|
aa8e12ef58 | ||
|
|
41bbda7bcf | ||
|
|
f19289362d | ||
|
|
2d546d92b5 | ||
|
|
1360a73028 | ||
|
|
7de224831f | ||
|
|
e9cda93898 | ||
|
|
2c1f5a9f34 | ||
|
|
d88d7ebebd | ||
|
|
17dcc2efd8 | ||
|
|
3391d7d3f4 | ||
|
|
bccb5e353b | ||
|
|
8e05105917 | ||
|
|
81babca775 | ||
|
|
fe8dd2a920 | ||
|
|
11af41f3c0 | ||
|
|
6a24c10225 | ||
|
|
8c50589eba | ||
|
|
eaa134d474 | ||
|
|
3d61d95e44 | ||
|
|
d9d3c899a1 | ||
|
|
00f71eba77 | ||
|
|
1e547f1815 | ||
|
|
4b7bbe686a | ||
|
|
f744acd131 | ||
|
|
2be61379f8 | ||
|
|
227a1034cd | ||
|
|
33f863e1e6 | ||
|
|
4e161248b3 | ||
|
|
749dfc0fba | ||
|
|
ed00b4550c | ||
|
|
471c918ac3 | ||
|
|
0c23c16f3b | ||
|
|
0adb34b4d3 | ||
|
|
859522b028 | ||
|
|
e6cb804055 | ||
|
|
a218564a24 | ||
|
|
4071abcb56 | ||
|
|
f81e026e12 | ||
|
|
21a1791e7a | ||
|
|
0615e46d8a | ||
|
|
9b881ee11a | ||
|
|
170f03979e | ||
|
|
7c6b2faa1a | ||
|
|
dbe3944089 | ||
|
|
0b50f424fa | ||
|
|
701a52dd22 |
@@ -301,6 +301,27 @@
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>preview</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>reschedule</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
@@ -2993,6 +3014,27 @@
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>attach_pdf_to_email</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>bill_federal_tax_rate</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
@@ -16495,6 +16537,48 @@
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>markpstexempt</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>markpstexemptconfirm</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>postbills</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
@@ -24108,6 +24192,612 @@
|
||||
</folder_node>
|
||||
</children>
|
||||
</folder_node>
|
||||
<folder_node>
|
||||
<name>landing</name>
|
||||
<children>
|
||||
<folder_node>
|
||||
<name>bigfeature</name>
|
||||
<children>
|
||||
<concept_node>
|
||||
<name>subtitle</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>title</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>
|
||||
<name>footer</name>
|
||||
<children>
|
||||
<folder_node>
|
||||
<name>company</name>
|
||||
<children>
|
||||
<concept_node>
|
||||
<name>about</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>contact</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>disclaimers</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>name</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>privacypolicy</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>
|
||||
<name>io</name>
|
||||
<children>
|
||||
<concept_node>
|
||||
<name>help</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>name</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>status</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>
|
||||
<concept_node>
|
||||
<name>slogan</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>
|
||||
<name>hero</name>
|
||||
<children>
|
||||
<concept_node>
|
||||
<name>button</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>title</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>
|
||||
<name>labels</name>
|
||||
<children>
|
||||
<concept_node>
|
||||
<name>features</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>managemyshop</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>pricing</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>
|
||||
<name>pricing</name>
|
||||
<children>
|
||||
<folder_node>
|
||||
<name>basic</name>
|
||||
<children>
|
||||
<concept_node>
|
||||
<name>name</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>sub</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>
|
||||
<name>essentials</name>
|
||||
<children>
|
||||
<concept_node>
|
||||
<name>name</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>sub</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>
|
||||
<concept_node>
|
||||
<name>pricingtitle</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>
|
||||
<folder_node>
|
||||
<name>pro</name>
|
||||
<children>
|
||||
<concept_node>
|
||||
<name>name</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>sub</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>
|
||||
<concept_node>
|
||||
<name>title</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>
|
||||
<folder_node>
|
||||
<name>unlimited</name>
|
||||
<children>
|
||||
<concept_node>
|
||||
<name>name</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>sub</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>
|
||||
</children>
|
||||
</folder_node>
|
||||
</children>
|
||||
</folder_node>
|
||||
<folder_node>
|
||||
<name>menus</name>
|
||||
<children>
|
||||
@@ -29793,6 +30483,48 @@
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>key_tag</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>paint_grid</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>parts_label_single</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
@@ -30087,6 +30819,27 @@
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>stolen_recovery_checklist</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>supplement_request</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
@@ -31857,6 +32610,27 @@
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>gsr_by_csr</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>gsr_by_delivery_date</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
@@ -32298,6 +33072,27 @@
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>open_orders_csr</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>open_orders_estimator</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
|
||||
@@ -12,7 +12,9 @@ module.exports = {
|
||||
modifyVars: {
|
||||
...(process.env.NODE_ENV === "development"
|
||||
? { "@primary-color": "#a51d1d" }
|
||||
: { "@primary-color": "#1DA57A" }),
|
||||
: {
|
||||
//"@primary-color": "#1DA57A"
|
||||
}),
|
||||
// "@primary-color": " #1890ff", // primary color for all components
|
||||
// "@link-color": "#1890ff", // link color
|
||||
// "@success-color": "#52c41a", // success state color
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
"craco-less": "^1.17.1",
|
||||
"dinero.js": "^1.8.1",
|
||||
"dotenv": "^9.0.2",
|
||||
"enquire-js": "^0.2.1",
|
||||
"env-cmd": "^10.1.0",
|
||||
"exifr": "^7.0.0",
|
||||
"firebase": "^8.6.0",
|
||||
@@ -35,6 +36,8 @@
|
||||
"preval.macro": "^5.0.0",
|
||||
"prop-types": "^15.7.2",
|
||||
"query-string": "^7.0.0",
|
||||
"rc-queue-anim": "^1.8.5",
|
||||
"rc-scroll-anim": "^2.7.6",
|
||||
"react": "^17.0.1",
|
||||
"react-big-calendar": "^0.33.2",
|
||||
"react-color": "^2.19.3",
|
||||
@@ -49,6 +52,7 @@
|
||||
"react-resizable": "^3.0.1",
|
||||
"react-router-dom": "^5.2.0",
|
||||
"react-scripts": "^4.0.3",
|
||||
"react-sublime-video": "^0.2.5",
|
||||
"react-virtualized": "^9.22.3",
|
||||
"recharts": "^2.0.7",
|
||||
"redux": "^4.1.0",
|
||||
|
||||
@@ -6,7 +6,6 @@ import moment from "moment";
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import GlobalLoadingBar from "../components/global-loading-bar/global-loading-bar.component";
|
||||
import JiraSupportComponent from "../components/jira-support-widget/jira-support-widget.component";
|
||||
import client from "../utils/GraphQLClient";
|
||||
import App from "./App";
|
||||
moment.locale("en-US");
|
||||
@@ -16,21 +15,6 @@ if (process.env.NODE_ENV === "production") LogRocket.init("gvfvfw/bodyshopapp");
|
||||
export default function AppContainer() {
|
||||
const { t } = useTranslation();
|
||||
|
||||
// useEffect(() => {
|
||||
// // Include the Crisp code here, without the <script></script> tags
|
||||
// window.$crisp = [];
|
||||
// window.CRISP_WEBSITE_ID = "36724f62-2eb0-4b29-9cdd-9905fb99913e";
|
||||
// var d = document;
|
||||
// var s = d.createElement("script");
|
||||
// s.src = "https://client.crisp.chat/l.js";
|
||||
// s.async = 1;
|
||||
// d.getElementsByTagName("head")[0].appendChild(s);
|
||||
|
||||
// return () => {
|
||||
// d.getElementsByTagName("head")[0].removeChild(s);
|
||||
// };
|
||||
// }, []);
|
||||
|
||||
return (
|
||||
<ApolloProvider client={client}>
|
||||
<ConfigProvider
|
||||
@@ -46,7 +30,6 @@ export default function AppContainer() {
|
||||
>
|
||||
<GlobalLoadingBar />
|
||||
<App />
|
||||
<JiraSupportComponent />
|
||||
</ConfigProvider>
|
||||
</ApolloProvider>
|
||||
);
|
||||
|
||||
@@ -8,7 +8,7 @@ import DocumentEditorContainer from "../components/document-editor/document-edit
|
||||
import ErrorBoundary from "../components/error-boundary/error-boundary.component";
|
||||
//Component Imports
|
||||
import LoadingSpinner from "../components/loading-spinner/loading-spinner.component";
|
||||
import AboutPage from "../pages/about/about.page";
|
||||
import DisclaimerPage from "../pages/disclaimer/disclaimer.page";
|
||||
import TechPageContainer from "../pages/tech/tech.page.container";
|
||||
import { setOnline } from "../redux/application/application.actions";
|
||||
import { selectOnline } from "../redux/application/application.selectors";
|
||||
@@ -17,7 +17,7 @@ import { selectCurrentUser } from "../redux/user/user.selectors";
|
||||
import PrivateRoute from "../utils/private-route";
|
||||
import "./App.styles.scss";
|
||||
|
||||
const LandingPage = lazy(() => import("../pages/landing/landing.page"));
|
||||
import LandingPage from "../pages/landing/landing.page";
|
||||
const ResetPassword = lazy(() =>
|
||||
import("../pages/reset-password/reset-password.component")
|
||||
);
|
||||
@@ -100,7 +100,7 @@ export function App({ checkUserSession, currentUser, online, setOnline }) {
|
||||
<Route exact path="/csi/:surveyId" component={CsiPage} />
|
||||
</ErrorBoundary>
|
||||
<ErrorBoundary>
|
||||
<Route exact path="/about" component={AboutPage} />
|
||||
<Route exact path="/disclaimer" component={DisclaimerPage} />
|
||||
</ErrorBoundary>
|
||||
<ErrorBoundary>
|
||||
<Route
|
||||
|
||||
BIN
client/src/assets/ImEX Online Logo - Dark.png
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
client/src/assets/ImEX Online Logo.png
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
client/src/assets/banner-logo.png
Normal file
|
After Width: | Height: | Size: 55 KiB |
BIN
client/src/assets/banner1.jpeg
Normal file
|
After Width: | Height: | Size: 272 KiB |
BIN
client/src/assets/banner2.jpeg
Normal file
|
After Width: | Height: | Size: 237 KiB |
BIN
client/src/assets/banner3.jpeg
Normal file
|
After Width: | Height: | Size: 177 KiB |
5
client/src/assets/icons/technology.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" ?><svg style="enable-background:new 0 0 128 128;" version="1.1" viewBox="0 0 128 128" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><style type="text/css">
|
||||
.st0{fill:none;stroke:#000000;stroke-width:8;stroke-miterlimit:10;}
|
||||
.st1{display:none;}
|
||||
.st2{display:inline;opacity:0.25;fill:#F45EFD;}
|
||||
</style><g id="_x31_2_3D_Printing"/><g id="_x31_1_VR_Gear"/><g id="_x31_0_Virtual_reality"/><g id="_x39__Augmented_reality"/><g id="_x38__Teleport"/><g id="_x37__Glassess"/><g id="_x36__Folding_phone"/><g id="_x35__Drone"/><g id="_x34__Retina_scan"/><g id="_x33__Smartwatch"/><g id="_x32__Bionic_Arm"/><g id="_x31__Chip"><g><path d="M108,40c-5.2,0-9.6,3.3-11.3,8H84V32h-8V20h-8v12h-8V20h-8v12h-8v16H24v-8.7c4.7-1.7,8-6.1,8-11.3c0-6.6-5.4-12-12-12 S8,21.4,8,28c0,5.2,3.3,9.6,8,11.3V56h28v8H16v16.7c-4.7,1.7-8,6.1-8,11.3c0,6.6,5.4,12,12,12s12-5.4,12-12c0-5.2-3.3-9.6-8-11.3 V72h20v16h8v12h8V88h8v12h8V88h8V72h8v16.7c-4.7,1.7-8,6.1-8,11.3c0,6.6,5.4,12,12,12s12-5.4,12-12c0-5.2-3.3-9.6-8-11.3V64H84v-8 h12.7c1.7,4.7,6.1,8,11.3,8c6.6,0,12-5.4,12-12S114.6,40,108,40z M20,32c-2.2,0-4-1.8-4-4s1.8-4,4-4s4,1.8,4,4S22.2,32,20,32z M20,96c-2.2,0-4-1.8-4-4s1.8-4,4-4s4,1.8,4,4S22.2,96,20,96z M76,80H52V40h24V80z M96,96c2.2,0,4,1.8,4,4s-1.8,4-4,4s-4-1.8-4-4 S93.8,96,96,96z M108,56c-2.2,0-4-1.8-4-4s1.8-4,4-4s4,1.8,4,4S110.2,56,108,56z"/><rect height="8" width="8" x="56" y="64"/></g></g><g class="st1" id="Guide"><path class="st2" d="M120,8v112H8V8H120 M128,0H0v128h128V0L128,0z"/></g></svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
@@ -81,6 +81,7 @@ function BillEnterModalContainer({
|
||||
},
|
||||
],
|
||||
},
|
||||
refetchQueries: ["QUERY_PARTS_BILLS_BY_JOBID"],
|
||||
});
|
||||
console.log("adjustmentsToInsert", adjustmentsToInsert);
|
||||
const adjKeys = Object.keys(adjustmentsToInsert);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { HomeFilled } from "@ant-design/icons";
|
||||
import { Breadcrumb } from "antd";
|
||||
import { Breadcrumb, Row, Col } from "antd";
|
||||
import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { Link } from "react-router-dom";
|
||||
@@ -14,27 +14,29 @@ const mapStateToProps = createStructuredSelector({
|
||||
|
||||
export function BreadCrumbs({ breadcrumbs }) {
|
||||
return (
|
||||
<div className="breadcrumb-container imex-flex-row">
|
||||
<Breadcrumb separator=">" style={{ flex: 1 }}>
|
||||
<Breadcrumb.Item>
|
||||
<Link to={`/manage`}>
|
||||
<HomeFilled />
|
||||
</Link>
|
||||
</Breadcrumb.Item>
|
||||
{breadcrumbs.map((item) =>
|
||||
item.link ? (
|
||||
<Breadcrumb.Item key={item.label}>
|
||||
<Link to={item.link}>{item.label} </Link>
|
||||
</Breadcrumb.Item>
|
||||
) : (
|
||||
<Breadcrumb.Item key={item.label}>{item.label}</Breadcrumb.Item>
|
||||
)
|
||||
)}
|
||||
</Breadcrumb>
|
||||
<div>
|
||||
<Row className="breadcrumb-container">
|
||||
<Col xs={24} sm={24} md={16}>
|
||||
<Breadcrumb separator=">">
|
||||
<Breadcrumb.Item>
|
||||
<Link to={`/manage`}>
|
||||
<HomeFilled />
|
||||
</Link>
|
||||
</Breadcrumb.Item>
|
||||
{breadcrumbs.map((item) =>
|
||||
item.link ? (
|
||||
<Breadcrumb.Item key={item.label}>
|
||||
<Link to={item.link}>{item.label} </Link>
|
||||
</Breadcrumb.Item>
|
||||
) : (
|
||||
<Breadcrumb.Item key={item.label}>{item.label}</Breadcrumb.Item>
|
||||
)
|
||||
)}
|
||||
</Breadcrumb>
|
||||
</Col>
|
||||
<Col xs={24} sm={24} md={8}>
|
||||
<GlobalSearch />
|
||||
</div>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
);
|
||||
}
|
||||
export default connect(mapStateToProps, null)(BreadCrumbs);
|
||||
|
||||
@@ -43,6 +43,10 @@ export function EmailOverlayContainer({
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [sending, setSending] = useState(false);
|
||||
const [rawHtml, setRawHtml] = useState("");
|
||||
const [pdfCopytoAttach, setPdfCopytoAttach] = useState({
|
||||
filename: null,
|
||||
pdf: null,
|
||||
});
|
||||
const [selectedMedia, setSelectedMedia] = useState([]);
|
||||
|
||||
const defaultEmailFrom = {
|
||||
@@ -59,17 +63,17 @@ export function EmailOverlayContainer({
|
||||
const handleFinish = async (values) => {
|
||||
logImEXEvent("email_send_from_modal");
|
||||
|
||||
const attachments = [];
|
||||
//const attachments = [];
|
||||
|
||||
if (values.fileList)
|
||||
await asyncForEach(values.fileList, async (f) => {
|
||||
const t = {
|
||||
ContentType: f.type,
|
||||
Filename: f.name,
|
||||
Base64Content: (await toBase64(f.originFileObj)).split(",")[1],
|
||||
};
|
||||
attachments.push(t);
|
||||
});
|
||||
// if (values.fileList)
|
||||
// await asyncForEach(values.fileList, async (f) => {
|
||||
// const t = {
|
||||
// ContentType: f.type,
|
||||
// Filename: f.name,
|
||||
// Base64Content: (await toBase64(f.originFileObj)).split(",")[1],
|
||||
// };
|
||||
// attachments.push(t);
|
||||
// });
|
||||
|
||||
setSending(true);
|
||||
try {
|
||||
@@ -77,11 +81,28 @@ export function EmailOverlayContainer({
|
||||
...defaultEmailFrom,
|
||||
...values,
|
||||
html: rawHtml,
|
||||
attachments:
|
||||
values.fileList &&
|
||||
(await Promise.all(
|
||||
values.fileList.map(async (f) => await toBase64(f.originFileObj))
|
||||
)),
|
||||
attachments: [
|
||||
...(values.fileList
|
||||
? await Promise.all(
|
||||
values.fileList.map(async (f) => {
|
||||
return {
|
||||
filename: f.name,
|
||||
path: await toBase64(f.originFileObj),
|
||||
};
|
||||
})
|
||||
)
|
||||
: []),
|
||||
...(pdfCopytoAttach.pdf
|
||||
? [
|
||||
{
|
||||
path: pdfCopytoAttach.pdf,
|
||||
filename:
|
||||
pdfCopytoAttach.filename &&
|
||||
`${pdfCopytoAttach.filename}.pdf`,
|
||||
},
|
||||
]
|
||||
: []),
|
||||
],
|
||||
media: selectedMedia.filter((m) => m.isSelected).map((m) => m.src),
|
||||
//attachments,
|
||||
});
|
||||
@@ -99,13 +120,22 @@ export function EmailOverlayContainer({
|
||||
const render = async () => {
|
||||
logImEXEvent("email_render_template", { template: emailConfig.template });
|
||||
setLoading(true);
|
||||
let html = await RenderTemplate(emailConfig.template, bodyshop, true);
|
||||
let { html, pdf, filename } = await RenderTemplate(
|
||||
emailConfig.template,
|
||||
bodyshop,
|
||||
true
|
||||
);
|
||||
|
||||
const response = await axios.post("/render/inlinecss", {
|
||||
html: html,
|
||||
url: `${window.location.protocol}://${window.location.host}/`,
|
||||
});
|
||||
setRawHtml(response.data);
|
||||
|
||||
if (pdf) {
|
||||
setPdfCopytoAttach({ pdf, filename });
|
||||
}
|
||||
|
||||
form.setFieldsValue({
|
||||
...emailConfig.messageOptions,
|
||||
cc:
|
||||
@@ -166,8 +196,8 @@ const toBase64 = (file) =>
|
||||
reader.onerror = (error) => reject(error);
|
||||
});
|
||||
|
||||
const asyncForEach = async (array, callback) => {
|
||||
for (let index = 0; index < array.length; index++) {
|
||||
await callback(array[index], index, array);
|
||||
}
|
||||
};
|
||||
// const asyncForEach = async (array, callback) => {
|
||||
// for (let index = 0; index < array.length; index++) {
|
||||
// await callback(array[index], index, array);
|
||||
// }
|
||||
// };
|
||||
|
||||
@@ -37,7 +37,7 @@ export default function GlobalSearch() {
|
||||
value: job.ro_number,
|
||||
label: (
|
||||
<Link to={`/manage/jobs/${job.id}`}>
|
||||
<Space wrap split={<Divider type="vertical" />}>
|
||||
<Space size="small" split={<Divider type="vertical" />}>
|
||||
<strong>{job.ro_number || t("general.labels.na")}</strong>
|
||||
<span>{`${job.ownr_fn || ""} ${job.ownr_ln || ""} ${
|
||||
job.ownr_co_nm || ""
|
||||
@@ -45,7 +45,7 @@ export default function GlobalSearch() {
|
||||
<span>{`${job.v_model_yr || ""} ${job.v_make_desc || ""} ${
|
||||
job.v_model_desc || ""
|
||||
}`}</span>
|
||||
<span>{`${job.clm_no}`}</span>
|
||||
<span>{`${job.clm_no || ""}`}</span>
|
||||
</Space>
|
||||
</Link>
|
||||
),
|
||||
@@ -62,7 +62,7 @@ export default function GlobalSearch() {
|
||||
}`,
|
||||
label: (
|
||||
<Link to={`/manage/owners/${owner.id}`}>
|
||||
<Space wrap split={<Divider type="vertical" />}>
|
||||
<Space size="small" split={<Divider type="vertical" />}>
|
||||
<span>{`${owner.ownr_fn || ""} ${owner.ownr_ln || ""} ${
|
||||
owner.ownr_co_nm || ""
|
||||
}`}</span>
|
||||
@@ -85,14 +85,14 @@ export default function GlobalSearch() {
|
||||
} ${vehicle.v_model_desc || ""}`,
|
||||
label: (
|
||||
<Link to={`/manage/vehicles/${vehicle.id}`}>
|
||||
<Space wrap split={<Divider type="vertical" />}>
|
||||
<Space size="small" split={<Divider type="vertical" />}>
|
||||
<span>
|
||||
{`${vehicle.v_model_yr || ""} ${
|
||||
vehicle.v_make_desc || ""
|
||||
} ${vehicle.v_model_desc || ""}`}
|
||||
</span>
|
||||
<span>{vehicle.plate_no}</span>
|
||||
<span> {vehicle.v_vin}</span>
|
||||
<span>{vehicle.plate_no || ""}</span>
|
||||
<span> {vehicle.v_vin || ""}</span>
|
||||
</Space>
|
||||
</Link>
|
||||
),
|
||||
@@ -107,11 +107,12 @@ export default function GlobalSearch() {
|
||||
value: `${payment.job.ro_number} ${payment.payer} ${payment.amount}`,
|
||||
label: (
|
||||
<Link to={`/manage/jobs/${payment.job.id}`}>
|
||||
<Space wrap split={<Divider type="vertical" />}>
|
||||
<Space size="small" split={<Divider type="vertical" />}>
|
||||
<span>{payment.paymentnum}</span>
|
||||
<span>{payment.job.ro_number}</span>
|
||||
<span>{payment.job.memo}</span>
|
||||
<span>{payment.job.amount}</span>
|
||||
<span>{payment.job.transactionid}</span>
|
||||
<span>{payment.memo || ""}</span>
|
||||
<span>{payment.amount || ""}</span>
|
||||
<span>{payment.transactionid || ""}</span>
|
||||
</Space>
|
||||
</Link>
|
||||
),
|
||||
@@ -126,7 +127,7 @@ export default function GlobalSearch() {
|
||||
value: `${bill.invoice_number} - ${bill.vendor.name}`,
|
||||
label: (
|
||||
<Link to={`/manage/bills?billid=${bill.id}`}>
|
||||
<Space wrap split={<Divider type="vertical" />}>
|
||||
<Space size="small" split={<Divider type="vertical" />}>
|
||||
<span>{bill.invoice_number}</span>
|
||||
<span>{bill.vendor.name}</span>
|
||||
<span>{bill.date}</span>
|
||||
@@ -146,7 +147,7 @@ export default function GlobalSearch() {
|
||||
}`,
|
||||
label: (
|
||||
<Link to={`/manage/phonebook?phonebookentry=${pb.id}`}>
|
||||
<Space wrap split={<Divider type="vertical" />}>
|
||||
<Space size="small" split={<Divider type="vertical" />}>
|
||||
<span>{`${pb.firstname || ""} ${pb.lastname || ""} ${
|
||||
pb.company || ""
|
||||
}`}</span>
|
||||
@@ -165,8 +166,6 @@ export default function GlobalSearch() {
|
||||
|
||||
return (
|
||||
<AutoComplete
|
||||
key="globalsearch"
|
||||
dropdownMatchSelectWidth={"false"}
|
||||
options={options}
|
||||
onSearch={handleSearch}
|
||||
allowClear
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
import React from "react";
|
||||
|
||||
export default function JiraSupportComponent() {
|
||||
//useScript();
|
||||
|
||||
return <div></div>;
|
||||
}
|
||||
|
||||
// const useScript = () => {
|
||||
// useEffect(() => {
|
||||
// const script = document.createElement("script");
|
||||
// script.src = "https://jsd-widget.atlassian.com/assets/embed.js";
|
||||
// script.setAttribute("data-jsd-embedded", true);
|
||||
// script.setAttribute("data-key", "d69bb65c-1dd3-483f-b109-66a970d03f44");
|
||||
// script.setAttribute("data-base-url", "https://jsd-widget.atlassian.com");
|
||||
// //script.async = true;
|
||||
// script.onload = () => {
|
||||
// var DOMContentLoaded_event = document.createEvent("Event");
|
||||
// DOMContentLoaded_event.initEvent("DOMContentLoaded", true, true);
|
||||
// window.document.dispatchEvent(DOMContentLoaded_event);
|
||||
// };
|
||||
// document.head.appendChild(script);
|
||||
|
||||
// return () => {
|
||||
// document.head.removeChild(script);
|
||||
// };
|
||||
// }, []);
|
||||
// };
|
||||
@@ -2,7 +2,7 @@ import { Button, Popover, Space } from "antd";
|
||||
import React, { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import { Link } from "react-router-dom";
|
||||
import { Link, useHistory, useLocation } from "react-router-dom";
|
||||
import { setModalContext } from "../../redux/modals/modals.actions";
|
||||
import CurrencyFormatter from "../../utils/CurrencyFormatter";
|
||||
import PhoneFormatter from "../../utils/PhoneFormatter";
|
||||
@@ -11,6 +11,8 @@ import { TemplateList } from "../../utils/TemplateConstants";
|
||||
import DataLabel from "../data-label/data-label.component";
|
||||
import ScheduleAtChange from "./job-at-change.component";
|
||||
import ScheduleEventColor from "./schedule-event.color.component";
|
||||
import queryString from "query-string";
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
setScheduleContext: (context) =>
|
||||
dispatch(setModalContext({ context: context, modal: "schedule" })),
|
||||
@@ -24,6 +26,8 @@ export function ScheduleEventComponent({
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const [visible, setVisible] = useState(false);
|
||||
const history = useHistory();
|
||||
const searchParams = queryString.parse(useLocation().search);
|
||||
|
||||
const blockContent = (
|
||||
<div>
|
||||
@@ -88,6 +92,20 @@ export function ScheduleEventComponent({
|
||||
<Button>{t("appointments.actions.viewjob")}</Button>
|
||||
</Link>
|
||||
) : null}
|
||||
{event.job ? (
|
||||
<Button
|
||||
onClick={() => {
|
||||
history.push({
|
||||
search: queryString.stringify({
|
||||
...searchParams,
|
||||
selected: event.job.id,
|
||||
}),
|
||||
});
|
||||
}}
|
||||
>
|
||||
{t("appointments.actions.preview")}
|
||||
</Button>
|
||||
) : null}
|
||||
<Button
|
||||
onClick={() => {
|
||||
const Template = TemplateList("job").appointment_reminder;
|
||||
|
||||
@@ -295,18 +295,18 @@ export function JobLinesComponent({
|
||||
onClick={async () => {
|
||||
await deleteJobLine({
|
||||
variables: { joblineId: record.id },
|
||||
update(cache) {
|
||||
cache.modify({
|
||||
id: cache.identify(job),
|
||||
fields: {
|
||||
joblines(existingJobLines, { readField }) {
|
||||
return existingJobLines.filter(
|
||||
(jlRef) => record.id !== readField("id", jlRef)
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
||||
},
|
||||
// update(cache) {
|
||||
// cache.modify({
|
||||
// id: cache.identify(job),
|
||||
// fields: {
|
||||
// joblines(existingJobLines, { readField }) {
|
||||
// return existingJobLines.filter(
|
||||
// (jlRef) => record.id !== readField("id", jlRef)
|
||||
// );
|
||||
// },
|
||||
// },
|
||||
// });
|
||||
// },
|
||||
});
|
||||
await axios.post("/job/totalsssu", {
|
||||
id: job.id,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Button, Card, Space, Table } from "antd";
|
||||
import { EditFilled } from "@ant-design/icons";
|
||||
import Dinero from "dinero.js";
|
||||
import React, { useMemo, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
@@ -115,16 +116,29 @@ export function JobPayments({
|
||||
dataIndex: "actions",
|
||||
key: "actions",
|
||||
render: (text, record) => (
|
||||
<PrintWrapperComponent
|
||||
templateObject={{
|
||||
name: TemplateList("payment").payment_receipt.key,
|
||||
variables: { id: record.id },
|
||||
}}
|
||||
messageObject={{
|
||||
to: job.ownr_ea,
|
||||
}}
|
||||
id={job.id}
|
||||
/>
|
||||
<Space wrap>
|
||||
<Button
|
||||
disabled={record.exportedat}
|
||||
onClick={() => {
|
||||
setPaymentContext({
|
||||
actions: { refetch: refetch },
|
||||
context: record,
|
||||
});
|
||||
}}
|
||||
>
|
||||
<EditFilled />
|
||||
</Button>
|
||||
<PrintWrapperComponent
|
||||
templateObject={{
|
||||
name: TemplateList("payment").payment_receipt.key,
|
||||
variables: { id: record.id },
|
||||
}}
|
||||
messageObject={{
|
||||
to: job.ownr_ea,
|
||||
}}
|
||||
id={job.id}
|
||||
/>
|
||||
</Space>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Checkbox, PageHeader, Table } from "antd";
|
||||
import { Checkbox, Table, Typography } from "antd";
|
||||
import React, { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import CurrencyFormatter from "../../utils/CurrencyFormatter";
|
||||
@@ -21,6 +21,7 @@ export default function JobReconciliationBillsTable({
|
||||
title: t("billlines.fields.line_desc"),
|
||||
dataIndex: "line_desc",
|
||||
key: "line_desc",
|
||||
width: "35%",
|
||||
sorter: (a, b) => alphaSort(a.line_desc, b.line_desc),
|
||||
sortOrder:
|
||||
state.sortedInfo.columnKey === "line_desc" && state.sortedInfo.order,
|
||||
@@ -29,6 +30,8 @@ export default function JobReconciliationBillsTable({
|
||||
title: t("billlines.labels.from"),
|
||||
dataIndex: "from",
|
||||
key: "from",
|
||||
width: "20%",
|
||||
ellipsis: true,
|
||||
render: (text, record) =>
|
||||
`${record.bill.vendor && record.bill.vendor.name} / ${
|
||||
record.bill.invoice_number
|
||||
@@ -57,7 +60,7 @@ export default function JobReconciliationBillsTable({
|
||||
),
|
||||
},
|
||||
{
|
||||
title: t("billlines.fields.quantity"),
|
||||
title: t("joblines.fields.part_qty"),
|
||||
dataIndex: "quantity",
|
||||
key: "quantity",
|
||||
sorter: (a, b) => a.quantity - b.quantity,
|
||||
@@ -86,10 +89,12 @@ export default function JobReconciliationBillsTable({
|
||||
};
|
||||
|
||||
return (
|
||||
<PageHeader title={t("bills.labels.bills")}>
|
||||
<div>
|
||||
<Typography.Title level={4}>{t("bills.labels.bills")}</Typography.Title>
|
||||
<Table
|
||||
pagination={false}
|
||||
scroll={{ y: "40vh", x: true }}
|
||||
size="small"
|
||||
scroll={{ y: "80vh", x: true }}
|
||||
columns={columns}
|
||||
rowKey="id"
|
||||
dataSource={invoiceLineData}
|
||||
@@ -99,6 +104,6 @@ export default function JobReconciliationBillsTable({
|
||||
selectedRowKeys: selectedLines,
|
||||
}}
|
||||
/>
|
||||
</PageHeader>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -22,21 +22,23 @@ export default function JobReconciliationModalComponent({ job, bills }) {
|
||||
);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Row gutter={[16, 16]}>
|
||||
<Col span={12}>
|
||||
<JobReconciliationPartsTable
|
||||
jobLineData={jobLineData}
|
||||
jobLineState={jobLineState}
|
||||
/>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<JobReconciliationBillsTable
|
||||
invoiceLineData={invoiceLineData}
|
||||
billLineState={billLineState}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
<div style={{ flex: 1, display: "flex", flexDirection: "column" }}>
|
||||
<div style={{ flex: 1 }}>
|
||||
<Row gutter={8}>
|
||||
<Col span={12}>
|
||||
<JobReconciliationPartsTable
|
||||
jobLineData={jobLineData}
|
||||
jobLineState={jobLineState}
|
||||
/>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<JobReconciliationBillsTable
|
||||
invoiceLineData={invoiceLineData}
|
||||
billLineState={billLineState}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
<Row>
|
||||
<JobReconciliationTotals
|
||||
jobLines={jobLineData}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
.imex-reconciliation-modal {
|
||||
top: 20px;
|
||||
.ant-modal-content {
|
||||
height: 95vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.ant-modal-body {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import { selectReconciliation } from "../../redux/modals/modals.selectors";
|
||||
import JobReconciliationModalComponent from "./job-reconciliation-modal.component";
|
||||
import LoadingSpinner from "../loading-spinner/loading-spinner.component";
|
||||
import AlertComponent from "../alert/alert.component";
|
||||
import "./job-reconciliation-modal.styles.scss";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
reconciliationModal: selectReconciliation,
|
||||
@@ -38,23 +39,23 @@ function JobReconciliationModalContainer({
|
||||
return (
|
||||
<Modal
|
||||
title={t("jobs.labels.reconciliationheader")}
|
||||
width={"90%"}
|
||||
width={"95%"}
|
||||
visible={visible}
|
||||
okText={t("general.actions.close")}
|
||||
onOk={handleCancel}
|
||||
onCancel={handleCancel}
|
||||
cancelButtonProps={{ display: "none" }}
|
||||
destroyOnClose
|
||||
className="imex-reconciliation-modal"
|
||||
>
|
||||
<LoadingSpinner loading={loading}>
|
||||
{error && <AlertComponent message={error.message} type="error" />}
|
||||
{data && (
|
||||
<JobReconciliationModalComponent
|
||||
job={data && data.jobs_by_pk}
|
||||
bills={data && data.bills}
|
||||
/>
|
||||
)}
|
||||
</LoadingSpinner>
|
||||
{loading && <LoadingSpinner loading={loading} />}
|
||||
{error && <AlertComponent message={error.message} type="error" />}
|
||||
{data && (
|
||||
<JobReconciliationModalComponent
|
||||
job={data && data.jobs_by_pk}
|
||||
bills={data && data.bills}
|
||||
/>
|
||||
)}
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { PageHeader, Table } from "antd";
|
||||
import { Table, Typography } from "antd";
|
||||
import React, { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import CurrencyFormatter from "../../utils/CurrencyFormatter";
|
||||
@@ -102,11 +102,13 @@ export default function JobReconcilitionPartsTable({
|
||||
};
|
||||
|
||||
return (
|
||||
<PageHeader title={t("jobs.labels.lines")}>
|
||||
<div>
|
||||
<Typography.Title level={4}>{t("jobs.labels.lines")}</Typography.Title>
|
||||
<Table
|
||||
pagination={false}
|
||||
columns={columns}
|
||||
scroll={{ y: "40vh", x: true }}
|
||||
size="small"
|
||||
scroll={{ y: "80vh", x: true }}
|
||||
rowKey="id"
|
||||
dataSource={jobLineData}
|
||||
onChange={handleTableChange}
|
||||
@@ -122,6 +124,6 @@ export default function JobReconcilitionPartsTable({
|
||||
<div style={{ fontStyle: "italic", margin: "4px" }}>
|
||||
{t("jobs.labels.reconciliation.removedpartsstrikethrough")}
|
||||
</div>
|
||||
</PageHeader>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { LoadingOutlined } from "@ant-design/icons";
|
||||
import { useLazyQuery } from "@apollo/client";
|
||||
import { Empty, Select } from "antd";
|
||||
import { Empty, Select, Space, Tag } from "antd";
|
||||
import _ from "lodash";
|
||||
import React, { forwardRef, useEffect } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
@@ -80,13 +80,20 @@ const JobSearchSelect = (
|
||||
{theOptions
|
||||
? theOptions.map((o) => (
|
||||
<Option key={o.id} value={o.id} status={o.status}>
|
||||
{`${clm_no && o.clm_no ? `${o.clm_no} | ` : ""}${
|
||||
o.ro_number || t("general.labels.na")
|
||||
} | ${o.ownr_ln || ""} ${o.ownr_fn || ""} ${
|
||||
o.ownr_co_nm ? ` ${o.ownr_co_num}` : ""
|
||||
}| ${o.v_model_yr || ""} ${o.v_make_desc || ""} ${
|
||||
o.v_model_desc || ""
|
||||
}`}
|
||||
<Space align="center">
|
||||
<span>
|
||||
{`${clm_no && o.clm_no ? `${o.clm_no} | ` : ""}${
|
||||
o.ro_number || t("general.labels.na")
|
||||
} | ${o.ownr_ln || ""} ${o.ownr_fn || ""} ${
|
||||
o.ownr_co_nm ? ` ${o.ownr_co_num}` : ""
|
||||
}| ${o.v_model_yr || ""} ${o.v_make_desc || ""} ${
|
||||
o.v_model_desc || ""
|
||||
}`}
|
||||
</span>
|
||||
<Tag>
|
||||
<strong>{o.status}</strong>
|
||||
</Tag>
|
||||
</Space>
|
||||
</Option>
|
||||
))
|
||||
: null}
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
import { DownCircleFilled } from "@ant-design/icons";
|
||||
import { useMutation } from "@apollo/client";
|
||||
import { Button, Dropdown, Menu, notification } from "antd";
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { UPDATE_JOB_STATUS } from "../../graphql/jobs.queries";
|
||||
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)(JobsAdminStatus);
|
||||
|
||||
export function JobsAdminStatus({ bodyshop, job }) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [mutationUpdateJobstatus] = useMutation(UPDATE_JOB_STATUS);
|
||||
const updateJobStatus = (status) => {
|
||||
mutationUpdateJobstatus({
|
||||
variables: { jobId: job.id, status: status },
|
||||
})
|
||||
.then((r) => {
|
||||
notification["success"]({ message: t("jobs.successes.save") });
|
||||
// refetch();
|
||||
})
|
||||
.catch((error) => {
|
||||
notification["error"]({ message: t("jobs.errors.saving") });
|
||||
});
|
||||
};
|
||||
|
||||
const statusmenu = (
|
||||
<Menu
|
||||
onClick={(e) => {
|
||||
updateJobStatus(e.key);
|
||||
}}
|
||||
>
|
||||
{bodyshop.md_ro_statuses.statuses.map((item) => (
|
||||
<Menu.Item key={item}>{item}</Menu.Item>
|
||||
))}
|
||||
</Menu>
|
||||
);
|
||||
|
||||
return (
|
||||
<Dropdown overlay={statusmenu} trigger={["click"]} key="changestatus">
|
||||
<Button shape="round">
|
||||
<span>{job.status}</span>
|
||||
|
||||
<DownCircleFilled />
|
||||
</Button>
|
||||
</Dropdown>
|
||||
);
|
||||
}
|
||||
@@ -11,6 +11,7 @@ export const GetSupplementDelta = async (client, jobId, newLines) => {
|
||||
query: GET_ALL_JOBLINES_BY_PK,
|
||||
variables: { id: jobId },
|
||||
});
|
||||
|
||||
const existingLines = _.cloneDeep(existingLinesFromDb);
|
||||
const linesToInsert = [];
|
||||
const linesToUpdate = [];
|
||||
@@ -19,11 +20,14 @@ export const GetSupplementDelta = async (client, jobId, newLines) => {
|
||||
const matchingIndex = existingLines.findIndex(
|
||||
(eL) => eL.unq_seq === newLine.unq_seq
|
||||
);
|
||||
|
||||
//Should do a check to make sure there is only 1 matching unq sequence number.
|
||||
|
||||
if (matchingIndex >= 0) {
|
||||
//Found a relevant matching line. Add it to lines to update.
|
||||
linesToUpdate.push({
|
||||
id: existingLines[matchingIndex].id,
|
||||
newData: newLine,
|
||||
newData: { ...newLine, removed: false },
|
||||
});
|
||||
|
||||
//Splice out item we found for performance.
|
||||
|
||||
@@ -11,7 +11,8 @@ import FormItemPhone, {
|
||||
PhoneItemFormatterValidation,
|
||||
} from "../form-items-formatted/phone-form-item.component";
|
||||
import JobsDetailRatesChangeButton from "../jobs-detail-rates-change-button/jobs-detail-rates-change-button.component";
|
||||
import { JobsDetailRatesParts } from "../jobs-detail-rates/jobs-detail-rates.parts.component";
|
||||
import JobsDetailRatesParts from "../jobs-detail-rates/jobs-detail-rates.parts.component";
|
||||
import JobsMarkPstExempt from "../jobs-mark-pst-exempt/jobs-mark-pst-exempt.component";
|
||||
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
//currentUser: selectCurrentUser
|
||||
@@ -187,7 +188,7 @@ export function JobsCreateJobsInfo({ bodyshop, form, selected }) {
|
||||
header={t("menus.jobsdetail.financials")}
|
||||
>
|
||||
<JobsDetailRatesChangeButton form={form} />
|
||||
|
||||
<JobsMarkPstExempt form={form} />
|
||||
<LayoutFormRow>
|
||||
<Form.Item label={t("jobs.fields.ded_amt")} name="ded_amt">
|
||||
<CurrencyInput />
|
||||
|
||||
@@ -181,7 +181,7 @@ export function JobsDetailHeaderActions({
|
||||
{job.inproduction ? (
|
||||
<Menu.Item
|
||||
key="addtoproduction"
|
||||
disabled={!!!job.converted || jobRO}
|
||||
disabled={!job.converted}
|
||||
onClick={() => AddToProduction(client, job.id, refetch, true)}
|
||||
>
|
||||
{t("jobs.actions.removefromproduction")}
|
||||
@@ -189,7 +189,7 @@ export function JobsDetailHeaderActions({
|
||||
) : (
|
||||
<Menu.Item
|
||||
key="addtoproduction"
|
||||
disabled={!!!job.converted || !!job.inproduction || jobRO}
|
||||
disabled={!job.converted}
|
||||
onClick={() => AddToProduction(client, job.id, refetch)}
|
||||
>
|
||||
{t("jobs.actions.addtoproduction")}
|
||||
|
||||
@@ -1,4 +1,13 @@
|
||||
import { Form, Input, InputNumber, Select, Space, Switch, Tooltip } from "antd";
|
||||
import {
|
||||
Divider,
|
||||
Form,
|
||||
Input,
|
||||
InputNumber,
|
||||
Select,
|
||||
Space,
|
||||
Switch,
|
||||
Tooltip,
|
||||
} from "antd";
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
@@ -7,6 +16,7 @@ import { selectJobReadOnly } from "../../redux/application/application.selectors
|
||||
import CABCpvrtCalculator from "../ca-bc-pvrt-calculator/ca-bc-pvrt-calculator.component";
|
||||
import CurrencyInput from "../form-items-formatted/currency-form-item.component";
|
||||
import JobsDetailRatesChangeButton from "../jobs-detail-rates-change-button/jobs-detail-rates-change-button.component";
|
||||
import JobsMarkPstExempt from "../jobs-mark-pst-exempt/jobs-mark-pst-exempt.component";
|
||||
import FormRow from "../layout-form-row/layout-form-row.component";
|
||||
import JobsDetailRatesParts from "./jobs-detail-rates.parts.component";
|
||||
|
||||
@@ -103,8 +113,19 @@ export function JobsDetailRates({ jobRO, form, job }) {
|
||||
<Switch disabled={jobRO} />
|
||||
</Form.Item>
|
||||
</FormRow>
|
||||
<JobsDetailRatesChangeButton form={form} disabled={jobRO} />
|
||||
<FormRow header={t("jobs.forms.laborrates")}>
|
||||
<Divider
|
||||
orientation="left"
|
||||
type="horizontal"
|
||||
style={{ marginTop: ".8rem", float: "right" }}
|
||||
>
|
||||
{t("jobs.forms.laborrates")}
|
||||
</Divider>
|
||||
<Space>
|
||||
<div></div>
|
||||
<JobsDetailRatesChangeButton form={form} disabled={jobRO} />
|
||||
<JobsMarkPstExempt form={form} />
|
||||
</Space>
|
||||
<FormRow noDivider>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.labor_rate_desc")}
|
||||
name="labor_rate_desc"
|
||||
@@ -180,7 +201,6 @@ export function JobsDetailRates({ jobRO, form, job }) {
|
||||
<CurrencyInput disabled={jobRO} />
|
||||
</Form.Item>
|
||||
</FormRow>
|
||||
|
||||
<JobsDetailRatesParts form={form} />
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -19,7 +19,11 @@ export function JobsDetailRatesParts({
|
||||
|
||||
return (
|
||||
<Collapse defaultActiveKey={expanded && "rates"}>
|
||||
<Collapse.Panel header={t("jobs.labels.parts_tax_rates")} key="rates">
|
||||
<Collapse.Panel
|
||||
forceRender
|
||||
header={t("jobs.labels.parts_tax_rates")}
|
||||
key="rates"
|
||||
>
|
||||
<LayoutFormRow header={t("joblines.fields.part_types.PAA")}>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.parts_tax_rates.prt_discp")}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
import { Popconfirm, Button } from "antd";
|
||||
import React from "react";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { selectJobReadOnly } from "../../redux/application/application.selectors";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import _ from "lodash";
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop,
|
||||
jobRO: selectJobReadOnly,
|
||||
});
|
||||
|
||||
export function JobsMarkPstExempt({ jobRO, form }) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const handleConfirm = () => {
|
||||
const newPartRates = _.cloneDeep(form.getFieldValue("parts_tax_rates"));
|
||||
|
||||
Object.keys(newPartRates).forEach((key) => {
|
||||
newPartRates[key] = {
|
||||
...newPartRates[key],
|
||||
prt_tax_in: false,
|
||||
prt_tax_rt: 0,
|
||||
};
|
||||
});
|
||||
|
||||
form.setFieldsValue({
|
||||
state_tax_rate: 0,
|
||||
tax_lbr_rt: 0,
|
||||
tax_levies_rt: 0,
|
||||
tax_sub_rt: 0,
|
||||
tax_shop_mat_rt: 0,
|
||||
tax_paint_mat_rt: 0,
|
||||
tax_str_rt: 0,
|
||||
tax_tow_rt: 0,
|
||||
parts_tax_rates: newPartRates,
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<Popconfirm
|
||||
onConfirm={handleConfirm}
|
||||
disabled={jobRO}
|
||||
okText={t("general.labels.yes")}
|
||||
cancelText={t("general.labels.no")}
|
||||
title={t("jobs.actions.markpstexemptconfirm")}
|
||||
>
|
||||
<Button type="link" disabled={jobRO}>
|
||||
{t("jobs.actions.markpstexempt")}
|
||||
</Button>
|
||||
</Popconfirm>
|
||||
);
|
||||
}
|
||||
export default connect(mapStateToProps, null)(JobsMarkPstExempt);
|
||||
@@ -31,11 +31,14 @@ function OwnerDetailJobsComponent({ bodyshop, owner }) {
|
||||
title: t("jobs.fields.vehicle"),
|
||||
dataIndex: "vehicleid",
|
||||
key: "vehicleid",
|
||||
render: (text, record) => (
|
||||
<Link to={`/manage/vehicles/${record.vehicleid}`}>
|
||||
{`${record.v_model_yr} ${record.v_make_desc} ${record.v_model_desc}`}
|
||||
</Link>
|
||||
),
|
||||
render: (text, record) =>
|
||||
record.vehicleid ? (
|
||||
<Link to={`/manage/vehicles/${record.vehicleid}`}>
|
||||
{`${record.v_model_yr} ${record.v_make_desc} ${record.v_model_desc}`}
|
||||
</Link>
|
||||
) : (
|
||||
t("jobs.errors.novehicle")
|
||||
),
|
||||
},
|
||||
{
|
||||
title: t("jobs.fields.clm_no"),
|
||||
|
||||
@@ -90,7 +90,11 @@ export function PartsOrderListTableComponent({
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
disabled={jobRO || record.return}
|
||||
disabled={
|
||||
jobRO ||
|
||||
record.return ||
|
||||
record.vendor.id === bodyshop.inhousevendorid
|
||||
}
|
||||
onClick={() => {
|
||||
logImEXEvent("parts_order_receive_bill");
|
||||
setPartsReceiveContext({
|
||||
@@ -139,7 +143,10 @@ export function PartsOrderListTableComponent({
|
||||
</Button>
|
||||
</Popconfirm>
|
||||
<Button
|
||||
disabled={jobRO ? !record.return : jobRO}
|
||||
disabled={
|
||||
(jobRO ? !record.return : jobRO) ||
|
||||
record.vendor.id === bodyshop.inhousevendorid
|
||||
}
|
||||
onClick={() => {
|
||||
logImEXEvent("parts_order_receive_bill");
|
||||
|
||||
@@ -157,7 +164,7 @@ export function PartsOrderListTableComponent({
|
||||
quantity: pol.quantity,
|
||||
|
||||
actual_price: pol.act_price,
|
||||
cost_center: pol.jobline.part_type
|
||||
cost_center: pol.jobline?.part_type
|
||||
? responsibilityCenters.defaults.costs[
|
||||
pol.jobline.part_type
|
||||
] || null
|
||||
|
||||
@@ -101,7 +101,9 @@ export function PartsOrderModalContainer({
|
||||
|
||||
const jobLinesResult = await updateJobLines({
|
||||
variables: {
|
||||
ids: values.parts_order_lines.data.map((item) => item.job_line_id),
|
||||
ids: values.parts_order_lines.data
|
||||
.filter((item) => item.job_line_id)
|
||||
.map((item) => item.job_line_id),
|
||||
status: isReturn
|
||||
? bodyshop.md_order_statuses.default_returned || "Returned*"
|
||||
: bodyshop.md_order_statuses.default_ordered || "Ordered*",
|
||||
|
||||
@@ -9,6 +9,7 @@ import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
import Event from "../job-at-change/schedule-event.container";
|
||||
import HeaderComponent from "./schedule-calendar-header.component";
|
||||
import "./schedule-calendar.styles.scss";
|
||||
import JobDetailCards from "../job-detail-cards/job-detail-cards.component";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop,
|
||||
@@ -45,45 +46,48 @@ export function ScheduleCalendarWrapperComponent({
|
||||
const selectedDate = new Date(date || moment(search.date) || Date.now());
|
||||
|
||||
return (
|
||||
<Calendar
|
||||
events={data}
|
||||
defaultView={search.view || defaultView || "week"}
|
||||
date={selectedDate}
|
||||
onNavigate={(date, view, action) => {
|
||||
search.date = date.toISOString().substr(0, 10);
|
||||
history.push({ search: queryString.stringify(search) });
|
||||
}}
|
||||
onRangeChange={(start, end) => {
|
||||
if (setDateRangeCallback) setDateRangeCallback({ start, end });
|
||||
}}
|
||||
onView={(view) => {
|
||||
search.view = view;
|
||||
history.push({ search: queryString.stringify(search) });
|
||||
}}
|
||||
step={15}
|
||||
// timeslots={1}
|
||||
showMultiDayTimes
|
||||
localizer={localizer}
|
||||
min={
|
||||
bodyshop.schedule_start_time
|
||||
? new Date(bodyshop.schedule_start_time)
|
||||
: new Date("2020-01-01T06:00:00")
|
||||
}
|
||||
max={
|
||||
bodyshop.schedule_end_time
|
||||
? new Date(bodyshop.schedule_end_time)
|
||||
: new Date("2020-01-01T20:00:00")
|
||||
}
|
||||
eventPropGetter={handleEventPropStyles}
|
||||
components={{
|
||||
event: (e) =>
|
||||
Event({ bodyshop: bodyshop, event: e.event, refetch: refetch }),
|
||||
header: (p) => (
|
||||
<HeaderComponent {...p} events={data} refetch={refetch} />
|
||||
),
|
||||
}}
|
||||
{...otherProps}
|
||||
/>
|
||||
<>
|
||||
<JobDetailCards />
|
||||
<Calendar
|
||||
events={data}
|
||||
defaultView={search.view || defaultView || "week"}
|
||||
date={selectedDate}
|
||||
onNavigate={(date, view, action) => {
|
||||
search.date = date.toISOString().substr(0, 10);
|
||||
history.push({ search: queryString.stringify(search) });
|
||||
}}
|
||||
onRangeChange={(start, end) => {
|
||||
if (setDateRangeCallback) setDateRangeCallback({ start, end });
|
||||
}}
|
||||
onView={(view) => {
|
||||
search.view = view;
|
||||
history.push({ search: queryString.stringify(search) });
|
||||
}}
|
||||
step={15}
|
||||
// timeslots={1}
|
||||
showMultiDayTimes
|
||||
localizer={localizer}
|
||||
min={
|
||||
bodyshop.schedule_start_time
|
||||
? new Date(bodyshop.schedule_start_time)
|
||||
: new Date("2020-01-01T06:00:00")
|
||||
}
|
||||
max={
|
||||
bodyshop.schedule_end_time
|
||||
? new Date(bodyshop.schedule_end_time)
|
||||
: new Date("2020-01-01T20:00:00")
|
||||
}
|
||||
eventPropGetter={handleEventPropStyles}
|
||||
components={{
|
||||
event: (e) =>
|
||||
Event({ bodyshop: bodyshop, event: e.event, refetch: refetch }),
|
||||
header: (p) => (
|
||||
<HeaderComponent {...p} events={data} refetch={refetch} />
|
||||
),
|
||||
}}
|
||||
{...otherProps}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ export default function ScheduleCalendarComponent({ data, refetch }) {
|
||||
return (
|
||||
<Row gutter={[16, 16]}>
|
||||
<ScheduleModal />
|
||||
|
||||
<Col span={24}>
|
||||
<PageHeader
|
||||
extra={
|
||||
|
||||
@@ -436,6 +436,14 @@ export default function ShopInfoGeneral({ form }) {
|
||||
>
|
||||
<CurrencyInput />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name={["attach_pdf_to_email"]}
|
||||
label={t("bodyshop.fields.attach_pdf_to_email")}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
</LayoutFormRow>
|
||||
<LayoutFormRow grow header={t("bodyshop.labels.messagingpresets")}>
|
||||
<Form.List name={["md_messaging_presets"]}>
|
||||
|
||||
@@ -91,6 +91,7 @@ export const QUERY_BODYSHOP = gql`
|
||||
md_jobline_presets
|
||||
cdk_dealerid
|
||||
features
|
||||
attach_pdf_to_email
|
||||
employees {
|
||||
id
|
||||
active
|
||||
@@ -178,6 +179,7 @@ export const UPDATE_SHOP = gql`
|
||||
jc_hourly_rates
|
||||
md_jobline_presets
|
||||
cdk_dealerid
|
||||
attach_pdf_to_email
|
||||
employees {
|
||||
id
|
||||
first_name
|
||||
|
||||
@@ -23,19 +23,6 @@ export const GET_ALL_JOBLINES_BY_PK = gql`
|
||||
notes
|
||||
location
|
||||
tax_part
|
||||
parts_order_lines {
|
||||
id
|
||||
parts_order {
|
||||
id
|
||||
order_number
|
||||
order_date
|
||||
user_email
|
||||
vendor {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
@@ -228,7 +215,11 @@ export const generateJobLinesUpdatesForInvoicing = (joblines) => {
|
||||
|
||||
export const DELETE_JOB_LINE_BY_PK = gql`
|
||||
mutation DELETE_JOB_LINE_BY_PK($joblineId: uuid!) {
|
||||
delete_joblines_by_pk(id: $joblineId) {
|
||||
update_joblines_by_pk(
|
||||
pk_columns: { id: $joblineId }
|
||||
_set: { removed: true }
|
||||
) {
|
||||
removed
|
||||
id
|
||||
}
|
||||
}
|
||||
|
||||
@@ -559,6 +559,7 @@ export const GET_JOB_BY_PK = gql`
|
||||
}
|
||||
payments {
|
||||
id
|
||||
jobid
|
||||
amount
|
||||
payer
|
||||
created_at
|
||||
@@ -566,6 +567,8 @@ export const GET_JOB_BY_PK = gql`
|
||||
transactionid
|
||||
memo
|
||||
date
|
||||
type
|
||||
exportedat
|
||||
}
|
||||
cccontracts {
|
||||
id
|
||||
@@ -686,6 +689,8 @@ export const QUERY_JOB_CARD_DETAILS = gql`
|
||||
v_make_desc
|
||||
v_model_desc
|
||||
v_color
|
||||
v_vin
|
||||
plate_st
|
||||
plate_no
|
||||
vehicle {
|
||||
id
|
||||
@@ -1040,6 +1045,7 @@ export const SEARCH_JOBS_FOR_AUTOCOMPLETE = gql`
|
||||
v_make_desc
|
||||
v_model_desc
|
||||
v_model_yr
|
||||
status
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -36,6 +36,7 @@ export const GLOBAL_SEARCH_QUERY = gql`
|
||||
search_payments(args: { search: $search }) {
|
||||
id
|
||||
amount
|
||||
paymentnum
|
||||
job {
|
||||
ro_number
|
||||
id
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
import { AlertOutlined } from "@ant-design/icons";
|
||||
import * as Sentry from "@sentry/react";
|
||||
import { Button, notification, Space } from "antd";
|
||||
//import "antd/dist/antd.css";
|
||||
import "antd/dist/antd.less";
|
||||
import Dinero from "dinero.js";
|
||||
import i18n from "i18next";
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import { Provider } from "react-redux";
|
||||
@@ -15,7 +12,6 @@ import LoadingSpinner from "./components/loading-spinner/loading-spinner.compone
|
||||
import "./index.css";
|
||||
import { persistor, store } from "./redux/store";
|
||||
import reportWebVitals from "./reportWebVitals";
|
||||
import * as serviceWorkerRegistration from "./serviceWorkerRegistration";
|
||||
import "./translations/i18n";
|
||||
import "./utils/CleanAxios";
|
||||
require("dotenv").config();
|
||||
@@ -52,44 +48,44 @@ ReactDOM.render(
|
||||
document.getElementById("root")
|
||||
);
|
||||
|
||||
const onServiceWorkerUpdate = (registration) => {
|
||||
console.log("onServiceWorkerUpdate", registration);
|
||||
// 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",
|
||||
});
|
||||
};
|
||||
// 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 });
|
||||
// serviceWorkerRegistration.register({ onUpdate: onServiceWorkerUpdate });
|
||||
reportWebVitals();
|
||||
|
||||
53
client/src/landing/Banner0.jsx
Normal file
@@ -0,0 +1,53 @@
|
||||
import React from 'react';
|
||||
import { Button } from 'antd';
|
||||
import { DownOutlined } from '@ant-design/icons';
|
||||
import QueueAnim from 'rc-queue-anim';
|
||||
import TweenOne from 'rc-tween-one';
|
||||
import { isImg } from './utils';
|
||||
|
||||
class Banner extends React.PureComponent {
|
||||
render() {
|
||||
const { ...currentProps } = this.props;
|
||||
const { dataSource } = currentProps;
|
||||
delete currentProps.dataSource;
|
||||
delete currentProps.isMobile;
|
||||
return (
|
||||
<div {...currentProps} {...dataSource.wrapper}>
|
||||
<QueueAnim
|
||||
key="QueueAnim"
|
||||
type={['bottom', 'top']}
|
||||
delay={200}
|
||||
{...dataSource.textWrapper}
|
||||
>
|
||||
<div key="title" {...dataSource.title}>
|
||||
{typeof dataSource.title.children === 'string' &&
|
||||
dataSource.title.children.match(isImg) ? (
|
||||
<img src={dataSource.title.children} width="100%" alt="img" />
|
||||
) : (
|
||||
dataSource.title.children
|
||||
)}
|
||||
</div>
|
||||
<div key="content" {...dataSource.content}>
|
||||
{dataSource.content.children}
|
||||
</div>
|
||||
<Button ghost key="button" {...dataSource.button}>
|
||||
{dataSource.button.children}
|
||||
</Button>
|
||||
</QueueAnim>
|
||||
<TweenOne
|
||||
animation={{
|
||||
y: '-=20',
|
||||
yoyo: true,
|
||||
repeat: -1,
|
||||
duration: 1000,
|
||||
}}
|
||||
className="banner0-icon"
|
||||
key="icon"
|
||||
>
|
||||
<DownOutlined />
|
||||
</TweenOne>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
export default Banner;
|
||||
49
client/src/landing/Content0.jsx
Normal file
@@ -0,0 +1,49 @@
|
||||
import React from 'react';
|
||||
import QueueAnim from 'rc-queue-anim';
|
||||
import { Row, Col } from 'antd';
|
||||
import OverPack from 'rc-scroll-anim/lib/ScrollOverPack';
|
||||
import { getChildrenToRender } from './utils';
|
||||
|
||||
class Content extends React.PureComponent {
|
||||
render() {
|
||||
const { dataSource, isMobile, ...props } = this.props;
|
||||
const {
|
||||
wrapper,
|
||||
titleWrapper,
|
||||
page,
|
||||
OverPack: overPackData,
|
||||
childWrapper,
|
||||
} = dataSource;
|
||||
return (
|
||||
<div {...props} {...wrapper}>
|
||||
<div {...page}>
|
||||
<div {...titleWrapper}>
|
||||
{titleWrapper.children.map(getChildrenToRender)}
|
||||
</div>
|
||||
<OverPack {...overPackData}>
|
||||
<QueueAnim
|
||||
type="bottom"
|
||||
key="block"
|
||||
leaveReverse
|
||||
component={Row}
|
||||
componentProps={childWrapper}
|
||||
>
|
||||
{childWrapper.children.map((block, i) => {
|
||||
const { children: item, ...blockProps } = block;
|
||||
return (
|
||||
<Col key={i.toString()} {...blockProps}>
|
||||
<div {...item}>
|
||||
{item.children.map(getChildrenToRender)}
|
||||
</div>
|
||||
</Col>
|
||||
);
|
||||
})}
|
||||
</QueueAnim>
|
||||
</OverPack>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Content;
|
||||
70
client/src/landing/Content1.jsx
Normal file
@@ -0,0 +1,70 @@
|
||||
import React from 'react';
|
||||
import QueueAnim from 'rc-queue-anim';
|
||||
import TweenOne from 'rc-tween-one';
|
||||
import { Row, Col } from 'antd';
|
||||
import OverPack from 'rc-scroll-anim/lib/ScrollOverPack';
|
||||
|
||||
function Content1(props) {
|
||||
const { ...tagProps } = props;
|
||||
const { dataSource, isMobile } = tagProps;
|
||||
delete tagProps.dataSource;
|
||||
delete tagProps.isMobile;
|
||||
const animType = {
|
||||
queue: isMobile ? 'bottom' : 'right',
|
||||
one: isMobile
|
||||
? {
|
||||
scaleY: '+=0.3',
|
||||
opacity: 0,
|
||||
type: 'from',
|
||||
ease: 'easeOutQuad',
|
||||
}
|
||||
: {
|
||||
x: '-=30',
|
||||
opacity: 0,
|
||||
type: 'from',
|
||||
ease: 'easeOutQuad',
|
||||
},
|
||||
};
|
||||
return (
|
||||
<div {...tagProps} {...dataSource.wrapper}>
|
||||
<OverPack {...dataSource.OverPack} component={Row}>
|
||||
<TweenOne
|
||||
key="img"
|
||||
animation={animType.one}
|
||||
resetStyle
|
||||
{...dataSource.imgWrapper}
|
||||
component={Col}
|
||||
componentProps={{
|
||||
md: dataSource.imgWrapper.md,
|
||||
xs: dataSource.imgWrapper.xs,
|
||||
}}
|
||||
>
|
||||
<span {...dataSource.img}>
|
||||
<img src={dataSource.img.children} width="100%" alt="img" />
|
||||
</span>
|
||||
</TweenOne>
|
||||
<QueueAnim
|
||||
key="text"
|
||||
type={animType.queue}
|
||||
leaveReverse
|
||||
ease={['easeOutQuad', 'easeInQuad']}
|
||||
{...dataSource.textWrapper}
|
||||
component={Col}
|
||||
componentProps={{
|
||||
md: dataSource.textWrapper.md,
|
||||
xs: dataSource.textWrapper.xs,
|
||||
}}
|
||||
>
|
||||
<h2 key="h1" {...dataSource.title}>
|
||||
{dataSource.title.children}
|
||||
</h2>
|
||||
<div key="p" {...dataSource.content}>
|
||||
{dataSource.content.children}
|
||||
</div>
|
||||
</QueueAnim>
|
||||
</OverPack>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Content1;
|
||||
60
client/src/landing/Content12.jsx
Normal file
@@ -0,0 +1,60 @@
|
||||
import React from 'react';
|
||||
import { Row, Col } from 'antd';
|
||||
import { TweenOneGroup } from 'rc-tween-one';
|
||||
import OverPack from 'rc-scroll-anim/lib/ScrollOverPack';
|
||||
import { getChildrenToRender } from './utils';
|
||||
|
||||
class Content12 extends React.PureComponent {
|
||||
getChildrenToRender = (data) =>
|
||||
data.map((item) => {
|
||||
return (
|
||||
<Col key={item.name} {...item}>
|
||||
<div {...item.children.wrapper}>
|
||||
<span {...item.children.img}>
|
||||
<img src={item.children.img.children} alt="img" />
|
||||
</span>
|
||||
</div>
|
||||
</Col>
|
||||
);
|
||||
});
|
||||
|
||||
render() {
|
||||
const { ...props } = this.props;
|
||||
const { dataSource } = props;
|
||||
delete props.dataSource;
|
||||
delete props.isMobile;
|
||||
const childrenToRender = this.getChildrenToRender(
|
||||
dataSource.block.children
|
||||
);
|
||||
return (
|
||||
<div {...props} {...dataSource.wrapper}>
|
||||
<div {...dataSource.page}>
|
||||
<div key="title" {...dataSource.titleWrapper}>
|
||||
{dataSource.titleWrapper.children.map(getChildrenToRender)}
|
||||
</div>
|
||||
<OverPack
|
||||
className={`content-template ${props.className}`}
|
||||
{...dataSource.OverPack}
|
||||
>
|
||||
<TweenOneGroup
|
||||
component={Row}
|
||||
key="ul"
|
||||
enter={{
|
||||
y: '+=30',
|
||||
opacity: 0,
|
||||
type: 'from',
|
||||
ease: 'easeOutQuad',
|
||||
}}
|
||||
leave={{ y: '+=30', opacity: 0, ease: 'easeOutQuad' }}
|
||||
{...dataSource.block}
|
||||
>
|
||||
{childrenToRender}
|
||||
</TweenOneGroup>
|
||||
</OverPack>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Content12;
|
||||
94
client/src/landing/Content3.jsx
Normal file
@@ -0,0 +1,94 @@
|
||||
import React from 'react';
|
||||
import QueueAnim from 'rc-queue-anim';
|
||||
import TweenOne from 'rc-tween-one';
|
||||
import { Row, Col } from 'antd';
|
||||
import OverPack from 'rc-scroll-anim/lib/ScrollOverPack';
|
||||
import { getChildrenToRender } from './utils';
|
||||
|
||||
class Content3 extends React.PureComponent {
|
||||
getDelay = (e, b) => (e % b) * 100 + Math.floor(e / b) * 100 + b * 100;
|
||||
|
||||
render() {
|
||||
const { ...props } = this.props;
|
||||
const { dataSource, isMobile } = props;
|
||||
delete props.dataSource;
|
||||
delete props.isMobile;
|
||||
let clearFloatNum = 0;
|
||||
const children = dataSource.block.children.map((item, i) => {
|
||||
const childObj = item.children;
|
||||
const delay = isMobile ? i * 50 : this.getDelay(i, 24 / item.md);
|
||||
const liAnim = {
|
||||
opacity: 0,
|
||||
type: 'from',
|
||||
ease: 'easeOutQuad',
|
||||
delay,
|
||||
};
|
||||
const childrenAnim = { ...liAnim, x: '+=10', delay: delay + 100 };
|
||||
clearFloatNum += item.md;
|
||||
clearFloatNum = clearFloatNum > 24 ? 0 : clearFloatNum;
|
||||
return (
|
||||
<TweenOne
|
||||
component={Col}
|
||||
animation={liAnim}
|
||||
key={item.name}
|
||||
{...item}
|
||||
componentProps={{ md: item.md, xs: item.xs }}
|
||||
className={
|
||||
!clearFloatNum
|
||||
? `${item.className || ''} clear-both`.trim()
|
||||
: item.className
|
||||
}
|
||||
>
|
||||
<TweenOne
|
||||
animation={{
|
||||
x: '-=10',
|
||||
opacity: 0,
|
||||
type: 'from',
|
||||
ease: 'easeOutQuad',
|
||||
}}
|
||||
key="img"
|
||||
{...childObj.icon}
|
||||
>
|
||||
<img src={childObj.icon.children} width="100%" alt="img" />
|
||||
</TweenOne>
|
||||
<div {...childObj.textWrapper}>
|
||||
<TweenOne
|
||||
key="h2"
|
||||
animation={childrenAnim}
|
||||
component="h2"
|
||||
{...childObj.title}
|
||||
>
|
||||
{childObj.title.children}
|
||||
</TweenOne>
|
||||
<TweenOne
|
||||
key="p"
|
||||
animation={{ ...childrenAnim, delay: delay + 200 }}
|
||||
component="div"
|
||||
{...childObj.content}
|
||||
>
|
||||
{childObj.content.children}
|
||||
</TweenOne>
|
||||
</div>
|
||||
</TweenOne>
|
||||
);
|
||||
});
|
||||
return (
|
||||
<div {...props} {...dataSource.wrapper}>
|
||||
<div {...dataSource.page}>
|
||||
<div {...dataSource.titleWrapper}>
|
||||
{dataSource.titleWrapper.children.map(getChildrenToRender)}
|
||||
</div>
|
||||
<OverPack {...dataSource.OverPack}>
|
||||
<QueueAnim key="u" type="bottom">
|
||||
<Row key="row" {...dataSource.block}>
|
||||
{children}
|
||||
</Row>
|
||||
</QueueAnim>
|
||||
</OverPack>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Content3;
|
||||
59
client/src/landing/Content4.jsx
Normal file
@@ -0,0 +1,59 @@
|
||||
import React from 'react';
|
||||
import TweenOne from 'rc-tween-one';
|
||||
import OverPack from 'rc-scroll-anim/lib/ScrollOverPack';
|
||||
import VideoPlay from 'react-sublime-video';
|
||||
import { getChildrenToRender } from './utils';
|
||||
|
||||
function Content4(props) {
|
||||
const { ...tagProps } = props;
|
||||
const { dataSource, isMobile } = tagProps;
|
||||
delete tagProps.dataSource;
|
||||
delete tagProps.isMobile;
|
||||
const animation = {
|
||||
y: '+=30',
|
||||
opacity: 0,
|
||||
type: 'from',
|
||||
ease: 'easeOutQuad',
|
||||
};
|
||||
const videoChildren = dataSource.video.children.video;
|
||||
const videoNameArray = videoChildren.split('.');
|
||||
const type = videoNameArray[videoNameArray.length - 1];
|
||||
return (
|
||||
<div {...tagProps} {...dataSource.wrapper}>
|
||||
<div {...dataSource.page}>
|
||||
<div key="title" {...dataSource.titleWrapper}>
|
||||
{dataSource.titleWrapper.children.map(getChildrenToRender)}
|
||||
</div>
|
||||
<OverPack {...dataSource.OverPack}>
|
||||
<TweenOne
|
||||
key="video"
|
||||
animation={{ ...animation, delay: 300 }}
|
||||
{...dataSource.video}
|
||||
>
|
||||
{isMobile ? (
|
||||
<video
|
||||
width="100%"
|
||||
loop
|
||||
controls
|
||||
poster={dataSource.video.children.image}
|
||||
>
|
||||
<source src={videoChildren} type={`video/${type}`} />
|
||||
<track kind="captions" />
|
||||
</video>
|
||||
) : (
|
||||
<VideoPlay
|
||||
loop
|
||||
width="100%"
|
||||
poster={dataSource.video.children.image}
|
||||
>
|
||||
<source src={videoChildren} type={`video/${type}`} />
|
||||
</VideoPlay>
|
||||
)}
|
||||
</TweenOne>
|
||||
</OverPack>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Content4;
|
||||
69
client/src/landing/Footer1.jsx
Normal file
@@ -0,0 +1,69 @@
|
||||
import React from 'react';
|
||||
import TweenOne from 'rc-tween-one';
|
||||
import OverPack from 'rc-scroll-anim/lib/ScrollOverPack';
|
||||
import QueueAnim from 'rc-queue-anim';
|
||||
import { Row, Col } from 'antd';
|
||||
import { getChildrenToRender } from './utils';
|
||||
import { isImg } from './utils';
|
||||
|
||||
class Footer extends React.Component {
|
||||
static defaultProps = {
|
||||
className: 'footer1',
|
||||
};
|
||||
|
||||
getLiChildren = (data) =>
|
||||
data.map((item, i) => {
|
||||
const { title, childWrapper, ...itemProps } = item;
|
||||
return (
|
||||
<Col key={i.toString()} {...itemProps} title={null} content={null}>
|
||||
<h2 {...title}>
|
||||
{typeof title.children === 'string' &&
|
||||
title.children.match(isImg) ? (
|
||||
<img src={title.children} width="100%" alt="img" />
|
||||
) : (
|
||||
title.children
|
||||
)}
|
||||
</h2>
|
||||
<div {...childWrapper}>
|
||||
{childWrapper.children.map(getChildrenToRender)}
|
||||
</div>
|
||||
</Col>
|
||||
);
|
||||
});
|
||||
|
||||
render() {
|
||||
const { ...props } = this.props;
|
||||
const { dataSource } = props;
|
||||
delete props.dataSource;
|
||||
delete props.isMobile;
|
||||
const childrenToRender = this.getLiChildren(dataSource.block.children);
|
||||
return (
|
||||
<div {...props} {...dataSource.wrapper}>
|
||||
<OverPack {...dataSource.OverPack}>
|
||||
<QueueAnim
|
||||
type="bottom"
|
||||
key="ul"
|
||||
leaveReverse
|
||||
component={Row}
|
||||
{...dataSource.block}
|
||||
>
|
||||
{childrenToRender}
|
||||
</QueueAnim>
|
||||
<TweenOne
|
||||
animation={{ y: '+=30', opacity: 0, type: 'from' }}
|
||||
key="copyright"
|
||||
{...dataSource.copyrightWrapper}
|
||||
>
|
||||
<div {...dataSource.copyrightPage}>
|
||||
<div {...dataSource.copyright}>
|
||||
{dataSource.copyright.children}
|
||||
</div>
|
||||
</div>
|
||||
</TweenOne>
|
||||
</OverPack>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Footer;
|
||||
135
client/src/landing/Nav0.jsx
Normal file
@@ -0,0 +1,135 @@
|
||||
import React from 'react';
|
||||
import TweenOne from 'rc-tween-one';
|
||||
import { Menu } from 'antd';
|
||||
import { getChildrenToRender } from './utils';
|
||||
|
||||
const { Item, SubMenu } = Menu;
|
||||
|
||||
class Header extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
phoneOpen: undefined,
|
||||
};
|
||||
}
|
||||
|
||||
phoneClick = () => {
|
||||
const phoneOpen = !this.state.phoneOpen;
|
||||
this.setState({
|
||||
phoneOpen,
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const { dataSource, isMobile, ...props } = this.props;
|
||||
const { phoneOpen } = this.state;
|
||||
const navData = dataSource.Menu.children;
|
||||
const navChildren = navData.map((item) => {
|
||||
const { children: a, subItem, ...itemProps } = item;
|
||||
if (subItem) {
|
||||
return (
|
||||
<SubMenu
|
||||
key={item.name}
|
||||
{...itemProps}
|
||||
title={
|
||||
<div
|
||||
{...a}
|
||||
className={`header0-item-block ${a.className}`.trim()}
|
||||
>
|
||||
{a.children.map(getChildrenToRender)}
|
||||
</div>
|
||||
}
|
||||
popupClassName="header0-item-child"
|
||||
>
|
||||
{subItem.map(($item, ii) => {
|
||||
const { children: childItem } = $item;
|
||||
const child = childItem.href ? (
|
||||
<a {...childItem}>
|
||||
{childItem.children.map(getChildrenToRender)}
|
||||
</a>
|
||||
) : (
|
||||
<div {...childItem}>
|
||||
{childItem.children.map(getChildrenToRender)}
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
<Item key={$item.name || ii.toString()} {...$item}>
|
||||
{child}
|
||||
</Item>
|
||||
);
|
||||
})}
|
||||
</SubMenu>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<Item key={item.name} {...itemProps}>
|
||||
<a {...a} className={`header0-item-block ${a.className}`.trim()}>
|
||||
{a.children.map(getChildrenToRender)}
|
||||
</a>
|
||||
</Item>
|
||||
);
|
||||
});
|
||||
const moment = phoneOpen === undefined ? 300 : null;
|
||||
return (
|
||||
<TweenOne
|
||||
component="header"
|
||||
animation={{ opacity: 0, type: 'from' }}
|
||||
{...dataSource.wrapper}
|
||||
{...props}
|
||||
>
|
||||
<div
|
||||
{...dataSource.page}
|
||||
className={`${dataSource.page.className}${phoneOpen ? ' open' : ''}`}
|
||||
>
|
||||
<TweenOne
|
||||
animation={{ x: -30, type: 'from', ease: 'easeOutQuad' }}
|
||||
{...dataSource.logo}
|
||||
>
|
||||
<img width="100%" src={dataSource.logo.children} alt="img" />
|
||||
</TweenOne>
|
||||
{isMobile && (
|
||||
<div
|
||||
{...dataSource.mobileMenu}
|
||||
onClick={() => {
|
||||
this.phoneClick();
|
||||
}}
|
||||
>
|
||||
<em />
|
||||
<em />
|
||||
<em />
|
||||
</div>
|
||||
)}
|
||||
<TweenOne
|
||||
{...dataSource.Menu}
|
||||
animation={
|
||||
isMobile
|
||||
? {
|
||||
height: 0,
|
||||
duration: 300,
|
||||
onComplete: (e) => {
|
||||
if (this.state.phoneOpen) {
|
||||
e.target.style.height = 'auto';
|
||||
}
|
||||
},
|
||||
ease: 'easeInOutQuad',
|
||||
}
|
||||
: null
|
||||
}
|
||||
moment={moment}
|
||||
reverse={!!phoneOpen}
|
||||
>
|
||||
<Menu
|
||||
mode={isMobile ? 'inline' : 'horizontal'}
|
||||
defaultSelectedKeys={['sub0']}
|
||||
theme="dark"
|
||||
>
|
||||
{navChildren}
|
||||
</Menu>
|
||||
</TweenOne>
|
||||
</div>
|
||||
</TweenOne>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Header;
|
||||
73
client/src/landing/Pricing1.jsx
Normal file
@@ -0,0 +1,73 @@
|
||||
import React from 'react';
|
||||
import OverPack from 'rc-scroll-anim/lib/ScrollOverPack';
|
||||
import QueueAnim from 'rc-queue-anim';
|
||||
import { Row, Col, Button } from 'antd';
|
||||
import { getChildrenToRender } from './utils';
|
||||
|
||||
class Pricing1 extends React.PureComponent {
|
||||
getChildrenToRender = (item) => {
|
||||
const {
|
||||
wrapper,
|
||||
topWrapper,
|
||||
name,
|
||||
buttonWrapper,
|
||||
line,
|
||||
content,
|
||||
money,
|
||||
} = item.children;
|
||||
return (
|
||||
<Col key={item.name} {...item}>
|
||||
<QueueAnim type="bottom" {...wrapper}>
|
||||
<div {...topWrapper}>
|
||||
<div {...name} key="name">
|
||||
{name.children}
|
||||
</div>
|
||||
<h1 {...money} key="money">
|
||||
{money.children}
|
||||
</h1>
|
||||
</div>
|
||||
<div {...content} key="content">
|
||||
{content.children}
|
||||
</div>
|
||||
<i {...line} key="line" />
|
||||
<div {...buttonWrapper} key="button">
|
||||
<Button {...buttonWrapper.children.a}>
|
||||
{buttonWrapper.children.a.children}
|
||||
</Button>
|
||||
</div>
|
||||
</QueueAnim>
|
||||
</Col>
|
||||
);
|
||||
};
|
||||
|
||||
render() {
|
||||
const { ...props } = this.props;
|
||||
const { dataSource } = props;
|
||||
delete props.dataSource;
|
||||
delete props.isMobile;
|
||||
const { block } = dataSource;
|
||||
const childrenToRender = block.children.map(this.getChildrenToRender);
|
||||
return (
|
||||
<div {...props} {...dataSource.wrapper}>
|
||||
<div {...dataSource.page}>
|
||||
<div key="title" {...dataSource.titleWrapper}>
|
||||
{dataSource.titleWrapper.children.map(getChildrenToRender)}
|
||||
</div>
|
||||
<OverPack {...dataSource.OverPack}>
|
||||
<QueueAnim
|
||||
type="bottom"
|
||||
component={Row}
|
||||
leaveReverse
|
||||
ease={['easeOutQuad', 'easeInOutQuad']}
|
||||
key="content"
|
||||
>
|
||||
{childrenToRender}
|
||||
</QueueAnim>
|
||||
</OverPack>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Pricing1;
|
||||
114
client/src/landing/Pricing2.jsx
Normal file
@@ -0,0 +1,114 @@
|
||||
import React from 'react';
|
||||
import OverPack from 'rc-scroll-anim/lib/ScrollOverPack';
|
||||
import QueueAnim from 'rc-queue-anim';
|
||||
import { Table } from 'antd';
|
||||
import { getChildrenToRender, isImg } from './utils';
|
||||
|
||||
class Pricing2 extends React.PureComponent {
|
||||
getColumns = (columns) => {
|
||||
return columns.map((item) => {
|
||||
const { childWrapper, ...$item } = item;
|
||||
return {
|
||||
align: 'center',
|
||||
...$item,
|
||||
title: (
|
||||
<div {...childWrapper}>
|
||||
{childWrapper.children.map(getChildrenToRender)}
|
||||
</div>
|
||||
),
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
getDataSource = (dataSource, columns) =>
|
||||
dataSource.map((item, i) => {
|
||||
const obj = { key: i.toString() };
|
||||
item.children.forEach(($item, ii) => {
|
||||
if (columns[ii]) {
|
||||
obj[columns[ii].key] = (
|
||||
<div {...$item}>
|
||||
{typeof $item.children === 'string' &&
|
||||
$item.children.match(isImg) ? (
|
||||
<img src={$item.children} alt="img" />
|
||||
) : (
|
||||
$item.children
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
return obj;
|
||||
});
|
||||
|
||||
getMobileChild = (table) => {
|
||||
const { columns, dataSource, ...tableProps } = table;
|
||||
const names = columns.children.filter(
|
||||
(item) => item.key.indexOf('name') >= 0
|
||||
);
|
||||
const newColumns = columns.children.filter(
|
||||
(item) => item.key.indexOf('name') === -1
|
||||
);
|
||||
return newColumns.map((item, i) => {
|
||||
const items = [].concat(names[0], item).filter((c) => c);
|
||||
if (items.length > 1) {
|
||||
items[0].colSpan = 0;
|
||||
items[1].colSpan = 2;
|
||||
}
|
||||
const dataSources = dataSource.children.map(($item) => {
|
||||
const child = $item.children.filter(
|
||||
(c) => c.name.indexOf('name') === -1
|
||||
);
|
||||
const n = $item.children.filter((c) => c.name.indexOf('name') >= 0);
|
||||
return {
|
||||
...$item,
|
||||
children: [].concat(n[0], child[i]).filter((c) => c),
|
||||
};
|
||||
});
|
||||
const props = {
|
||||
...tableProps,
|
||||
columns: this.getColumns(items),
|
||||
dataSource: this.getDataSource(dataSources, items),
|
||||
};
|
||||
return (
|
||||
<Table key={i.toString()} {...props} pagination={false} bordered />
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const { dataSource, isMobile, ...props } = this.props;
|
||||
const { Table: table, wrapper, page, titleWrapper } = dataSource;
|
||||
const { columns, dataSource: tableData, ...$table } = table;
|
||||
const tableProps = {
|
||||
...$table,
|
||||
columns: this.getColumns(columns.children),
|
||||
dataSource: this.getDataSource(tableData.children, columns.children),
|
||||
};
|
||||
const childrenToRender = isMobile ? (
|
||||
this.getMobileChild(table)
|
||||
) : (
|
||||
<Table key="table" {...tableProps} pagination={false} bordered />
|
||||
);
|
||||
return (
|
||||
<div {...props} {...wrapper}>
|
||||
<div {...page}>
|
||||
<div key="title" {...titleWrapper}>
|
||||
{titleWrapper.children.map(getChildrenToRender)}
|
||||
</div>
|
||||
<OverPack {...dataSource.OverPack}>
|
||||
<QueueAnim
|
||||
type="bottom"
|
||||
leaveReverse
|
||||
ease={['easeOutQuad', 'easeInOutQuad']}
|
||||
key="content"
|
||||
>
|
||||
{childrenToRender}
|
||||
</QueueAnim>
|
||||
</OverPack>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Pricing2;
|
||||
1070
client/src/landing/data.source.js
Normal file
4
client/src/landing/documentation.md
Normal file
@@ -0,0 +1,4 @@
|
||||
# 如何使用:
|
||||
|
||||
- umi 里如何使用[请查看](https://landing.ant.design/docs/use/umi)。
|
||||
- 其它脚手架使用[请查看](https://landing.ant.design/docs/use/getting-started)。
|
||||
150
client/src/landing/index.jsx
Normal file
@@ -0,0 +1,150 @@
|
||||
/* eslint no-undef: 0 */
|
||||
/* eslint arrow-parens: 0 */
|
||||
import { enquireScreen } from "enquire-js";
|
||||
import React from "react";
|
||||
import Banner0 from "./Banner0";
|
||||
// import Content4 from "./Content4";
|
||||
import Content0 from "./Content0";
|
||||
import Content1 from "./Content1";
|
||||
import {
|
||||
Banner00DataSource,
|
||||
// Content40DataSource,
|
||||
Content00DataSource,
|
||||
Content10DataSource,
|
||||
// Pricing11DataSource,
|
||||
// Content30DataSource,
|
||||
// Content120DataSource,
|
||||
Footer10DataSource,
|
||||
Nav00DataSource,
|
||||
Pricing20DataSource,
|
||||
} from "./data.source";
|
||||
// import Pricing1 from "./Pricing1";
|
||||
// import Content3 from "./Content3";
|
||||
// import Content12 from "./Content12";
|
||||
import Footer1 from "./Footer1";
|
||||
import "./less/antMotionStyle.less";
|
||||
import Nav0 from "./Nav0";
|
||||
import Pricing2 from "./Pricing2";
|
||||
|
||||
let isMobile;
|
||||
enquireScreen((b) => {
|
||||
isMobile = b;
|
||||
});
|
||||
|
||||
const { location = {} } = typeof window !== "undefined" ? window : {};
|
||||
|
||||
export default class Home extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
isMobile,
|
||||
show: !location.port, // 如果不是 dva 2.0 请删除
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
// 适配手机屏幕;
|
||||
enquireScreen((b) => {
|
||||
this.setState({ isMobile: !!b });
|
||||
});
|
||||
// dva 2.0 样式在组件渲染之后动态加载,导致滚动组件不生效;线上不影响;
|
||||
/* 如果不是 dva 2.0 请删除 start */
|
||||
if (location.port) {
|
||||
// 样式 build 时间在 200-300ms 之间;
|
||||
setTimeout(() => {
|
||||
this.setState({
|
||||
show: true,
|
||||
});
|
||||
}, 500);
|
||||
}
|
||||
/* 如果不是 dva 2.0 请删除 end */
|
||||
console.log("Setting $crisp segments", ["lead"]);
|
||||
window.$crisp.push(["set", "session:segments", [["lead"]]]);
|
||||
window.$crisp.push([
|
||||
"set",
|
||||
"session:event",
|
||||
[[["landing-page", {}, "green"]]],
|
||||
]);
|
||||
}
|
||||
|
||||
render() {
|
||||
const children = [
|
||||
<Nav0
|
||||
id="Nav0_0"
|
||||
key="Nav0_0"
|
||||
dataSource={Nav00DataSource}
|
||||
isMobile={this.state.isMobile}
|
||||
/>,
|
||||
<Banner0
|
||||
id="Banner0_0"
|
||||
key="Banner0_0"
|
||||
dataSource={Banner00DataSource}
|
||||
isMobile={this.state.isMobile}
|
||||
/>,
|
||||
...(process.env.NODE_ENV !== "production"
|
||||
? [
|
||||
// <Content4
|
||||
// id="Content4_0"
|
||||
// key="Content4_0"
|
||||
// dataSource={Content40DataSource}
|
||||
// isMobile={this.state.isMobile}
|
||||
// />,
|
||||
<Content1
|
||||
id="Content1_0"
|
||||
key="Content1_0"
|
||||
dataSource={Content10DataSource}
|
||||
isMobile={this.state.isMobile}
|
||||
/>,
|
||||
<Content0
|
||||
id="Content0_0"
|
||||
key="Content0_0"
|
||||
dataSource={Content00DataSource}
|
||||
isMobile={this.state.isMobile}
|
||||
/>,
|
||||
<Pricing2
|
||||
id="Pricing2_0"
|
||||
key="Pricing2_0"
|
||||
dataSource={Pricing20DataSource}
|
||||
isMobile={this.state.isMobile}
|
||||
/>,
|
||||
// <Pricing1
|
||||
// id="Pricing1_1"
|
||||
// key="Pricing1_1"
|
||||
// dataSource={Pricing11DataSource}
|
||||
// isMobile={this.state.isMobile}
|
||||
// />,
|
||||
// <Content3
|
||||
// id="Content3_0"
|
||||
// key="Content3_0"
|
||||
// dataSource={Content30DataSource}
|
||||
// isMobile={this.state.isMobile}
|
||||
// />,
|
||||
// <Content12
|
||||
// id="Content12_0"
|
||||
// key="Content12_0"
|
||||
// dataSource={Content120DataSource}
|
||||
// isMobile={this.state.isMobile}
|
||||
// />,
|
||||
]
|
||||
: []),
|
||||
<Footer1
|
||||
id="Footer1_0"
|
||||
key="Footer1_0"
|
||||
dataSource={Footer10DataSource}
|
||||
isMobile={this.state.isMobile}
|
||||
/>,
|
||||
];
|
||||
return (
|
||||
<div
|
||||
className="templates-wrapper"
|
||||
ref={(d) => {
|
||||
this.dom = d;
|
||||
}}
|
||||
>
|
||||
{/* 如果不是 dva 2.0 替换成 {children} start */}
|
||||
{this.state.show && children}
|
||||
{/* 如果不是 dva 2.0 替换成 {children} end */}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
14
client/src/landing/less/antMotionStyle.less
Normal file
@@ -0,0 +1,14 @@
|
||||
@import './common.less';
|
||||
@import './custom.less';
|
||||
@import './content.less';
|
||||
@import './nav0.less';
|
||||
@import './banner0.less';
|
||||
@import './content4.less';
|
||||
@import './content0.less';
|
||||
@import './content1.less';
|
||||
@import './pricing2.less';
|
||||
@import './pricing1.less';
|
||||
@import './content3.less';
|
||||
@import './content12.less';
|
||||
@import './footer1.less';
|
||||
@import './edit.less';
|
||||
84
client/src/landing/less/banner0.less
Normal file
@@ -0,0 +1,84 @@
|
||||
@banner0: banner0;
|
||||
.@{banner0} {
|
||||
// 如果在第一屏且导航位置为 relative, 一屏为 height: calc(~"100vh - 64px");
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
border-color: #666;
|
||||
background-image: url("../../assets/banner1.jpeg");
|
||||
background-size: cover;
|
||||
background-attachment: fixed;
|
||||
background-position: center;
|
||||
& &-text-wrapper {
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
top: 20%;
|
||||
margin: auto;
|
||||
left: 0;
|
||||
right: 0;
|
||||
font-size: 14px;
|
||||
color: @template-text-color-light;
|
||||
width: 550px;
|
||||
> .queue-anim-leaving {
|
||||
position: relative !important;
|
||||
}
|
||||
}
|
||||
& &-title {
|
||||
width: 350px;
|
||||
//left: 30px;
|
||||
min-height: 60px;
|
||||
margin: auto;
|
||||
display: inline-block;
|
||||
font-size: 40px;
|
||||
position: relative;
|
||||
}
|
||||
& &-content {
|
||||
margin-bottom: 20px;
|
||||
word-wrap: break-word;
|
||||
min-height: 24px;
|
||||
}
|
||||
& &-button {
|
||||
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 {
|
||||
bottom: 20px;
|
||||
font-size: 24px;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
margin-left: -12px;
|
||||
color: @template-text-color-light;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
.@{banner0} {
|
||||
background-attachment: inherit;
|
||||
& &-text-wrapper {
|
||||
width: 90%;
|
||||
}
|
||||
& &-title {
|
||||
width: 90%;
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
42
client/src/landing/less/common.less
Normal file
@@ -0,0 +1,42 @@
|
||||
|
||||
// @import "~antd/lib/style/v2-compatible-reset.less";
|
||||
|
||||
body {
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
body,
|
||||
div,
|
||||
dl,
|
||||
dt,
|
||||
dd,
|
||||
ul,
|
||||
ol,
|
||||
li,
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* .content-wrapper > .tween-one-leaving,
|
||||
.queue-anim-leaving {
|
||||
// position: absolute !important;
|
||||
// width: 100%;
|
||||
} */
|
||||
|
||||
.video {
|
||||
max-width: 800px;
|
||||
}
|
||||
|
||||
#react-content {
|
||||
min-height: 100%;
|
||||
}
|
||||
.home-page-wrapper p {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
44
client/src/landing/less/content.less
Normal file
@@ -0,0 +1,44 @@
|
||||
@homepage: home-page;
|
||||
.@{homepage}-wrapper {
|
||||
width: 100%;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
.@{homepage} {
|
||||
height: 100%;
|
||||
max-width: 1200px;
|
||||
position: relative;
|
||||
margin: auto;
|
||||
will-change: transform;
|
||||
}
|
||||
.title-wrapper > h1, > h1 {
|
||||
font-size: 32px;
|
||||
color: @text-color;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
.title-wrapper {
|
||||
margin: 0 auto 64px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.@{homepage} {
|
||||
padding: 128px 24px;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
.@{homepage}-wrapper {
|
||||
.@{homepage} {
|
||||
padding: 56px 24px;
|
||||
>h1 {
|
||||
font-size: 24px;
|
||||
margin: 0 auto 32px;
|
||||
&.title-h1 {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
}
|
||||
>p {
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
55
client/src/landing/less/content0.less
Normal file
@@ -0,0 +1,55 @@
|
||||
@content0: content0;
|
||||
|
||||
.@{content0}-wrapper {
|
||||
min-height: 446px;
|
||||
overflow: hidden;
|
||||
|
||||
.@{content0} {
|
||||
height: 100%;
|
||||
padding: 64px 24px;
|
||||
|
||||
>.title-wrapper {
|
||||
margin: 0 auto 48px;
|
||||
}
|
||||
|
||||
&-block {
|
||||
padding: 0 4%;
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
min-height: 200px;
|
||||
margin-bottom: 24px;
|
||||
img {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&-wrapper {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
top: 25%;
|
||||
padding: 20px 0;
|
||||
}
|
||||
|
||||
&.queue-anim-leaving {
|
||||
position: relative !important;
|
||||
}
|
||||
|
||||
&-icon {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
&-title {
|
||||
line-height: 32px;
|
||||
margin: 10px auto;
|
||||
font-size: 24px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
.@{content0}-wrapper {
|
||||
min-height: 880px;
|
||||
}
|
||||
}
|
||||
76
client/src/landing/less/content1.less
Normal file
@@ -0,0 +1,76 @@
|
||||
@content1: content1;
|
||||
.@{content1}-wrapper {
|
||||
height: 360px;
|
||||
.@{content1} {
|
||||
height: 100%;
|
||||
padding: 0 24px;
|
||||
&-img {
|
||||
height: 100%;
|
||||
transform-origin: top;
|
||||
padding: 0 32px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
span {
|
||||
display: block;
|
||||
width: 250px;
|
||||
img {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
&-text {
|
||||
padding: 0 32px;
|
||||
height: 100%;
|
||||
.@{content1}-content,
|
||||
.@{content1}-title {
|
||||
position: relative !important;
|
||||
}
|
||||
.@{content1}-title {
|
||||
font-size: 32px;
|
||||
font-weight: normal;
|
||||
color: #404040;
|
||||
margin-top: 120px;
|
||||
}
|
||||
.content {
|
||||
margin-top: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
.@{content1}-wrapper {
|
||||
height: 600px;
|
||||
.@{content1} {
|
||||
&-img {
|
||||
height: 200px;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
margin-top: 64px;
|
||||
span {
|
||||
display: inline-block;
|
||||
width: 180px;
|
||||
height: 200px;
|
||||
line-height: 200px;
|
||||
margin: auto;
|
||||
}
|
||||
}
|
||||
&-text {
|
||||
height: auto;
|
||||
margin-bottom: 20px;
|
||||
text-align: center;
|
||||
padding: 0;
|
||||
.@{content1}-content,
|
||||
.@{content1}-title {
|
||||
width: 100%;
|
||||
top: auto;
|
||||
}
|
||||
.@{content1}-title {
|
||||
margin: 32px auto 16px;
|
||||
font-size: 24px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
52
client/src/landing/less/content12.less
Normal file
@@ -0,0 +1,52 @@
|
||||
@content12: content12;
|
||||
.@{content12}-wrapper {
|
||||
background-color: #fafafa;
|
||||
min-height: 470px;
|
||||
.@{content12} {
|
||||
padding: 64px 24px;
|
||||
>p {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
.img-wrapper {
|
||||
margin: 0 auto;
|
||||
left: 0;
|
||||
right: 0;
|
||||
.block {
|
||||
margin-bottom: 40px;
|
||||
.block-content {
|
||||
display: flex;
|
||||
border-radius: 4px;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
border: none;
|
||||
height: 64px;
|
||||
align-items: center;
|
||||
transition: box-shadow .3s @ease-out, transform .3s @ease-out;
|
||||
& > span {
|
||||
width: 100%;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
.@{content12}-wrapper {
|
||||
overflow: hidden;
|
||||
.@{content12} {
|
||||
ul {
|
||||
li {
|
||||
display: block;
|
||||
width: 100%;
|
||||
padding: 2%;
|
||||
span {
|
||||
height: 168px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
52
client/src/landing/less/content3.less
Normal file
@@ -0,0 +1,52 @@
|
||||
@content3: content3;
|
||||
.@{content3}-wrapper {
|
||||
min-height: 764px;
|
||||
.@{content3} {
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
& .title-content {
|
||||
text-align: center;
|
||||
}
|
||||
&-block-wrapper {
|
||||
position: relative;
|
||||
.@{content3}-block {
|
||||
display: inline-block;
|
||||
padding: 48px 24px;
|
||||
vertical-align: top;
|
||||
.@{content3}-icon {
|
||||
display: inline-block;
|
||||
width: 15%;
|
||||
vertical-align: top;
|
||||
}
|
||||
.@{content3}-text {
|
||||
width: 85%;
|
||||
display: inline-block;
|
||||
padding-left: 8%;
|
||||
}
|
||||
&.clear-both {
|
||||
clear: both;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
.@{content3}-wrapper {
|
||||
min-height: 1080px;
|
||||
.@{content3} {
|
||||
&-block-wrapper {
|
||||
margin: 20px auto;
|
||||
height: auto;
|
||||
.@{content3}-block {
|
||||
.@{content3}-title {
|
||||
font-size: 20px;
|
||||
}
|
||||
&.queue-anim-leaving {
|
||||
position: relative !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
37
client/src/landing/less/content4.less
Normal file
@@ -0,0 +1,37 @@
|
||||
@content4: content4;
|
||||
.@{content4}-wrapper {
|
||||
min-height: 720px;
|
||||
background: #fafafa;
|
||||
.@{content4} {
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
&-video {
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
max-width: 800px;
|
||||
margin: auto;
|
||||
background: #fff;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, .15);
|
||||
video {
|
||||
display: block;
|
||||
margin: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
.@{content4}-wrapper {
|
||||
min-height: 350px;
|
||||
.@{content4} {
|
||||
overflow: hidden;
|
||||
width: 90%;
|
||||
margin: auto;
|
||||
&-video {
|
||||
top: 15%;
|
||||
background: url("https://zos.alipayobjects.com/rmsportal/HZgzhugQZkqUwBVeNyfz.jpg") no-repeat center;
|
||||
background-size: cover;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
35
client/src/landing/less/custom.less
Normal file
@@ -0,0 +1,35 @@
|
||||
@import "~antd/lib/style/themes/default.less";
|
||||
|
||||
@line-color: #e9e9e9;
|
||||
|
||||
@shadow-color: rgba(0, 0, 0, 0.15);
|
||||
|
||||
@bottom-bar-bg-color: #262626;
|
||||
@bottom-bar-line-color: #000;
|
||||
|
||||
@template-bg-color: #001529;
|
||||
@template-bg-color-light: #ececec;
|
||||
@template-nav-bg-color: #001529;
|
||||
@template-text-color: #ccc;
|
||||
@template-text-title-color: #bcbcbc;
|
||||
@template-text-color-light: #fff;
|
||||
@template-footer-text-color: #999;
|
||||
|
||||
@animate-duration: .45s;
|
||||
|
||||
/* 详细页图片或框框的样式;
|
||||
*/
|
||||
.page-shadow() {
|
||||
box-shadow: 0 5px 8px @shadow-color;
|
||||
}
|
||||
|
||||
.page-pro() {
|
||||
border-radius: 6px;
|
||||
border: 1px solid @line-color;
|
||||
transform: translateY(0);
|
||||
transition: transform .3s @ease-out, box-shadow .3s @ease-out;
|
||||
&:hover {
|
||||
.page-shadow();
|
||||
transform: translateY(-5px);
|
||||
}
|
||||
}
|
||||
0
client/src/landing/less/edit.less
Normal file
98
client/src/landing/less/footer1.less
Normal file
@@ -0,0 +1,98 @@
|
||||
.footer1-wrapper {
|
||||
background: @template-bg-color;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
min-height: 360px;
|
||||
color: @template-footer-text-color;
|
||||
.footer1 {
|
||||
.home-page {
|
||||
padding: 64px 24px 80px;
|
||||
}
|
||||
}
|
||||
.block {
|
||||
padding: 0 32px;
|
||||
.logo {
|
||||
max-width: 180px;
|
||||
}
|
||||
.slogan {
|
||||
font-size: 12px;
|
||||
margin-top: -20px;
|
||||
}
|
||||
>h2 {
|
||||
margin-bottom: 24px;
|
||||
color: @template-text-color;
|
||||
}
|
||||
a {
|
||||
color: @template-footer-text-color;
|
||||
margin-bottom: 12px;
|
||||
float: left;
|
||||
clear: both;
|
||||
&:hover {
|
||||
color: @primary-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
.copyright-wrapper {
|
||||
width: 100%;
|
||||
border-top: 1px solid fade(@line-color, 10);
|
||||
.home-page {
|
||||
padding: 0 24px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.copyright {
|
||||
height: 80px;
|
||||
text-align: center;
|
||||
line-height: 80px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
.footer1 {
|
||||
min-height: 550px;
|
||||
&-wrapper {
|
||||
.footer1 {
|
||||
.home-page {
|
||||
padding: 64px 24px 32px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.logo {
|
||||
margin: 0 auto 24px;
|
||||
}
|
||||
.block {
|
||||
text-align: center;
|
||||
margin-bottom: 32px;
|
||||
padding: 0;
|
||||
}
|
||||
>ul {
|
||||
width: 90%;
|
||||
margin: 20px auto 0;
|
||||
padding: 10px 0;
|
||||
>li {
|
||||
width: 100%;
|
||||
h2 {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
li {
|
||||
display: inline-block;
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.copyright {
|
||||
&-wrapper {
|
||||
.home-page {
|
||||
padding: 0;
|
||||
.copyright {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
span {
|
||||
width: 90%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
187
client/src/landing/less/nav0.less
Normal file
@@ -0,0 +1,187 @@
|
||||
@header0: header0;
|
||||
|
||||
.@{header0} {
|
||||
background: @template-nav-bg-color;
|
||||
width: 100%;
|
||||
z-index: 1;
|
||||
box-shadow: 0 5px 8px fade(#000, 15);
|
||||
position: relative;
|
||||
top: 0;
|
||||
|
||||
.home-page {
|
||||
padding: 0 24px;
|
||||
}
|
||||
|
||||
&-logo {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
width: 150px;
|
||||
line-height: 64px;
|
||||
|
||||
& img {
|
||||
vertical-align: middle;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
& a {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
&-menu {
|
||||
float: right;
|
||||
|
||||
.ant-menu {
|
||||
line-height: 62px;
|
||||
height: 64px;
|
||||
|
||||
a {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-item {
|
||||
&-block {
|
||||
padding: 0 8px;
|
||||
|
||||
>* {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-item,
|
||||
&-item-child,
|
||||
&-menu {
|
||||
|
||||
.ant-menu-sub .ant-menu-item,
|
||||
.ant-menu-inline .ant-menu-item {
|
||||
height: auto;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.item {
|
||||
&-sub-item {
|
||||
display: block;
|
||||
padding: 8px 24px;
|
||||
}
|
||||
|
||||
&-image {
|
||||
float: left;
|
||||
margin-right: 16px;
|
||||
margin-top: 4px;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
&-title {
|
||||
font-size: 14px;
|
||||
color: #fff;
|
||||
margin-left: 46px;
|
||||
}
|
||||
|
||||
&-content {
|
||||
font-size: 12px;
|
||||
color: fade(#fff, 75);
|
||||
margin-left: 46px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
.@{header0} {
|
||||
&-logo {
|
||||
z-index: 101;
|
||||
}
|
||||
|
||||
&.home-page-wrapper .home-page {
|
||||
padding: 0 24px;
|
||||
}
|
||||
|
||||
&-menu {
|
||||
height: auto;
|
||||
float: inherit;
|
||||
position: relative;
|
||||
left: -24px;
|
||||
width: ~"calc(100% + 48px)";
|
||||
opacity: 0;
|
||||
transition: opacity .3s @ease-in-out;
|
||||
|
||||
& li {
|
||||
padding: 0 24px;
|
||||
|
||||
&.ant-menu-submenu {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
.item {
|
||||
&-sub-item {
|
||||
padding: 8px 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-mobile-menu {
|
||||
width: 16px;
|
||||
height: 14px;
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
top: 24px;
|
||||
right: 24px;
|
||||
z-index: 100;
|
||||
|
||||
em {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 2px;
|
||||
background: #fff;
|
||||
margin-top: 4px;
|
||||
transition: transform .3s @ease-in-out, opacity .3s @ease-in-out;
|
||||
}
|
||||
|
||||
:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.ant-menu {
|
||||
height: auto;
|
||||
overflow: hidden;
|
||||
|
||||
.ant-menu-item-selected {
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
|
||||
& .open {
|
||||
height: auto;
|
||||
|
||||
.@{header0}-mobile-menu {
|
||||
em {
|
||||
&:nth-child(1) {
|
||||
transform: translateY(6px) rotate(45deg);
|
||||
}
|
||||
|
||||
&:nth-child(2) {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
&:nth-child(3) {
|
||||
transform: translateY(-6px) rotate(-45deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
>.@{header0}-menu {
|
||||
opacity: 1;
|
||||
pointer-events: auto;
|
||||
}
|
||||
}
|
||||
&-item-block {
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
}
|
||||
}
|
||||
}
|
||||
85
client/src/landing/less/pricing1.less
Normal file
@@ -0,0 +1,85 @@
|
||||
@pricing1: pricing1;
|
||||
.@{pricing1}-wrapper {
|
||||
min-height: 760px;
|
||||
.@{pricing1} {
|
||||
>p {
|
||||
text-align: center;
|
||||
}
|
||||
&-content-wrapper {
|
||||
min-height: 400px;
|
||||
}
|
||||
&-block-box {
|
||||
width: 260px;
|
||||
border-radius: 4px;
|
||||
background: #eef0f3;
|
||||
text-align: center;
|
||||
color: #666;
|
||||
min-height: 400px;
|
||||
margin: auto;
|
||||
border: 1px solid transparent;
|
||||
.page-pro();
|
||||
&.active {
|
||||
border-color: @primary-color;
|
||||
background: #fff;
|
||||
.@{pricing1} {
|
||||
&-top-wrapper {
|
||||
background: @primary-color;
|
||||
}
|
||||
&-name,
|
||||
&-money,
|
||||
&-button {
|
||||
color: #fff;
|
||||
}
|
||||
&-button {
|
||||
background: @primary-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
&-block {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
&-top-wrapper {
|
||||
width: 100%;
|
||||
padding: 16px 24px;
|
||||
}
|
||||
&-name {
|
||||
font-size: 14px;
|
||||
}
|
||||
&-money {
|
||||
font-family: 'Helvetica Neue', sans-serif;
|
||||
font-size: 32px;
|
||||
color: #666;
|
||||
}
|
||||
&-content {
|
||||
font-size: 12px;
|
||||
line-height: 2;
|
||||
font-weight: 300;
|
||||
margin: 32px 24px 48px;
|
||||
}
|
||||
&-line {
|
||||
display: block;
|
||||
height: 1px;
|
||||
background: #d9d9d9;
|
||||
margin: 0 24px;
|
||||
}
|
||||
&-button-wrapper {
|
||||
margin: 18px 24px;
|
||||
}
|
||||
&-button {
|
||||
padding: 0 24px;
|
||||
}
|
||||
}
|
||||
&.home-page-wrapper {
|
||||
.@{pricing1}-title-wrapper {
|
||||
margin-bottom: 64px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
.@{pricing1}-wrapper {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
}
|
||||
59
client/src/landing/less/pricing2.less
Normal file
@@ -0,0 +1,59 @@
|
||||
@pricing2: pricing2;
|
||||
|
||||
.@{pricing2}-wrapper {
|
||||
min-height: 760px;
|
||||
|
||||
.@{pricing2} {
|
||||
>p {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
&-content-wrapper {
|
||||
min-height: 400px;
|
||||
}
|
||||
|
||||
&-table-name-block {
|
||||
text-align: center;
|
||||
color: #666;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&-table-name {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
&-table-money {
|
||||
font-size: 16px;
|
||||
margin: 8px 0 16px;
|
||||
}
|
||||
|
||||
&-table-content {
|
||||
text-align: center;
|
||||
color: #666;
|
||||
|
||||
&-name {
|
||||
color: #666;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.home-page-wrapper {
|
||||
.@{pricing2}-title-wrapper {
|
||||
margin-bottom: 64px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
.@{pricing2} {
|
||||
&-wrapper {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
&-table {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
}
|
||||
}
|
||||
18
client/src/landing/utils.js
Normal file
@@ -0,0 +1,18 @@
|
||||
|
||||
import React from 'react';
|
||||
import { Button } from 'antd';
|
||||
|
||||
export const isImg = /^http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w-./?%&=]*)?/;
|
||||
export const getChildrenToRender = (item, i) => {
|
||||
let tag = item.name.indexOf('title') === 0 ? 'h1' : 'div';
|
||||
tag = item.href ? 'a' : tag;
|
||||
let children = typeof item.children === 'string' && item.children.match(isImg)
|
||||
? React.createElement('img', { src: item.children, alt: 'img' })
|
||||
: item.children;
|
||||
if (item.name.indexOf('button') === 0 && typeof item.children === 'object') {
|
||||
children = React.createElement(Button, {
|
||||
...item.children
|
||||
});
|
||||
}
|
||||
return React.createElement(tag, { key: i.toString(), ...item }, children);
|
||||
};
|
||||
@@ -12,7 +12,6 @@ import AlertComponent from "../../components/alert/alert.component";
|
||||
import { QUERY_EXPORT_LOG_PAGINATED } from "../../graphql/accounting.queries";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
import { DateTimeFormatter } from "../../utils/DateFormatter";
|
||||
import { alphaSort } from "../../utils/sorters";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop,
|
||||
@@ -79,12 +78,10 @@ export function ExportLogsPageComponent({ bodyshop }) {
|
||||
title: t("jobs.fields.ro_number"),
|
||||
dataIndex: "ro_number",
|
||||
key: "ro_number",
|
||||
sorter: (a, b) => alphaSort(a.ro_number, b.ro_number),
|
||||
sortOrder: sortcolumn === "ro_number" && sortorder,
|
||||
|
||||
render: (text, record) =>
|
||||
record.job && (
|
||||
<Link to={"/manage/jobs/" + record.job && record.job.id}>
|
||||
<Link to={`/manage/jobs/${record.job.id}`}>
|
||||
{(record.job && record.job.ro_number) || t("general.labels.na")}
|
||||
</Link>
|
||||
),
|
||||
|
||||
@@ -15,6 +15,8 @@ import JobAdminOwnerReassociate from "../../components/jobs-admin-owner-reassoci
|
||||
import JobsAdminUnvoid from "../../components/jobs-admin-unvoid/jobs-admin-unvoid.component";
|
||||
import JobAdminVehicleReassociate from "../../components/jobs-admin-vehicle-reassociate/jobs-admin-vehicle-reassociate.component";
|
||||
import LoadingSpinner from "../../components/loading-spinner/loading-spinner.component";
|
||||
import JobsAdminStatus from "../../components/jobs-admin-change-status/jobs-admin-change.status.component";
|
||||
|
||||
import NotFound from "../../components/not-found/not-found.component";
|
||||
import RbacWrapper from "../../components/rbac-wrapper/rbac-wrapper.component";
|
||||
import { GET_JOB_BY_PK } from "../../graphql/jobs.queries";
|
||||
@@ -96,6 +98,7 @@ export function JobsCloseContainer({ setBreadcrumbs, setSelectedHeader }) {
|
||||
<JobsAdminDeleteIntake job={data ? data.jobs_by_pk : {}} />
|
||||
<JobsAdminMarkReexport job={data ? data.jobs_by_pk : {}} />
|
||||
<JobsAdminUnvoid job={data ? data.jobs_by_pk : {}} />
|
||||
<JobsAdminStatus job={data ? data.jobs_by_pk : {}} />
|
||||
</Space>
|
||||
</Card>
|
||||
</Col>
|
||||
|
||||
@@ -42,9 +42,26 @@ export function JobsCloseComponent({ job, bodyshop, jobRO }) {
|
||||
setLoading(true);
|
||||
const result = await client.mutate({
|
||||
mutation: generateJobLinesUpdatesForInvoicing(values.joblines),
|
||||
});
|
||||
if (result.errors) {
|
||||
return; // Abandon the rest of the close.
|
||||
}
|
||||
|
||||
const closeResult = await closeJob({
|
||||
variables: {
|
||||
jobId: job.id,
|
||||
job: {
|
||||
status: bodyshop.md_ro_statuses.default_invoiced || "",
|
||||
date_invoiced: new Date(),
|
||||
actual_in: values.actual_in,
|
||||
actual_completion: values.actual_completion,
|
||||
actual_delivery: values.actual_delivery,
|
||||
},
|
||||
},
|
||||
refetchQueries: ["QUERY_JOB_CLOSE_DETAILS"],
|
||||
awaitRefetchQueries: true,
|
||||
});
|
||||
|
||||
if (!result.errors) {
|
||||
notification["success"]({ message: t("jobs.successes.save") });
|
||||
// form.resetFields();
|
||||
@@ -56,18 +73,6 @@ export function JobsCloseComponent({ job, bodyshop, jobRO }) {
|
||||
});
|
||||
return; // Abandon the rest of the close.
|
||||
}
|
||||
form.resetFields();
|
||||
form.resetFields();
|
||||
|
||||
const closeResult = await closeJob({
|
||||
variables: {
|
||||
jobId: job.id,
|
||||
job: {
|
||||
status: bodyshop.md_ro_statuses.default_invoiced || "",
|
||||
date_invoiced: new Date(),
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (!closeResult.errors) {
|
||||
setLoading(false);
|
||||
@@ -84,6 +89,8 @@ export function JobsCloseComponent({ job, bodyshop, jobRO }) {
|
||||
}),
|
||||
});
|
||||
}
|
||||
form.resetFields();
|
||||
form.resetFields();
|
||||
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
@@ -3,6 +3,7 @@ import { connect } from "react-redux";
|
||||
import { Redirect } from "react-router-dom";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { selectCurrentUser } from "../../redux/user/user.selectors";
|
||||
import LandingPageStatic from "../../landing/index";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
currentUser: selectCurrentUser,
|
||||
@@ -13,5 +14,6 @@ export default connect(mapStateToProps, null)(LandingPage);
|
||||
export function LandingPage({ currentUser }) {
|
||||
if (currentUser.authorized) return <Redirect to={"/manage"} />;
|
||||
|
||||
return <Redirect to={"/signin"} />;
|
||||
return <LandingPageStatic />;
|
||||
//return <Redirect to={"/signin"} />;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@ import FcmNotification from "../../components/fcm-notification/fcm-notification.
|
||||
//import FooterComponent from "../../components/footer/footer.component";
|
||||
//Component Imports
|
||||
import HeaderContainer from "../../components/header/header.container";
|
||||
import JiraSupportComponent from "../../components/jira-support-widget/jira-support-widget.component";
|
||||
import LoadingSpinner from "../../components/loading-spinner/loading-spinner.component";
|
||||
import PartnerPingComponent from "../../components/partner-ping/partner-ping.component";
|
||||
import PrintCenterModalContainer from "../../components/print-center-modal/print-center-modal.container";
|
||||
@@ -408,10 +407,9 @@ export function Manage({ match, conflict, bodyshop }) {
|
||||
</div>
|
||||
<div id="noticeable-widget" style={{ marginLeft: "1rem" }} />
|
||||
</div>
|
||||
<Link to="/about" target="_blank" style={{ color: "#ccc" }}>
|
||||
<Link to="/disclaimer" target="_blank" style={{ color: "#ccc" }}>
|
||||
Disclaimer & Notices
|
||||
</Link>
|
||||
<JiraSupportComponent />
|
||||
</div>
|
||||
</Footer>
|
||||
</Content>
|
||||
|
||||
@@ -7,6 +7,7 @@ import LoadingSpinner from "../../components/loading-spinner/loading-spinner.com
|
||||
import { QUERY_BODYSHOP } from "../../graphql/bodyshop.queries";
|
||||
import { setBodyshop } from "../../redux/user/user.actions";
|
||||
import ManagePage from "./manage.page.component";
|
||||
import "../../utils/RegisterSw";
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
setBodyshop: (bs) => dispatch(setBodyshop(bs)),
|
||||
|
||||
@@ -9,6 +9,7 @@ import LoadingSpinner from "../../components/loading-spinner/loading-spinner.com
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import "../../utils/RegisterSw";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop,
|
||||
|
||||
@@ -17,7 +17,7 @@ export function* onCalculateScheduleLoad() {
|
||||
}
|
||||
export function* calculateScheduleLoad({ payload: end }) {
|
||||
//REMINDER: Moment.js is not immutable. Today WILL change when adjusted.
|
||||
const today = moment(new Date()).startOf("day");
|
||||
const today = moment().startOf("day");
|
||||
const state = yield select();
|
||||
const buckets = state.user.bodyshop.ssbuckets;
|
||||
|
||||
@@ -42,6 +42,7 @@ export function* calculateScheduleLoad({ payload: end }) {
|
||||
});
|
||||
|
||||
prodJobs.forEach((item) => {
|
||||
//Add all of the jobs currently in production to the buckets so that we have a starting point.
|
||||
const bucketId = CheckJobBucket(buckets, item);
|
||||
if (bucketId) {
|
||||
load.productionTotal[bucketId].count =
|
||||
|
||||
@@ -166,11 +166,14 @@ export function* signInSuccessSaga({ payload }) {
|
||||
LogRocket.identify(payload.email);
|
||||
try {
|
||||
// window.$crisp.push(["set", "user:email", [payload.email]]);
|
||||
console.log("$crisp set nickname", [payload.displayName || payload.email]);
|
||||
window.$crisp.push([
|
||||
"set",
|
||||
"user:nickname",
|
||||
[payload.displayName || payload.email],
|
||||
]);
|
||||
console.log("Setting $crisp segments", ["user"]);
|
||||
window.$crisp.push(["set", "session:segments", [["user"]]]);
|
||||
} catch (error) {
|
||||
console.log("Error updating Crisp settings.", error);
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
"cancel": "Cancel",
|
||||
"intake": "Intake",
|
||||
"new": "New Appointment",
|
||||
"preview": "Preview",
|
||||
"reschedule": "Reschedule",
|
||||
"sendreminder": "Send Reminder",
|
||||
"viewjob": "View Job"
|
||||
@@ -198,6 +199,7 @@
|
||||
"label": "Label"
|
||||
},
|
||||
"appt_length": "Default Appointment Length",
|
||||
"attach_pdf_to_email": "Attach PDF copy to sent emails?",
|
||||
"bill_federal_tax_rate": "Bills - Federal Tax Rate %",
|
||||
"bill_local_tax_rate": "Bill - Provincial/State Tax Rate %",
|
||||
"bill_state_tax_rate": "Bill - Provincial/State Tax Rate %",
|
||||
@@ -1033,6 +1035,8 @@
|
||||
"intake": "Intake",
|
||||
"manualnew": "Create New Job Manually",
|
||||
"mark": "Mark",
|
||||
"markpstexempt": "Mark Job PST Exempt",
|
||||
"markpstexemptconfirm": "Are you sure you want to do this? To undo this, you must manually update all PST rates.",
|
||||
"postbills": "Post Bills",
|
||||
"printCenter": "Print Center",
|
||||
"recalculate": "Recalculate",
|
||||
@@ -1422,6 +1426,56 @@
|
||||
"voided": "Job voided successfully."
|
||||
}
|
||||
},
|
||||
"landing": {
|
||||
"bigfeature": {
|
||||
"subtitle": "ImEX Online is built using world class technology by experts in the collision repair industry. This translates to software that is tailor made for the unique challenges faced by repair facilities with no compromises. ",
|
||||
"title": "Bringing the latest technology to the automotive repair industry. "
|
||||
},
|
||||
"footer": {
|
||||
"company": {
|
||||
"about": "About Us",
|
||||
"contact": "Contact",
|
||||
"disclaimers": "Disclaimers",
|
||||
"name": "Company",
|
||||
"privacypolicy": "Privacy Policy"
|
||||
},
|
||||
"io": {
|
||||
"help": "Help",
|
||||
"name": "ImEX Online",
|
||||
"status": "System Status"
|
||||
},
|
||||
"slogan": "A whole new kind of shop management system."
|
||||
},
|
||||
"hero": {
|
||||
"button": "Coming Soon",
|
||||
"title": "A whole new kind of shop management system."
|
||||
},
|
||||
"labels": {
|
||||
"features": "Features",
|
||||
"managemyshop": "Manage my Shop",
|
||||
"pricing": "Pricing"
|
||||
},
|
||||
"pricing": {
|
||||
"basic": {
|
||||
"name": "Basic",
|
||||
"sub": "Best suited for shops looking to increase their volume."
|
||||
},
|
||||
"essentials": {
|
||||
"name": "Essentials",
|
||||
"sub": "Best suited for small and low volume shops."
|
||||
},
|
||||
"pricingtitle": "Features",
|
||||
"pro": {
|
||||
"name": "Pro",
|
||||
"sub": "Empower your shop with the tools to operate at peak capacity."
|
||||
},
|
||||
"title": "Features",
|
||||
"unlimited": {
|
||||
"name": "Unlimited",
|
||||
"sub": "Everything you need and more for the high volume shop."
|
||||
}
|
||||
}
|
||||
},
|
||||
"menus": {
|
||||
"currentuser": {
|
||||
"languageselector": "Language",
|
||||
@@ -1779,6 +1833,8 @@
|
||||
"invoice_total_payable": "Invoice (Total Payable)",
|
||||
"job_costing_ro": "Job Costing",
|
||||
"job_notes": "Job Notes",
|
||||
"key_tag": "Key Tag",
|
||||
"paint_grid": "Paint Grid",
|
||||
"parts_label_single": "Parts Label - Single",
|
||||
"parts_list": "Parts List",
|
||||
"parts_order": "Parts Order Confirmation",
|
||||
@@ -1793,6 +1849,7 @@
|
||||
"qc_sheet": "Quality Control Sheet",
|
||||
"ro_totals": "RO Totals",
|
||||
"ro_with_description": "RO Summary with Descriptions",
|
||||
"stolen_recovery_checklist": "Stolen Recovery Checklist",
|
||||
"supplement_request": "Supplement Request",
|
||||
"thank_you_ro": "Thank You Letter",
|
||||
"thirdpartypayer": "Third Party Payer",
|
||||
@@ -1909,6 +1966,7 @@
|
||||
"export_payables": "Export Log - Payables",
|
||||
"export_payments": "Export Log - Payments",
|
||||
"export_receivables": "Export Log - Receivables",
|
||||
"gsr_by_csr": "Gross Sales by CSR",
|
||||
"gsr_by_delivery_date": "Gross Sales by Delivery Date",
|
||||
"gsr_by_estimator": "Gross Sales by Estimator",
|
||||
"gsr_by_exported_date": "Gross Sales by Export Date",
|
||||
@@ -1930,6 +1988,7 @@
|
||||
"job_costing_ro_estimator": "Job Costing by Estimator",
|
||||
"job_costing_ro_ins_co": "Job Costing by RO Source",
|
||||
"open_orders": "Open Orders by Date",
|
||||
"open_orders_csr": "Open Orders by CSR",
|
||||
"open_orders_estimator": "Open Orders by Estimator",
|
||||
"open_orders_ins_co": "Open Orders by Insurance Company",
|
||||
"parts_backorder": "Backordered Parts",
|
||||
@@ -2231,7 +2290,7 @@
|
||||
"city": "City",
|
||||
"cost_center": "Cost Center",
|
||||
"country": "Country",
|
||||
"discount": "Discount %",
|
||||
"discount": "Discount % (as decimal)",
|
||||
"display_name": "Display Name",
|
||||
"due_date": "Payment Due Date",
|
||||
"email": "Contact Email",
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
"cancel": "Cancelar",
|
||||
"intake": "Consumo",
|
||||
"new": "Nueva cita",
|
||||
"preview": "",
|
||||
"reschedule": "Reprogramar",
|
||||
"sendreminder": "",
|
||||
"viewjob": "Ver trabajo"
|
||||
@@ -198,6 +199,7 @@
|
||||
"label": ""
|
||||
},
|
||||
"appt_length": "",
|
||||
"attach_pdf_to_email": "",
|
||||
"bill_federal_tax_rate": "",
|
||||
"bill_local_tax_rate": "",
|
||||
"bill_state_tax_rate": "",
|
||||
@@ -1033,6 +1035,8 @@
|
||||
"intake": "",
|
||||
"manualnew": "",
|
||||
"mark": "",
|
||||
"markpstexempt": "",
|
||||
"markpstexemptconfirm": "",
|
||||
"postbills": "Contabilizar facturas",
|
||||
"printCenter": "Centro de impresión",
|
||||
"recalculate": "",
|
||||
@@ -1422,6 +1426,56 @@
|
||||
"voided": ""
|
||||
}
|
||||
},
|
||||
"landing": {
|
||||
"bigfeature": {
|
||||
"subtitle": "",
|
||||
"title": ""
|
||||
},
|
||||
"footer": {
|
||||
"company": {
|
||||
"about": "",
|
||||
"contact": "",
|
||||
"disclaimers": "",
|
||||
"name": "",
|
||||
"privacypolicy": ""
|
||||
},
|
||||
"io": {
|
||||
"help": "",
|
||||
"name": "",
|
||||
"status": ""
|
||||
},
|
||||
"slogan": ""
|
||||
},
|
||||
"hero": {
|
||||
"button": "",
|
||||
"title": ""
|
||||
},
|
||||
"labels": {
|
||||
"features": "",
|
||||
"managemyshop": "",
|
||||
"pricing": ""
|
||||
},
|
||||
"pricing": {
|
||||
"basic": {
|
||||
"name": "",
|
||||
"sub": ""
|
||||
},
|
||||
"essentials": {
|
||||
"name": "",
|
||||
"sub": ""
|
||||
},
|
||||
"pricingtitle": "",
|
||||
"pro": {
|
||||
"name": "",
|
||||
"sub": ""
|
||||
},
|
||||
"title": "",
|
||||
"unlimited": {
|
||||
"name": "",
|
||||
"sub": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
"menus": {
|
||||
"currentuser": {
|
||||
"languageselector": "idioma",
|
||||
@@ -1779,6 +1833,8 @@
|
||||
"invoice_total_payable": "",
|
||||
"job_costing_ro": "",
|
||||
"job_notes": "",
|
||||
"key_tag": "",
|
||||
"paint_grid": "",
|
||||
"parts_label_single": "",
|
||||
"parts_list": "",
|
||||
"parts_order": "",
|
||||
@@ -1793,6 +1849,7 @@
|
||||
"qc_sheet": "",
|
||||
"ro_totals": "",
|
||||
"ro_with_description": "",
|
||||
"stolen_recovery_checklist": "",
|
||||
"supplement_request": "",
|
||||
"thank_you_ro": "",
|
||||
"thirdpartypayer": "",
|
||||
@@ -1909,6 +1966,7 @@
|
||||
"export_payables": "",
|
||||
"export_payments": "",
|
||||
"export_receivables": "",
|
||||
"gsr_by_csr": "",
|
||||
"gsr_by_delivery_date": "",
|
||||
"gsr_by_estimator": "",
|
||||
"gsr_by_exported_date": "",
|
||||
@@ -1930,6 +1988,7 @@
|
||||
"job_costing_ro_estimator": "",
|
||||
"job_costing_ro_ins_co": "",
|
||||
"open_orders": "",
|
||||
"open_orders_csr": "",
|
||||
"open_orders_estimator": "",
|
||||
"open_orders_ins_co": "",
|
||||
"parts_backorder": "",
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
"cancel": "annuler",
|
||||
"intake": "Admission",
|
||||
"new": "Nouveau rendez-vous",
|
||||
"preview": "",
|
||||
"reschedule": "Replanifier",
|
||||
"sendreminder": "",
|
||||
"viewjob": "Voir le travail"
|
||||
@@ -198,6 +199,7 @@
|
||||
"label": ""
|
||||
},
|
||||
"appt_length": "",
|
||||
"attach_pdf_to_email": "",
|
||||
"bill_federal_tax_rate": "",
|
||||
"bill_local_tax_rate": "",
|
||||
"bill_state_tax_rate": "",
|
||||
@@ -1033,6 +1035,8 @@
|
||||
"intake": "",
|
||||
"manualnew": "",
|
||||
"mark": "",
|
||||
"markpstexempt": "",
|
||||
"markpstexemptconfirm": "",
|
||||
"postbills": "Poster des factures",
|
||||
"printCenter": "Centre d'impression",
|
||||
"recalculate": "",
|
||||
@@ -1422,6 +1426,56 @@
|
||||
"voided": ""
|
||||
}
|
||||
},
|
||||
"landing": {
|
||||
"bigfeature": {
|
||||
"subtitle": "",
|
||||
"title": ""
|
||||
},
|
||||
"footer": {
|
||||
"company": {
|
||||
"about": "",
|
||||
"contact": "",
|
||||
"disclaimers": "",
|
||||
"name": "",
|
||||
"privacypolicy": ""
|
||||
},
|
||||
"io": {
|
||||
"help": "",
|
||||
"name": "",
|
||||
"status": ""
|
||||
},
|
||||
"slogan": ""
|
||||
},
|
||||
"hero": {
|
||||
"button": "",
|
||||
"title": ""
|
||||
},
|
||||
"labels": {
|
||||
"features": "",
|
||||
"managemyshop": "",
|
||||
"pricing": ""
|
||||
},
|
||||
"pricing": {
|
||||
"basic": {
|
||||
"name": "",
|
||||
"sub": ""
|
||||
},
|
||||
"essentials": {
|
||||
"name": "",
|
||||
"sub": ""
|
||||
},
|
||||
"pricingtitle": "",
|
||||
"pro": {
|
||||
"name": "",
|
||||
"sub": ""
|
||||
},
|
||||
"title": "",
|
||||
"unlimited": {
|
||||
"name": "",
|
||||
"sub": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
"menus": {
|
||||
"currentuser": {
|
||||
"languageselector": "La langue",
|
||||
@@ -1779,6 +1833,8 @@
|
||||
"invoice_total_payable": "",
|
||||
"job_costing_ro": "",
|
||||
"job_notes": "",
|
||||
"key_tag": "",
|
||||
"paint_grid": "",
|
||||
"parts_label_single": "",
|
||||
"parts_list": "",
|
||||
"parts_order": "",
|
||||
@@ -1793,6 +1849,7 @@
|
||||
"qc_sheet": "",
|
||||
"ro_totals": "",
|
||||
"ro_with_description": "",
|
||||
"stolen_recovery_checklist": "",
|
||||
"supplement_request": "",
|
||||
"thank_you_ro": "",
|
||||
"thirdpartypayer": "",
|
||||
@@ -1909,6 +1966,7 @@
|
||||
"export_payables": "",
|
||||
"export_payments": "",
|
||||
"export_receivables": "",
|
||||
"gsr_by_csr": "",
|
||||
"gsr_by_delivery_date": "",
|
||||
"gsr_by_estimator": "",
|
||||
"gsr_by_exported_date": "",
|
||||
@@ -1930,6 +1988,7 @@
|
||||
"job_costing_ro_estimator": "",
|
||||
"job_costing_ro_ins_co": "",
|
||||
"open_orders": "",
|
||||
"open_orders_csr": "",
|
||||
"open_orders_estimator": "",
|
||||
"open_orders_ins_co": "",
|
||||
"parts_backorder": "",
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import i18n from "i18next";
|
||||
import { initReactI18next } from "react-i18next";
|
||||
import LanguageDetector from "i18next-browser-languagedetector";
|
||||
import { initReactI18next } from "react-i18next";
|
||||
import en_Translation from "./en_us/common.json";
|
||||
import fr_Translation from "./fr/common.json";
|
||||
import es_Translation from "./es/common.json";
|
||||
import fr_Translation from "./fr/common.json";
|
||||
|
||||
// the translations
|
||||
// (tip move them in a JSON file and import them)
|
||||
|
||||
46
client/src/utils/RegisterSw.js
Normal file
@@ -0,0 +1,46 @@
|
||||
import { AlertOutlined } from "@ant-design/icons";
|
||||
import { Button, notification, Space } from "antd";
|
||||
import i18n from "i18next";
|
||||
import React from "react";
|
||||
import * as serviceWorkerRegistration from "../serviceWorkerRegistration";
|
||||
|
||||
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 });
|
||||
@@ -8,6 +8,7 @@ import { setEmailOptions } from "../redux/email/email.actions";
|
||||
import { store } from "../redux/store";
|
||||
import client from "../utils/GraphQLClient";
|
||||
import { TemplateList } from "./TemplateConstants";
|
||||
import _ from "lodash";
|
||||
const server = process.env.REACT_APP_REPORTS_SERVER_URL;
|
||||
jsreport.serverUrl = server;
|
||||
|
||||
@@ -39,8 +40,10 @@ export default async function RenderTemplate(
|
||||
offset: moment().utcOffset(),
|
||||
},
|
||||
};
|
||||
|
||||
try {
|
||||
const render = await jsreport.renderAsync(reportRequest);
|
||||
|
||||
if (!renderAsHtml) {
|
||||
render.download(
|
||||
(Templates[templateObject.name] &&
|
||||
@@ -48,8 +51,21 @@ export default async function RenderTemplate(
|
||||
""
|
||||
);
|
||||
} else {
|
||||
let pdf;
|
||||
if (bodyshop.attach_pdf_to_email) {
|
||||
const pdfRequest = _.cloneDeep(reportRequest);
|
||||
pdfRequest.template.recipe = "chrome-pdf";
|
||||
const pdfRender = await jsreport.renderAsync(pdfRequest);
|
||||
pdf = pdfRender.toDataURI();
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
resolve(render.toString());
|
||||
resolve({
|
||||
pdf,
|
||||
filename:
|
||||
Templates[templateObject.name] &&
|
||||
Templates[templateObject.name].title,
|
||||
html: render.toString(),
|
||||
});
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
@@ -69,6 +69,14 @@ export const TemplateList = (type, context) => {
|
||||
disabled: false,
|
||||
group: "pre",
|
||||
},
|
||||
stolen_recovery_checklist: {
|
||||
title: i18n.t("printcenter.jobs.stolen_recovery_checklist"),
|
||||
description: "All Jobs Notes",
|
||||
subject: i18n.t("printcenter.jobs.stolen_recovery_checklist"),
|
||||
key: "stolen_recovery_checklist",
|
||||
disabled: false,
|
||||
group: "pre",
|
||||
},
|
||||
vehicle_check_in: {
|
||||
title: i18n.t("printcenter.jobs.vehicle_check_in"),
|
||||
description: "All Jobs Notes",
|
||||
@@ -150,6 +158,22 @@ export const TemplateList = (type, context) => {
|
||||
disabled: false,
|
||||
group: "ro",
|
||||
},
|
||||
key_tag: {
|
||||
title: i18n.t("printcenter.jobs.key_tag"),
|
||||
description: "All Jobs Notes",
|
||||
subject: i18n.t("printcenter.jobs.key_tag"),
|
||||
key: "key_tag",
|
||||
disabled: false,
|
||||
group: "ro",
|
||||
},
|
||||
paint_grid: {
|
||||
title: i18n.t("printcenter.jobs.paint_grid"),
|
||||
description: "All Jobs Notes",
|
||||
subject: i18n.t("printcenter.jobs.paint_grid"),
|
||||
key: "paint_grid",
|
||||
disabled: false,
|
||||
group: "ro",
|
||||
},
|
||||
worksheet_by_line_number: {
|
||||
title: i18n.t("printcenter.jobs.worksheet_by_line_number"),
|
||||
description: "All Jobs Notes",
|
||||
@@ -840,6 +864,18 @@ export const TemplateList = (type, context) => {
|
||||
field: i18n.t("jobs.fields.date_open"),
|
||||
},
|
||||
},
|
||||
gsr_by_csr: {
|
||||
title: i18n.t("reportcenter.templates.gsr_by_csr"),
|
||||
description: "",
|
||||
subject: i18n.t("reportcenter.templates.gsr_by_csr"),
|
||||
key: "gsr_by_csr",
|
||||
//idtype: "vendor",
|
||||
disabled: false,
|
||||
rangeFilter: {
|
||||
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||
field: i18n.t("jobs.fields.date_invoiced"),
|
||||
},
|
||||
},
|
||||
gsr_by_make: {
|
||||
title: i18n.t("reportcenter.templates.gsr_by_make"),
|
||||
description: "",
|
||||
@@ -949,6 +985,18 @@ export const TemplateList = (type, context) => {
|
||||
field: i18n.t("jobs.fields.date_open"),
|
||||
},
|
||||
},
|
||||
open_orders_csr: {
|
||||
title: i18n.t("reportcenter.templates.open_orders_csr"),
|
||||
description: "",
|
||||
subject: i18n.t("reportcenter.templates.open_orders_csr"),
|
||||
key: "open_orders_csr",
|
||||
//idtype: "vendor",
|
||||
disabled: false,
|
||||
rangeFilter: {
|
||||
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||
field: i18n.t("jobs.fields.date_open"),
|
||||
},
|
||||
},
|
||||
open_orders_estimator: {
|
||||
title: i18n.t("reportcenter.templates.open_orders_estimator"),
|
||||
description: "",
|
||||
|
||||
@@ -3472,7 +3472,7 @@ babel-preset-react-app@^10.0.0:
|
||||
babel-plugin-macros "2.8.0"
|
||||
babel-plugin-transform-react-remove-prop-types "0.4.24"
|
||||
|
||||
babel-runtime@^6.26.0:
|
||||
babel-runtime@6.x, babel-runtime@^6.26.0:
|
||||
version "6.26.0"
|
||||
resolved "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz"
|
||||
integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4=
|
||||
@@ -4892,6 +4892,13 @@ deep-diff@^0.3.5:
|
||||
resolved "https://registry.npmjs.org/deep-diff/-/deep-diff-0.3.8.tgz"
|
||||
integrity sha1-wB3mPvsO7JeYgB1Ax+Da4ltYLIQ=
|
||||
|
||||
deep-eql@~3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df"
|
||||
integrity sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==
|
||||
dependencies:
|
||||
type-detect "^4.0.0"
|
||||
|
||||
deep-equal@^1.0.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz"
|
||||
@@ -5313,6 +5320,18 @@ enhanced-resolve@^4.3.0:
|
||||
memory-fs "^0.5.0"
|
||||
tapable "^1.0.0"
|
||||
|
||||
enquire-js@^0.2.1:
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/enquire-js/-/enquire-js-0.2.1.tgz#f2478cf5808d42f54e8231f20fa133493e7f0fcb"
|
||||
integrity sha512-4vbcWD0ncK6VQ5M5giOImQb2hFPrKDZH5U+uRX9S6e9vfC6Q5PX6A38PVS6RMnCdr/luDTtJjjLuJinH/+a+Lw==
|
||||
dependencies:
|
||||
enquire.js "^2.1.6"
|
||||
|
||||
enquire.js@^2.1.6:
|
||||
version "2.1.6"
|
||||
resolved "https://registry.yarnpkg.com/enquire.js/-/enquire.js-2.1.6.tgz#3e8780c9b8b835084c3f60e166dbc3c2a3c89814"
|
||||
integrity sha1-PoeAybi4NQhMP2DhZtvDwqPImBQ=
|
||||
|
||||
enquirer@^2.3.5:
|
||||
version "2.3.6"
|
||||
resolved "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz"
|
||||
@@ -10179,7 +10198,7 @@ prompts@2.4.0, prompts@^2.0.1:
|
||||
kleur "^3.0.3"
|
||||
sisteransi "^1.0.5"
|
||||
|
||||
prop-types@15.x, prop-types@^15.0.0, prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.2, prop-types@^15.7.2:
|
||||
prop-types@15.x, prop-types@^15.0.0, prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2:
|
||||
version "15.7.2"
|
||||
resolved "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz"
|
||||
integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
|
||||
@@ -10335,7 +10354,7 @@ raf-schd@^4.0.2:
|
||||
resolved "https://registry.npmjs.org/raf-schd/-/raf-schd-4.0.3.tgz"
|
||||
integrity sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==
|
||||
|
||||
raf@^3.4.0, raf@^3.4.1:
|
||||
raf@3.x, raf@^3.4.0, raf@^3.4.1, raf@~3.4.0:
|
||||
version "3.4.1"
|
||||
resolved "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz"
|
||||
integrity sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==
|
||||
@@ -10552,6 +10571,16 @@ rc-progress@~3.1.0:
|
||||
"@babel/runtime" "^7.10.1"
|
||||
classnames "^2.2.6"
|
||||
|
||||
rc-queue-anim@^1.8.5:
|
||||
version "1.8.5"
|
||||
resolved "https://registry.yarnpkg.com/rc-queue-anim/-/rc-queue-anim-1.8.5.tgz#01ef3872bdfa0b70bb915ef9a637fc404244a589"
|
||||
integrity sha512-vTbZXBu7L3NcXUPjkFN7R80BE+1VYL1QBI10EioYYqZMk6A0iVbjoVAgfoK/Z4gIIxp399gJ8LqbMnQA1AhcXA==
|
||||
dependencies:
|
||||
babel-runtime "6.x"
|
||||
prop-types "^15.6.0"
|
||||
rc-tween-one "^2.5.0"
|
||||
react-lifecycles-compat "^3.0.4"
|
||||
|
||||
rc-rate@~2.9.0:
|
||||
version "2.9.1"
|
||||
resolved "https://registry.npmjs.org/rc-rate/-/rc-rate-2.9.1.tgz"
|
||||
@@ -10571,6 +10600,18 @@ rc-resize-observer@^1.0.0:
|
||||
rc-util "^5.0.0"
|
||||
resize-observer-polyfill "^1.5.1"
|
||||
|
||||
rc-scroll-anim@^2.7.6:
|
||||
version "2.7.6"
|
||||
resolved "https://registry.yarnpkg.com/rc-scroll-anim/-/rc-scroll-anim-2.7.6.tgz#f7e6622f2930ca3e1e258f7275bc2e1c26ce791c"
|
||||
integrity sha512-VwXJYXjZy9TtH1wcQIG7/yjt/Ay3VEjQl/TITaWzK9O7ujjOXRVOYY/tqKshmBMgaJ2oGeFQNmCN8zTwXguq0g==
|
||||
dependencies:
|
||||
babel-runtime "6.x"
|
||||
prop-types "^15.6.0"
|
||||
raf "3.x"
|
||||
rc-tween-one "^2.4.0"
|
||||
react-lifecycles-compat "^3.0.4"
|
||||
tween-functions "1.x"
|
||||
|
||||
rc-select@^12.0.0, rc-select@~12.1.6:
|
||||
version "12.1.10"
|
||||
resolved "https://registry.npmjs.org/rc-select/-/rc-select-12.1.10.tgz"
|
||||
@@ -10687,6 +10728,30 @@ rc-trigger@^5.0.0, rc-trigger@^5.0.4, rc-trigger@^5.1.2, rc-trigger@^5.2.1:
|
||||
rc-motion "^2.0.0"
|
||||
rc-util "^5.5.0"
|
||||
|
||||
rc-tween-one@^1.2.5:
|
||||
version "1.8.1"
|
||||
resolved "https://registry.yarnpkg.com/rc-tween-one/-/rc-tween-one-1.8.1.tgz#5b3b464b9bf2c369efc16c816cccf57bc16ae253"
|
||||
integrity sha512-Avg8EXHdt6ABV9WnmTmh6zEaAzUvl4bFZKbP3y6BE8UGBGp1qUhlIgCB83gL+5eA0VECdM/b9PsEBRrcxzSpGw==
|
||||
dependencies:
|
||||
babel-runtime "6.x"
|
||||
deep-eql "~3.0.1"
|
||||
prop-types "^15.6.1"
|
||||
raf "~3.4.0"
|
||||
style-utils "~0.1.13"
|
||||
tween-functions "~1.2.0"
|
||||
|
||||
rc-tween-one@^2.4.0, rc-tween-one@^2.5.0:
|
||||
version "2.7.3"
|
||||
resolved "https://registry.yarnpkg.com/rc-tween-one/-/rc-tween-one-2.7.3.tgz#c9d3c44743e25c654d65c22ec3934afd79923fae"
|
||||
integrity sha512-n4OPRLO6VMZHj61unq5KKxHMMfBz52bxob94fN3U5M9GqFg3H+T3TXnpHPnAK+cq/xBGo70ik2vB4Fpjo/txcA==
|
||||
dependencies:
|
||||
babel-runtime "6.x"
|
||||
prop-types "^15.6.1"
|
||||
raf "~3.4.0"
|
||||
react-lifecycles-compat "^3.0.4"
|
||||
style-utils "~0.2.0"
|
||||
tween-functions "~1.2.0"
|
||||
|
||||
rc-upload@~4.3.0:
|
||||
version "4.3.1"
|
||||
resolved "https://registry.npmjs.org/rc-upload/-/rc-upload-4.3.1.tgz"
|
||||
@@ -11064,6 +11129,14 @@ react-smooth@^2.0.0:
|
||||
raf "^3.4.0"
|
||||
react-transition-group "2.9.0"
|
||||
|
||||
react-sublime-video@^0.2.5:
|
||||
version "0.2.5"
|
||||
resolved "https://registry.yarnpkg.com/react-sublime-video/-/react-sublime-video-0.2.5.tgz#c967b8e9a374b36d6a5d1b63b93fa6ec02e54842"
|
||||
integrity sha1-yWe46aN0s21qXRtjuT+m7ALlSEI=
|
||||
dependencies:
|
||||
prop-types "^15.5.10"
|
||||
rc-tween-one "^1.2.5"
|
||||
|
||||
react-transition-group@2, react-transition-group@2.9.0:
|
||||
version "2.9.0"
|
||||
resolved "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.9.0.tgz"
|
||||
@@ -12441,6 +12514,16 @@ style-loader@1.3.0:
|
||||
loader-utils "^2.0.0"
|
||||
schema-utils "^2.7.0"
|
||||
|
||||
style-utils@~0.1.13:
|
||||
version "0.1.24"
|
||||
resolved "https://registry.yarnpkg.com/style-utils/-/style-utils-0.1.24.tgz#fc0675d79a0b201bf86fc5d5a1dd202f838de544"
|
||||
integrity sha512-MVZSKubpU/vIfpmOsi8/0ckWxb0WmGBmyNoEDGWZM9cM8n8sCL6DJftl3lEf8Uy5zKQ9+O1XdJxscWTDosCQpQ==
|
||||
|
||||
style-utils@~0.2.0:
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/style-utils/-/style-utils-0.2.1.tgz#c78fe6696214f4ab12701959f09553e9d81dd45b"
|
||||
integrity sha512-eKRIfWnUSdBqe2ko+qisUwBSlfWpHru89geRqzmScpDhkPW1ksmE04d//nDcXeF+TVK5cnBG90mMmHgxyxXleQ==
|
||||
|
||||
styled-components@^5.3.0:
|
||||
version "5.3.0"
|
||||
resolved "https://registry.npmjs.org/styled-components/-/styled-components-5.3.0.tgz"
|
||||
@@ -12848,6 +12931,11 @@ tty-browserify@0.0.0:
|
||||
resolved "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz"
|
||||
integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=
|
||||
|
||||
tween-functions@1.x, tween-functions@~1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/tween-functions/-/tween-functions-1.2.0.tgz#1ae3a50e7c60bb3def774eac707acbca73bbc3ff"
|
||||
integrity sha1-GuOlDnxguz3vd06scHrLynO7w/8=
|
||||
|
||||
type-check@^0.4.0, type-check@~0.4.0:
|
||||
version "0.4.0"
|
||||
resolved "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz"
|
||||
@@ -12862,7 +12950,7 @@ type-check@~0.3.2:
|
||||
dependencies:
|
||||
prelude-ls "~1.1.2"
|
||||
|
||||
type-detect@4.0.8:
|
||||
type-detect@4.0.8, type-detect@^4.0.0:
|
||||
version "4.0.8"
|
||||
resolved "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz"
|
||||
integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
[]
|
||||
11
hasura/migrations/1625768789569_run_sql_migration/up.yaml
Normal file
@@ -0,0 +1,11 @@
|
||||
- args:
|
||||
cascade: false
|
||||
read_only: false
|
||||
sql: "CREATE OR REPLACE FUNCTION public.search_payments(search text)\n RETURNS
|
||||
SETOF payments\n LANGUAGE plpgsql\n STABLE\nAS $function$\n\nBEGIN\n if search
|
||||
= '' then\n return query select * from payments ;\n else \n return query
|
||||
SELECT\n p.*\nFROM\n payments p, jobs j\nWHERE\np.jobid = j.id AND\n(\nsearch
|
||||
<% p.paymentnum OR\nsearch <% j.ownr_fn OR\nsearch <% j.ownr_ln OR\nsearch <%
|
||||
j.ownr_co_nm OR\nsearch <% j.ro_number OR\n search <% (p.payer) OR\n search
|
||||
<% (p.transactionid) OR\n search <% (p.memo));\n end if;\n\n\tEND\n$function$;"
|
||||
type: run_sql
|
||||
@@ -0,0 +1,6 @@
|
||||
- args:
|
||||
cascade: false
|
||||
read_only: false
|
||||
sql: alter table "public"."vehicles" add constraint "vehicles_v_vin_shopid_key"
|
||||
unique ("v_vin", "shopid");
|
||||
type: run_sql
|
||||
@@ -0,0 +1,5 @@
|
||||
- args:
|
||||
cascade: false
|
||||
read_only: false
|
||||
sql: alter table "public"."vehicles" drop constraint "vehicles_v_vin_shopid_key";
|
||||
type: run_sql
|
||||
@@ -0,0 +1,5 @@
|
||||
- args:
|
||||
cascade: false
|
||||
read_only: false
|
||||
sql: ALTER TABLE "public"."bodyshops" DROP COLUMN "attach_pdf_to_email";
|
||||
type: run_sql
|
||||
@@ -0,0 +1,6 @@
|
||||
- args:
|
||||
cascade: false
|
||||
read_only: false
|
||||
sql: ALTER TABLE "public"."bodyshops" ADD COLUMN "attach_pdf_to_email" boolean
|
||||
NOT NULL DEFAULT False;
|
||||
type: run_sql
|
||||
@@ -0,0 +1,87 @@
|
||||
- args:
|
||||
role: user
|
||||
table:
|
||||
name: bodyshops
|
||||
schema: public
|
||||
type: drop_select_permission
|
||||
- args:
|
||||
permission:
|
||||
allow_aggregations: false
|
||||
columns:
|
||||
- accountingconfig
|
||||
- address1
|
||||
- address2
|
||||
- appt_alt_transport
|
||||
- appt_colors
|
||||
- appt_length
|
||||
- bill_tax_rates
|
||||
- cdk_dealerid
|
||||
- city
|
||||
- country
|
||||
- created_at
|
||||
- default_adjustment_rate
|
||||
- deliverchecklist
|
||||
- email
|
||||
- enforce_class
|
||||
- enforce_referral
|
||||
- features
|
||||
- federal_tax_id
|
||||
- id
|
||||
- imexshopid
|
||||
- inhousevendorid
|
||||
- insurance_vendor_id
|
||||
- intakechecklist
|
||||
- jc_hourly_rates
|
||||
- jobsizelimit
|
||||
- logo_img_path
|
||||
- md_categories
|
||||
- md_ccc_rates
|
||||
- md_classes
|
||||
- md_hour_split
|
||||
- md_ins_cos
|
||||
- md_jobline_presets
|
||||
- md_labor_rates
|
||||
- md_messaging_presets
|
||||
- md_notes_presets
|
||||
- md_order_statuses
|
||||
- md_parts_locations
|
||||
- md_payment_types
|
||||
- md_rbac
|
||||
- md_referral_sources
|
||||
- md_responsibility_centers
|
||||
- md_ro_statuses
|
||||
- messagingservicesid
|
||||
- phone
|
||||
- prodtargethrs
|
||||
- production_config
|
||||
- region_config
|
||||
- schedule_end_time
|
||||
- schedule_start_time
|
||||
- scoreboard_target
|
||||
- shopname
|
||||
- shoprates
|
||||
- speedprint
|
||||
- ssbuckets
|
||||
- state
|
||||
- state_tax_id
|
||||
- stripe_acct_id
|
||||
- sub_status
|
||||
- target_touchtime
|
||||
- template_header
|
||||
- textid
|
||||
- updated_at
|
||||
- use_fippa
|
||||
- website
|
||||
- workingdays
|
||||
- zip_post
|
||||
computed_fields: []
|
||||
filter:
|
||||
associations:
|
||||
user:
|
||||
authid:
|
||||
_eq: X-Hasura-User-Id
|
||||
role: user
|
||||
table:
|
||||
name: bodyshops
|
||||
schema: public
|
||||
type: create_select_permission
|
||||
@@ -0,0 +1,88 @@
|
||||
- args:
|
||||
role: user
|
||||
table:
|
||||
name: bodyshops
|
||||
schema: public
|
||||
type: drop_select_permission
|
||||
- args:
|
||||
permission:
|
||||
allow_aggregations: false
|
||||
columns:
|
||||
- accountingconfig
|
||||
- address1
|
||||
- address2
|
||||
- appt_alt_transport
|
||||
- appt_colors
|
||||
- appt_length
|
||||
- attach_pdf_to_email
|
||||
- bill_tax_rates
|
||||
- cdk_dealerid
|
||||
- city
|
||||
- country
|
||||
- created_at
|
||||
- default_adjustment_rate
|
||||
- deliverchecklist
|
||||
- email
|
||||
- enforce_class
|
||||
- enforce_referral
|
||||
- features
|
||||
- federal_tax_id
|
||||
- id
|
||||
- imexshopid
|
||||
- inhousevendorid
|
||||
- insurance_vendor_id
|
||||
- intakechecklist
|
||||
- jc_hourly_rates
|
||||
- jobsizelimit
|
||||
- logo_img_path
|
||||
- md_categories
|
||||
- md_ccc_rates
|
||||
- md_classes
|
||||
- md_hour_split
|
||||
- md_ins_cos
|
||||
- md_jobline_presets
|
||||
- md_labor_rates
|
||||
- md_messaging_presets
|
||||
- md_notes_presets
|
||||
- md_order_statuses
|
||||
- md_parts_locations
|
||||
- md_payment_types
|
||||
- md_rbac
|
||||
- md_referral_sources
|
||||
- md_responsibility_centers
|
||||
- md_ro_statuses
|
||||
- messagingservicesid
|
||||
- phone
|
||||
- prodtargethrs
|
||||
- production_config
|
||||
- region_config
|
||||
- schedule_end_time
|
||||
- schedule_start_time
|
||||
- scoreboard_target
|
||||
- shopname
|
||||
- shoprates
|
||||
- speedprint
|
||||
- ssbuckets
|
||||
- state
|
||||
- state_tax_id
|
||||
- stripe_acct_id
|
||||
- sub_status
|
||||
- target_touchtime
|
||||
- template_header
|
||||
- textid
|
||||
- updated_at
|
||||
- use_fippa
|
||||
- website
|
||||
- workingdays
|
||||
- zip_post
|
||||
computed_fields: []
|
||||
filter:
|
||||
associations:
|
||||
user:
|
||||
authid:
|
||||
_eq: X-Hasura-User-Id
|
||||
role: user
|
||||
table:
|
||||
name: bodyshops
|
||||
schema: public
|
||||
type: create_select_permission
|
||||
@@ -0,0 +1,79 @@
|
||||
- args:
|
||||
role: user
|
||||
table:
|
||||
name: bodyshops
|
||||
schema: public
|
||||
type: drop_update_permission
|
||||
- args:
|
||||
permission:
|
||||
columns:
|
||||
- accountingconfig
|
||||
- address1
|
||||
- address2
|
||||
- appt_alt_transport
|
||||
- appt_colors
|
||||
- appt_length
|
||||
- bill_tax_rates
|
||||
- city
|
||||
- country
|
||||
- created_at
|
||||
- default_adjustment_rate
|
||||
- deliverchecklist
|
||||
- email
|
||||
- enforce_class
|
||||
- enforce_referral
|
||||
- federal_tax_id
|
||||
- id
|
||||
- inhousevendorid
|
||||
- insurance_vendor_id
|
||||
- intakechecklist
|
||||
- jc_hourly_rates
|
||||
- logo_img_path
|
||||
- md_categories
|
||||
- md_ccc_rates
|
||||
- md_classes
|
||||
- md_hour_split
|
||||
- md_ins_cos
|
||||
- md_jobline_presets
|
||||
- md_labor_rates
|
||||
- md_messaging_presets
|
||||
- md_notes_presets
|
||||
- md_order_statuses
|
||||
- md_parts_locations
|
||||
- md_payment_types
|
||||
- md_rbac
|
||||
- md_referral_sources
|
||||
- md_responsibility_centers
|
||||
- md_ro_statuses
|
||||
- phone
|
||||
- prodtargethrs
|
||||
- production_config
|
||||
- schedule_end_time
|
||||
- schedule_start_time
|
||||
- scoreboard_target
|
||||
- shopname
|
||||
- shoprates
|
||||
- speedprint
|
||||
- ssbuckets
|
||||
- state
|
||||
- state_tax_id
|
||||
- target_touchtime
|
||||
- updated_at
|
||||
- use_fippa
|
||||
- website
|
||||
- workingdays
|
||||
- zip_post
|
||||
filter:
|
||||
associations:
|
||||
_and:
|
||||
- user:
|
||||
authid:
|
||||
_eq: X-Hasura-User-Id
|
||||
- active:
|
||||
_eq: true
|
||||
set: {}
|
||||
role: user
|
||||
table:
|
||||
name: bodyshops
|
||||
schema: public
|
||||
type: create_update_permission
|
||||