Compare commits
427 Commits
master-bet
...
feature/IO
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a87473c392 | ||
|
|
989f020e30 | ||
|
|
42cf072f6b | ||
|
|
58b11fde76 | ||
|
|
32bba8060a | ||
|
|
9daf992582 | ||
|
|
63945e0ce2 | ||
|
|
d9020de77b | ||
|
|
55ef205907 | ||
|
|
42aa42c892 | ||
|
|
2d07c20ea8 | ||
|
|
8b0b37aab4 | ||
|
|
6640ed629d | ||
|
|
f190c26311 | ||
|
|
48a007de3c | ||
|
|
af7ff2d8b5 | ||
|
|
3e44458f5c | ||
|
|
735a38ead6 | ||
|
|
3687a644d6 | ||
|
|
cca07229d2 | ||
|
|
2fe4b113b2 | ||
|
|
1d04683c06 | ||
|
|
47a9bd1c2c | ||
|
|
d03910315d | ||
|
|
960febfe00 | ||
|
|
44168de7a1 | ||
|
|
ef30352ae3 | ||
|
|
b69505206c | ||
|
|
542ca4f1eb | ||
|
|
04a06e85ec | ||
|
|
797610a364 | ||
|
|
1e28bc5eef | ||
|
|
9346a819f5 | ||
|
|
4eb8faa5d9 | ||
|
|
ed5ec61e7c | ||
|
|
5fd71cf25e | ||
|
|
9f41b9d9fa | ||
|
|
942fff68a2 | ||
|
|
397f9bf587 | ||
|
|
0d7e54364a | ||
|
|
bfc2ecea1c | ||
|
|
4d1a583939 | ||
|
|
eb7e2d83af | ||
|
|
ce3caef085 | ||
|
|
a39dcfba10 | ||
|
|
ce3dbbfbc6 | ||
|
|
d8cb1b4a68 | ||
|
|
0455e03bfd | ||
|
|
c155d340b5 | ||
|
|
434f346688 | ||
|
|
4719c2d3a3 | ||
|
|
ae596b9df4 | ||
|
|
3b54fd27bb | ||
|
|
f463d3d6aa | ||
|
|
b9bca31b57 | ||
|
|
5ad5cca2ed | ||
|
|
fd720f2a27 | ||
|
|
02957fa132 | ||
|
|
2310f99787 | ||
|
|
fea67e752b | ||
|
|
0c2396eb12 | ||
|
|
232109c2c7 | ||
|
|
8c6ca5a4bd | ||
|
|
9d1dc4e0bb | ||
|
|
caff9af1a3 | ||
|
|
b810dec766 | ||
|
|
929086061d | ||
|
|
7cb70978d6 | ||
|
|
1c716546d5 | ||
|
|
4f9acb68a6 | ||
|
|
1e669e100a | ||
|
|
d5198edfc0 | ||
|
|
39bba3623a | ||
|
|
62dac2193f | ||
|
|
72da0734c8 | ||
|
|
69b4b76501 | ||
|
|
ae56e27e5f | ||
|
|
d6bb6a891d | ||
|
|
13e342f64f | ||
|
|
1bda15e353 | ||
|
|
2f83b0baa7 | ||
|
|
7ec0963e32 | ||
|
|
04728690ca | ||
|
|
a928d72aac | ||
|
|
4475bf038b | ||
|
|
2a31d740d5 | ||
|
|
53044d2790 | ||
|
|
7a36e48401 | ||
|
|
ebc75e71d3 | ||
|
|
1c779b05c3 | ||
|
|
9e6ee505ca | ||
|
|
ed15620884 | ||
|
|
680583addf | ||
|
|
545a9b2544 | ||
|
|
cac4f800ed | ||
|
|
1516633aea | ||
|
|
b25df2c7a8 | ||
|
|
1718ba5695 | ||
|
|
60acb8e744 | ||
|
|
1cf47b91e2 | ||
|
|
a159bdbff1 | ||
|
|
95c445c40f | ||
|
|
2826360627 | ||
|
|
3690ea0332 | ||
|
|
703fad7d39 | ||
|
|
913c81409a | ||
|
|
ff0c0de926 | ||
|
|
f6799c0436 | ||
|
|
73bb7ffdab | ||
|
|
39a69e60c9 | ||
|
|
ef5a3701a0 | ||
|
|
3c0780e410 | ||
|
|
3d5112f545 | ||
|
|
4d20ac07e9 | ||
|
|
9145149015 | ||
|
|
08bbfc6276 | ||
|
|
664ec1803f | ||
|
|
47f588e003 | ||
|
|
380d7d7170 | ||
|
|
bae5393b60 | ||
|
|
47db3fdbcd | ||
|
|
3c7134002d | ||
|
|
1c021368d1 | ||
|
|
482f48ed6d | ||
|
|
6c1bcfd5cb | ||
|
|
3847c44994 | ||
|
|
a994d0dc16 | ||
|
|
c10a136110 | ||
|
|
b09a1701cd | ||
|
|
bff174fdb6 | ||
|
|
231d20149a | ||
|
|
dc3d522443 | ||
|
|
1b5ee1d07a | ||
|
|
ff7523ecb8 | ||
|
|
b53fdadaee | ||
|
|
93390bef63 | ||
|
|
485e2ef4f1 | ||
|
|
9de3b5efb6 | ||
|
|
2632282bba | ||
|
|
7379f50792 | ||
|
|
9ae53d090f | ||
|
|
677c7bb4cc | ||
|
|
4fdc241b9c | ||
|
|
1c4879e57b | ||
|
|
06ca7603b9 | ||
|
|
28dc4867db | ||
|
|
1cf13da413 | ||
|
|
3919efaa77 | ||
|
|
a76fc780cb | ||
|
|
d915c123db | ||
|
|
151c9c0add | ||
|
|
f14dc497cf | ||
|
|
89339e1033 | ||
|
|
146a61c9cf | ||
|
|
5250d97935 | ||
|
|
18dce9795d | ||
|
|
7add2bb12e | ||
|
|
756fc07193 | ||
|
|
71a5722b0e | ||
|
|
4507135a1b | ||
|
|
7f2479f597 | ||
|
|
66b97be9d2 | ||
|
|
57909ebc61 | ||
|
|
d1090670a8 | ||
|
|
f4bcad1b06 | ||
|
|
6656708c8e | ||
|
|
bfe3fb2ed0 | ||
|
|
ec21521281 | ||
|
|
e71e671d7d | ||
|
|
df6b0fae21 | ||
|
|
69723a8bf4 | ||
|
|
76d907987a | ||
|
|
241caa6132 | ||
|
|
13b93f6d9d | ||
|
|
77555366f4 | ||
|
|
f3e8132bfc | ||
|
|
7510385cf4 | ||
|
|
e05b72615e | ||
|
|
b3f69d4088 | ||
|
|
8796c8fe06 | ||
|
|
b9a6a98fee | ||
|
|
acc9145d52 | ||
|
|
f9c8f53474 | ||
|
|
004e96517f | ||
|
|
957265b1c8 | ||
|
|
8807e282f4 | ||
|
|
c394974dc8 | ||
|
|
28386a4234 | ||
|
|
6f16c47d4f | ||
|
|
25062e37f4 | ||
|
|
2b1f8e4335 | ||
|
|
02690b6796 | ||
|
|
3897281015 | ||
|
|
8d0e5b93ed | ||
|
|
ef146032df | ||
|
|
1dc025fb36 | ||
|
|
30c0c84b93 | ||
|
|
4bd139f93b | ||
|
|
f59787add0 | ||
|
|
20c304a2db | ||
|
|
53526d9c80 | ||
|
|
68b4bc66ff | ||
|
|
805149daea | ||
|
|
b2529207e1 | ||
|
|
d2fe9b0590 | ||
|
|
eff4f82ad7 | ||
|
|
57327332c9 | ||
|
|
a2144ccb61 | ||
|
|
aa478fc510 | ||
|
|
659a0bc0fd | ||
|
|
f1ef28e544 | ||
|
|
fef680fb99 | ||
|
|
91a45a621a | ||
|
|
fe9512ca9c | ||
|
|
ff318599f5 | ||
|
|
d1ba90408d | ||
|
|
536f8d9cb9 | ||
|
|
6a9e871b08 | ||
|
|
d163d145d0 | ||
|
|
fdf0506976 | ||
|
|
c9d8fc3072 | ||
|
|
0bcf67a5f5 | ||
|
|
3e48753329 | ||
|
|
96441dbb33 | ||
|
|
6a0b63b185 | ||
|
|
9dea43fd34 | ||
|
|
465980dd8c | ||
|
|
03d04fd8d1 | ||
|
|
7d18c9b160 | ||
|
|
c097f98959 | ||
|
|
213d4ad928 | ||
|
|
710b3b00f5 | ||
|
|
d041d03fbf | ||
|
|
24b90e9888 | ||
|
|
4b83e798ac | ||
|
|
468f93f3df | ||
|
|
78d9dd5acb | ||
|
|
6ef7d4653d | ||
|
|
645eb637f2 | ||
|
|
268fdce5ac | ||
|
|
f9f3a05a43 | ||
|
|
8a92919b2e | ||
|
|
dbcd675300 | ||
|
|
4628af0e43 | ||
|
|
b1fedf5904 | ||
|
|
45ec03e615 | ||
|
|
570d36b695 | ||
|
|
b36697054e | ||
|
|
17149fe853 | ||
|
|
15c837f745 | ||
|
|
3f43ff05d0 | ||
|
|
d4dee21383 | ||
|
|
79da904767 | ||
|
|
0821797044 | ||
|
|
ad7ff62b56 | ||
|
|
f148d7d0d0 | ||
|
|
e19e3865e7 | ||
|
|
35f062d4e0 | ||
|
|
01328ba33c | ||
|
|
7caa138184 | ||
|
|
1b8c3f3081 | ||
|
|
3e4f36fb6f | ||
|
|
aedcb973f5 | ||
|
|
26dc720929 | ||
|
|
b5cc1c06df | ||
|
|
786c790307 | ||
|
|
3e8660bb61 | ||
|
|
997aed4ab3 | ||
|
|
f64ea058b9 | ||
|
|
96485ba252 | ||
|
|
a9bdcbcdd4 | ||
|
|
1d7f1cccba | ||
|
|
b002477c0d | ||
|
|
27f1447469 | ||
|
|
ff153cdd81 | ||
|
|
fe16329443 | ||
|
|
744e1cf2be | ||
|
|
ab2cf8c8c7 | ||
|
|
fbd001b797 | ||
|
|
4610be6f15 | ||
|
|
d5e34b649f | ||
|
|
7b49a94edd | ||
|
|
8dfcda6c5e | ||
|
|
756d97a9cb | ||
|
|
c0887dbeb9 | ||
|
|
b8f0ff217f | ||
|
|
cc805781e3 | ||
|
|
9531eca7a7 | ||
|
|
d7a1d5bbd2 | ||
|
|
c214168dcd | ||
|
|
dd085be5c7 | ||
|
|
bd7fbfff37 | ||
|
|
52a25fc720 | ||
|
|
384153d914 | ||
|
|
511ac5068b | ||
|
|
67e490ab53 | ||
|
|
b84cde1633 | ||
|
|
3350f7bd56 | ||
|
|
7510419836 | ||
|
|
7da3ef4e0c | ||
|
|
4c32171fbb | ||
|
|
470f178cde | ||
|
|
f9633505a2 | ||
|
|
de102d9898 | ||
|
|
9d503b12e6 | ||
|
|
4dc3bc1532 | ||
|
|
50da8cfbc6 | ||
|
|
bccfc127f3 | ||
|
|
2332d8756d | ||
|
|
a4abaed30a | ||
|
|
d47e18df1f | ||
|
|
c2d094da35 | ||
|
|
6e54b10239 | ||
|
|
e6c44ec52a | ||
|
|
39b8ecf785 | ||
|
|
d87f871334 | ||
|
|
07cea56e2b | ||
|
|
dbf3226f97 | ||
|
|
4b926edf24 | ||
|
|
ce0fd42995 | ||
|
|
bdf91443e0 | ||
|
|
68f4237e15 | ||
|
|
81fc747c03 | ||
|
|
3a25ed13b9 | ||
|
|
21c5eb6786 | ||
|
|
e85203e429 | ||
|
|
6b2d10d589 | ||
|
|
3d03de193e | ||
|
|
a56de72a6b | ||
|
|
0849bbbba6 | ||
|
|
0cd41d2036 | ||
|
|
a93bcd6ab6 | ||
|
|
77b72e160b | ||
|
|
b32c37f4af | ||
|
|
d0beea5cb3 | ||
|
|
30df6887c5 | ||
|
|
bc7823dda1 | ||
|
|
cbb195a313 | ||
|
|
097dc06c65 | ||
|
|
b06fbd25a0 | ||
|
|
89bbf274e5 | ||
|
|
d854177e5a | ||
|
|
aa9f82f2d4 | ||
|
|
2b45264628 | ||
|
|
4da299f431 | ||
|
|
9f9aa447a6 | ||
|
|
6a9f1597cb | ||
|
|
cddc48b851 | ||
|
|
84ab6d300c | ||
|
|
3c5026c2fb | ||
|
|
c3c8959d2e | ||
|
|
2c459d2636 | ||
|
|
a33c481dd5 | ||
|
|
d6b2f93e54 | ||
|
|
802e945829 | ||
|
|
a4a885f33a | ||
|
|
3380cebb28 | ||
|
|
21ed415f4f | ||
|
|
51dd89d36a | ||
|
|
bad96f231c | ||
|
|
184d72c444 | ||
|
|
6ca773050f | ||
|
|
648e8aaae0 | ||
|
|
ad9868b575 | ||
|
|
d4d10998f8 | ||
|
|
ba22c31deb | ||
|
|
f6be133a78 | ||
|
|
3768164f1f | ||
|
|
8465e7539f | ||
|
|
542eca5867 | ||
|
|
27a67c5f4a | ||
|
|
e00c40f2d5 | ||
|
|
b664e231dc | ||
|
|
92d6977f9e | ||
|
|
4059700468 | ||
|
|
196bdd83ba | ||
|
|
fbd52bc14e | ||
|
|
8013c988d0 | ||
|
|
460d6fcf12 | ||
|
|
92353c4853 | ||
|
|
8ca2a89f0f | ||
|
|
f54c2367f3 | ||
|
|
27452085e9 | ||
|
|
2bff7d9567 | ||
|
|
c3749f62fe | ||
|
|
b82c04a16a | ||
|
|
0ec099cdf5 | ||
|
|
d3f49094d8 | ||
|
|
4e2ad3bc62 | ||
|
|
05c287fcf7 | ||
|
|
c11cef4119 | ||
|
|
d6126cc5ce | ||
|
|
d88c925a68 | ||
|
|
372a572400 | ||
|
|
623ee8fbb1 | ||
|
|
729e0fc5ca | ||
|
|
d052cde6ca | ||
|
|
b52bbab903 | ||
|
|
9d42135ebf | ||
|
|
9ce5aa2189 | ||
|
|
e277292194 | ||
|
|
649961c831 | ||
|
|
e00cde2fbd | ||
|
|
25b89d191b | ||
|
|
0a60f77bfc | ||
|
|
66a80e439f | ||
|
|
d8cc25a54f | ||
|
|
39b9cfb348 | ||
|
|
c6087574be | ||
|
|
41c63cbfe9 | ||
|
|
f1afc81e7d | ||
|
|
018f8a19bb | ||
|
|
cccd007ba6 | ||
|
|
6d5b8baadf | ||
|
|
07e36415e4 | ||
|
|
8dc480826b | ||
|
|
533a5b87ec | ||
|
|
7bd83557c1 | ||
|
|
ef290e79b1 | ||
|
|
713b3f4f6d | ||
|
|
8fd9614f69 | ||
|
|
6682a98770 | ||
|
|
392b405978 | ||
|
|
be61850d18 | ||
|
|
f4208a2212 | ||
|
|
0b7278a2a8 | ||
|
|
bee078fe18 |
@@ -6,7 +6,7 @@ orbs:
|
||||
aws-cli: circleci/aws-cli@4.0
|
||||
eb: circleci/aws-elastic-beanstalk@2.0.1
|
||||
jobs:
|
||||
api-deploy:
|
||||
imex-api-deploy:
|
||||
docker:
|
||||
- image: cimg/node:18.18.2
|
||||
steps:
|
||||
@@ -19,9 +19,9 @@ jobs:
|
||||
eb deploy
|
||||
eb status
|
||||
|
||||
hasura-migrate:
|
||||
imex-hasura-migrate:
|
||||
docker:
|
||||
- image: cimg/node:16.15.0
|
||||
- image: cimg/node:18.18.2
|
||||
parameters:
|
||||
secret:
|
||||
type: string
|
||||
@@ -38,30 +38,10 @@ jobs:
|
||||
hasura metadata apply --endpoint https://db.imex.online/ --admin-secret << parameters.secret >>
|
||||
hasura metadata reload --endpoint https://db.imex.online/ --admin-secret << parameters.secret >>
|
||||
|
||||
app-build:
|
||||
docker:
|
||||
- image: cimg/node:16.15.0
|
||||
resource_class: large
|
||||
working_directory: ~/repo/client
|
||||
|
||||
steps:
|
||||
- checkout:
|
||||
path: ~/repo
|
||||
- run:
|
||||
name: Install Dependencies
|
||||
command: npm i
|
||||
|
||||
- run: npm run build
|
||||
|
||||
- aws-s3/sync:
|
||||
from: build
|
||||
to: "s3://imex-online-production/"
|
||||
arguments: "--exclude '*.map'"
|
||||
|
||||
app-beta-build:
|
||||
imex-app-build:
|
||||
docker:
|
||||
- image: cimg/node:18.18.2
|
||||
resource_class: large
|
||||
|
||||
working_directory: ~/repo/client
|
||||
|
||||
steps:
|
||||
@@ -71,7 +51,7 @@ jobs:
|
||||
name: Install Dependencies
|
||||
command: npm i
|
||||
|
||||
- run: npm run build
|
||||
- run: npm run build:imex
|
||||
|
||||
- aws-cli/setup:
|
||||
aws_access_key_id: AWS_ACCESS_KEY_ID
|
||||
@@ -80,9 +60,106 @@ jobs:
|
||||
|
||||
- aws-s3/sync:
|
||||
from: build
|
||||
to: "s3://imex-online-beta/"
|
||||
to: "s3://imex-online-production/"
|
||||
arguments: "--exclude '*.map'"
|
||||
|
||||
rome-api-deploy:
|
||||
docker:
|
||||
- image: "cimg/base:stable"
|
||||
steps:
|
||||
- checkout
|
||||
- eb/setup
|
||||
- run:
|
||||
command: |
|
||||
eb init romeonline-productionapi -r us-east-2 -p "Node.js 18 running on 64bit Amazon Linux 2"
|
||||
eb status --verbose
|
||||
eb deploy
|
||||
eb status
|
||||
|
||||
rome-hasura-migrate:
|
||||
docker:
|
||||
- image: cimg/node:18.18.2
|
||||
parameters:
|
||||
secret:
|
||||
type: string
|
||||
default: $HASURA_ROME_PROD_SECRET
|
||||
working_directory: ~/repo/hasura
|
||||
steps:
|
||||
- checkout:
|
||||
path: ~/repo
|
||||
- run:
|
||||
name: Execute migration
|
||||
command: |
|
||||
npm install hasura-cli -g
|
||||
hasura migrate apply --endpoint https://db.romeonline.io/ --admin-secret << parameters.secret >>
|
||||
hasura metadata apply --endpoint https://db.romeonline.io/ --admin-secret << parameters.secret >>
|
||||
hasura metadata reload --endpoint https://db.romeonline.io/ --admin-secret << parameters.secret >>
|
||||
|
||||
rome-app-build:
|
||||
docker:
|
||||
- image: cimg/node:18.18.2
|
||||
|
||||
working_directory: ~/repo/client
|
||||
|
||||
steps:
|
||||
- checkout:
|
||||
path: ~/repo
|
||||
- run:
|
||||
name: Install Dependencies
|
||||
command: npm i
|
||||
|
||||
- run: npm run build:rome
|
||||
|
||||
- aws-cli/setup:
|
||||
aws_access_key_id: AWS_ACCESS_KEY_ID
|
||||
aws_secret_access_key: AWS_SECRET_ACCESS_KEY
|
||||
region: AWS_REGION
|
||||
|
||||
- aws-s3/sync:
|
||||
from: build
|
||||
to: "s3://rome-online-production/"
|
||||
arguments: "--exclude '*.map'"
|
||||
|
||||
test-rome-hasura-migrate:
|
||||
docker:
|
||||
- image: cimg/node:16.15.0
|
||||
parameters:
|
||||
secret:
|
||||
type: string
|
||||
default: $HASURA_ROME_TEST_SECRET
|
||||
working_directory: ~/repo/hasura
|
||||
steps:
|
||||
- checkout:
|
||||
path: ~/repo
|
||||
- run:
|
||||
name: Execute migration
|
||||
command: |
|
||||
npm install hasura-cli -g
|
||||
hasura migrate apply --endpoint https://db.test.romeonline.io/ --admin-secret << parameters.secret >>
|
||||
hasura metadata apply --endpoint https://db.test.romeonline.io/ --admin-secret << parameters.secret >>
|
||||
hasura metadata reload --endpoint https://db.test.romeonline.io/ --admin-secret << parameters.secret >>
|
||||
|
||||
test-rome-app-build:
|
||||
docker:
|
||||
- image: cimg/node:18.18.2
|
||||
|
||||
working_directory: ~/repo/client
|
||||
|
||||
steps:
|
||||
- checkout:
|
||||
path: ~/repo
|
||||
- run:
|
||||
name: Install Dependencies
|
||||
command: npm i
|
||||
|
||||
- run: npm run build:test:rome
|
||||
|
||||
- aws-s3/sync:
|
||||
from: build
|
||||
to: "s3://rome-online-test/"
|
||||
arguments: "--exclude '*.map'"
|
||||
|
||||
|
||||
test-hasura-migrate:
|
||||
docker:
|
||||
- image: cimg/node:16.15.0
|
||||
@@ -98,12 +175,11 @@ jobs:
|
||||
name: Execute migration
|
||||
command: |
|
||||
npm install hasura-cli -g
|
||||
echo ${HASURA_TEST_SECRET}
|
||||
hasura migrate apply --endpoint https://db.test.bodyshop.app/ --admin-secret << parameters.secret >>
|
||||
hasura metadata apply --endpoint https://db.test.bodyshop.app/ --admin-secret << parameters.secret >>
|
||||
hasura metadata reload --endpoint https://db.test.bodyshop.app/ --admin-secret << parameters.secret >>
|
||||
|
||||
test-app-build:
|
||||
imex-test-app-build:
|
||||
docker:
|
||||
- image: cimg/node:16.15.0
|
||||
resource_class: large
|
||||
@@ -116,40 +192,13 @@ jobs:
|
||||
name: Install Dependencies
|
||||
command: npm i
|
||||
|
||||
- run: npm run build:test
|
||||
- run: npm run build:test:imex
|
||||
|
||||
- aws-s3/sync:
|
||||
from: build
|
||||
to: "s3://imex-online-test/"
|
||||
arguments: "--exclude '*.map'"
|
||||
|
||||
test-app-beta-build:
|
||||
docker:
|
||||
- image: cimg/node:18.18.2
|
||||
resource_class: large
|
||||
working_directory: ~/repo/client
|
||||
|
||||
steps:
|
||||
- checkout:
|
||||
path: ~/repo
|
||||
|
||||
- run:
|
||||
name: Install Dependencies
|
||||
command: npm i
|
||||
|
||||
- run: npm run build:test
|
||||
|
||||
- run: npm run sentry:sourcemaps
|
||||
|
||||
- aws-cli/setup:
|
||||
aws_access_key_id: AWS_ACCESS_KEY_ID
|
||||
aws_secret_access_key: AWS_SECRET_ACCESS_KEY
|
||||
region: AWS_REGION
|
||||
|
||||
- aws-s3/sync:
|
||||
from: build
|
||||
to: "s3://imex-online-test-beta/"
|
||||
arguments: "--exclude '*.map'"
|
||||
|
||||
admin-app-build:
|
||||
docker:
|
||||
@@ -184,36 +233,51 @@ jobs:
|
||||
workflows:
|
||||
deploy_and_build:
|
||||
jobs:
|
||||
- api-deploy:
|
||||
- imex-api-deploy:
|
||||
filters:
|
||||
branches:
|
||||
only: master
|
||||
- app-build:
|
||||
- imex-app-build:
|
||||
filters:
|
||||
branches:
|
||||
only: master
|
||||
- app-beta-build:
|
||||
filters:
|
||||
branches:
|
||||
only: master-beta
|
||||
- hasura-migrate:
|
||||
secret: ${HASURA_PROD_SECRET}
|
||||
filters:
|
||||
branches:
|
||||
only: master
|
||||
- test-app-build:
|
||||
- rome-api-deploy:
|
||||
filters:
|
||||
branches:
|
||||
only: rome/master
|
||||
- rome-app-build:
|
||||
filters:
|
||||
branches:
|
||||
only: rome/master
|
||||
- rome-hasura-migrate:
|
||||
secret: ${HASURA_PROD_SECRET}
|
||||
filters:
|
||||
branches:
|
||||
only: rome/master
|
||||
- imex-test-app-build:
|
||||
filters:
|
||||
branches:
|
||||
only: test
|
||||
- test-app-beta-build:
|
||||
filters:
|
||||
branches:
|
||||
only: test-beta
|
||||
|
||||
- test-hasura-migrate:
|
||||
secret: ${HASURA_TEST_SECRET}
|
||||
filters:
|
||||
branches:
|
||||
only: test
|
||||
- test-rome-app-build:
|
||||
filters:
|
||||
branches:
|
||||
only: rome/test
|
||||
- test-rome-hasura-migrate:
|
||||
secret: ${HASURA_ROME_TEST_SECRET}
|
||||
filters:
|
||||
branches:
|
||||
only: rome/test
|
||||
#- admin-app-build:
|
||||
#filters:
|
||||
#branches:
|
||||
|
||||
21
.editorconfig
Normal file
@@ -0,0 +1,21 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = false
|
||||
quote_type = single
|
||||
max_line_length = 100
|
||||
bracketSpacing = false
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[*.yml]
|
||||
indent_size = 2
|
||||
|
||||
[*.json]
|
||||
indent_size = 2
|
||||
3
.gitignore
vendored
@@ -21,6 +21,7 @@ admin/coverage
|
||||
/build
|
||||
client/build
|
||||
admin/build
|
||||
client/dist
|
||||
# misc
|
||||
.DS_Store
|
||||
.env
|
||||
@@ -119,4 +120,4 @@ logs/oAuthClient-log.log
|
||||
|
||||
/*.env.*
|
||||
.idea/*
|
||||
.idea
|
||||
.idea
|
||||
|
||||
16
.prettierrc.js
Normal file
@@ -0,0 +1,16 @@
|
||||
exports.default = {
|
||||
printWidth: 120,
|
||||
useTabs: false,
|
||||
tabWidth: 2,
|
||||
trailingComma: 'es5',
|
||||
semi: true,
|
||||
singleQuote: false,
|
||||
bracketSpacing: true,
|
||||
arrowParens: 'always',
|
||||
jsxSingleQuote: false,
|
||||
bracketSameLine: false,
|
||||
endOfLine: 'lf',
|
||||
importOrder: ['^@core/(.*)$', '^@server/(.*)$', '^@ui/(.*)$', '^[./]'],
|
||||
importOrderSeparation: true,
|
||||
importOrderSortSpecifiers: true,
|
||||
};
|
||||
14
_reference/BodyshopFeatures.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"mobile": "date",
|
||||
"allAccess": "bool",
|
||||
"timetickets": "date",
|
||||
"payments": "date",
|
||||
"partsorders": "date",
|
||||
"bills": "Date",
|
||||
"export": "date",
|
||||
"csi": "Date",
|
||||
"courtesycars": "date",
|
||||
"media": "date",
|
||||
"visualboard": "date",
|
||||
"scoreboard": "date"
|
||||
}
|
||||
@@ -3,6 +3,12 @@
|
||||
This documentation details the schema required for `.filters` files on the report server. It is used to dynamically
|
||||
modify the graphQL query and provide the user more power over their reports.
|
||||
|
||||
For filters and sorters, valid types include (`type` key in the schema):
|
||||
- string (default)
|
||||
- number
|
||||
- bool or boolean
|
||||
- date
|
||||
|
||||
# Special Notes
|
||||
- When passing the data to the template server, the property filters and sorters is added to the data object and will reflect the filters and sorters the user has selected
|
||||
|
||||
@@ -67,6 +73,8 @@ The following cases are available
|
||||
- `special.employees` - This will reflect the employees `bodyshop.employees`
|
||||
- `special.first_names` - This will reflect the first names `bodyshop.employees`
|
||||
- `special.last_names` - This will reflect the last names `bodyshop.employees`
|
||||
- `special.referral_sources` - This will reflect the referral sources `bodyshop.md_referral_sources
|
||||
- `special.class`- This will reflect the class `bodyshop.md_classes`
|
||||
-
|
||||
### Path without brackets, multi level
|
||||
|
||||
@@ -142,8 +150,7 @@ query gendoc_hours_sold_detail_open($starttz: timestamptz!, $endtz: timestamptz!
|
||||
|
||||
- Will only support two level of nesting in the graphQL query `jobs.joblines.mod_lb_hrs` vs `[jobs].joblines.mod_lb_hrs`
|
||||
is fine, but `jobs.[joblines.].some_table.mod_lb_hrs` is not.
|
||||
- The `dates` object is not yet implemented and will be added in a future release.
|
||||
- The type object must be 'string' or 'number' and is case-sensitive.
|
||||
- The type object must be 'string' or 'number' or 'bool' or 'boolean' or 'date' and is case-sensitive.
|
||||
- The `translation` key is used to look up the label in the GUI, if it is not found, the `label` key is used.
|
||||
- Do not add the ability to filter things that are already filtered as part of the original query, this would be
|
||||
redundant and could cause issues.
|
||||
@@ -172,4 +179,4 @@ query gendoc_hours_sold_detail_open($starttz: timestamptz!, $endtz: timestamptz!
|
||||
"direction": "asc"
|
||||
}
|
||||
}
|
||||
```
|
||||
```
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
REACT_APP_GRAPHQL_ENDPOINT=https://db.dev.bodyshop.app/v1/graphql
|
||||
REACT_APP_GRAPHQL_ENDPOINT_WS=wss://db.dev.bodyshop.app/v1/graphql
|
||||
REACT_APP_GA_CODE=231099835
|
||||
REACT_APP_FIREBASE_CONFIG={"apiKey":"AIzaSyDPLT8GiDHDR1R4nI66Qi0BY1aYviDPioc","authDomain":"imex-dev.firebaseapp.com","databaseURL":"https://imex-dev.firebaseio.com","projectId":"imex-dev","storageBucket":"imex-dev.appspot.com","messagingSenderId":"759548147434","appId":"1:759548147434:web:e8239868a48ceb36700993","measurementId":"G-K5XRBVVB4S"}
|
||||
REACT_APP_CLOUDINARY_ENDPOINT_API=https://api.cloudinary.com/v1_1/io-test
|
||||
REACT_APP_CLOUDINARY_ENDPOINT=https://res.cloudinary.com/io-test
|
||||
REACT_APP_CLOUDINARY_API_KEY=957865933348715
|
||||
REACT_APP_CLOUDINARY_THUMB_TRANSFORMATIONS=c_fill,h_250,w_250
|
||||
REACT_APP_FIREBASE_PUBLIC_VAPID_KEY='BG3tzU7L2BXlGZ_3VLK4PNaRceoEXEnmHfxcVbRMF5o5g05ejslhVPki9kBM9cBBT-08Ad9kN3HSpS6JmrWD6h4'
|
||||
REACT_APP_STRIPE_PUBLIC_KEY=pk_test_51GqB4TJl3nQjrZ0wCQWAxAhlNF8jKe0tipIa6ExBaxwJGitwvFsIZUEua4dUzaMIAuXp4qwYHXx7lgjyQSwP0Pe900vzm38C7g
|
||||
REACT_APP_AXIOS_BASE_API_URL=http://localhost:4000
|
||||
REACT_APP_REPORTS_SERVER_URL=https://reports3.test.imex.online
|
||||
REACT_APP_SPLIT_API=ts615lqgnmk84thn72uk18uu5pgce6e0l4rc
|
||||
14
client/.env.development.imex
Normal file
@@ -0,0 +1,14 @@
|
||||
VITE_APP_GRAPHQL_ENDPOINT=https://db.dev.bodyshop.app/v1/graphql
|
||||
VITE_APP_GRAPHQL_ENDPOINT_WS=wss://db.dev.bodyshop.app/v1/graphql
|
||||
VITE_APP_GA_CODE=231099835
|
||||
VITE_APP_FIREBASE_CONFIG={"apiKey":"AIzaSyDPLT8GiDHDR1R4nI66Qi0BY1aYviDPioc","authDomain":"imex-dev.firebaseapp.com","databaseURL":"https://imex-dev.firebaseio.com","projectId":"imex-dev","storageBucket":"imex-dev.appspot.com","messagingSenderId":"759548147434","appId":"1:759548147434:web:e8239868a48ceb36700993","measurementId":"G-K5XRBVVB4S"}
|
||||
VITE_APP_CLOUDINARY_ENDPOINT_API=https://api.cloudinary.com/v1_1/io-test
|
||||
VITE_APP_CLOUDINARY_ENDPOINT=https://res.cloudinary.com/io-test
|
||||
VITE_APP_CLOUDINARY_API_KEY=957865933348715
|
||||
VITE_APP_CLOUDINARY_THUMB_TRANSFORMATIONS=c_fill,h_250,w_250
|
||||
VITE_APP_FIREBASE_PUBLIC_VAPID_KEY='BG3tzU7L2BXlGZ_3VLK4PNaRceoEXEnmHfxcVbRMF5o5g05ejslhVPki9kBM9cBBT-08Ad9kN3HSpS6JmrWD6h4'
|
||||
VITE_APP_STRIPE_PUBLIC_KEY=pk_test_51GqB4TJl3nQjrZ0wCQWAxAhlNF8jKe0tipIa6ExBaxwJGitwvFsIZUEua4dUzaMIAuXp4qwYHXx7lgjyQSwP0Pe900vzm38C7g
|
||||
VITE_APP_AXIOS_BASE_API_URL=http://localhost:4000
|
||||
VITE_APP_REPORTS_SERVER_URL=https://reports3.test.imex.online
|
||||
VITE_APP_SPLIT_API=ts615lqgnmk84thn72uk18uu5pgce6e0l4rc
|
||||
VITE_APP_INSTANCE=IMEX
|
||||
14
client/.env.development.promanager
Normal file
@@ -0,0 +1,14 @@
|
||||
VITE_APP_GRAPHQL_ENDPOINT=https://db.dev.bodyshop.app/v1/graphql
|
||||
VITE_APP_GRAPHQL_ENDPOINT_WS=wss://db.dev.bodyshop.app/v1/graphql
|
||||
VITE_APP_GA_CODE=231099835
|
||||
VITE_APP_FIREBASE_CONFIG={ "apiKey": "AIzaSyAuLQR9SV5LsVxjU8wh9hvFLdhcAHU6cxE", "authDomain": "rome-prod-1.firebaseapp.com", "projectId": "rome-prod-1", "storageBucket": "rome-prod-1.appspot.com", "messagingSenderId": "147786367145", "appId": "1:147786367145:web:9d4cba68071c3f29a8a9b8", "measurementId": "G-G8Z9DRHTZS"}
|
||||
VITE_APP_CLOUDINARY_ENDPOINT_API=https://api.cloudinary.com/v1_1/io-test
|
||||
VITE_APP_CLOUDINARY_ENDPOINT=https://res.cloudinary.com/io-test
|
||||
VITE_APP_CLOUDINARY_API_KEY=957865933348715
|
||||
VITE_APP_CLOUDINARY_THUMB_TRANSFORMATIONS=c_fill,h_250,w_250
|
||||
VITE_APP_FIREBASE_PUBLIC_VAPID_KEY='BG3tzU7L2BXlGZ_3VLK4PNaRceoEXEnmHfxcVbRMF5o5g05ejslhVPki9kBM9cBBT-08Ad9kN3HSpS6JmrWD6h4'
|
||||
VITE_APP_STRIPE_PUBLIC_KEY=pk_test_51GqB4TJl3nQjrZ0wCQWAxAhlNF8jKe0tipIa6ExBaxwJGitwvFsIZUEua4dUzaMIAuXp4qwYHXx7lgjyQSwP0Pe900vzm38C7g
|
||||
VITE_APP_AXIOS_BASE_API_URL=http://localhost:4000
|
||||
VITE_APP_REPORTS_SERVER_URL=https://reports3.test.imex.online
|
||||
VITE_APP_SPLIT_API=ts615lqgnmk84thn72uk18uu5pgce6e0l4rc
|
||||
VITE_APP_INSTANCE=PROMANAGER
|
||||
15
client/.env.development.rome
Normal file
@@ -0,0 +1,15 @@
|
||||
VITE_APP_GRAPHQL_ENDPOINT=https://db.dev.bodyshop.app/v1/graphql
|
||||
VITE_APP_GRAPHQL_ENDPOINT_WS=wss://db.dev.bodyshop.app/v1/graphql
|
||||
VITE_APP_GA_CODE=231099835
|
||||
VITE_APP_FIREBASE_CONFIG={ "apiKey": "AIzaSyAuLQR9SV5LsVxjU8wh9hvFLdhcAHU6cxE", "authDomain": "rome-prod-1.firebaseapp.com", "projectId": "rome-prod-1", "storageBucket": "rome-prod-1.appspot.com", "messagingSenderId": "147786367145", "appId": "1:147786367145:web:9d4cba68071c3f29a8a9b8", "measurementId": "G-G8Z9DRHTZS"}
|
||||
VITE_APP_CLOUDINARY_ENDPOINT_API=https://api.cloudinary.com/v1_1/io-test
|
||||
VITE_APP_CLOUDINARY_ENDPOINT=https://res.cloudinary.com/io-test
|
||||
VITE_APP_CLOUDINARY_API_KEY=957865933348715
|
||||
VITE_APP_CLOUDINARY_THUMB_TRANSFORMATIONS=c_fill,h_250,w_250
|
||||
VITE_APP_FIREBASE_PUBLIC_VAPID_KEY='BP1B7ZTYpn-KMt6nOxlld6aS8Skt3Q7ZLEqP0hAvGHxG4UojPYiXZ6kPlzZkUC5jH-EcWXomTLtmadAIxurfcHo'
|
||||
VITE_APP_STRIPE_PUBLIC_KEY=pk_test_51GqB4TJl3nQjrZ0wCQWAxAhlNF8jKe0tipIa6ExBaxwJGitwvFsIZUEua4dUzaMIAuXp4qwYHXx7lgjyQSwP0Pe900vzm38C7g
|
||||
VITE_APP_AXIOS_BASE_API_URL=http://localhost:4000
|
||||
VITE_APP_REPORTS_SERVER_URL=https://reports3.test.imex.online
|
||||
VITE_APP_SPLIT_API=ts615lqgnmk84thn72uk18uu5pgce6e0l4rc
|
||||
VITE_APP_COUNTRY=USA
|
||||
VITE_APP_INSTANCE=ROME
|
||||
@@ -1,14 +0,0 @@
|
||||
GENERATE_SOURCEMAP=true
|
||||
REACT_APP_GRAPHQL_ENDPOINT=https://db.imex.online/v1/graphql
|
||||
REACT_APP_GRAPHQL_ENDPOINT_WS=wss://db.imex.online/v1/graphql
|
||||
REACT_APP_GA_CODE=231103507
|
||||
REACT_APP_FIREBASE_CONFIG={"apiKey":"AIzaSyDSezy-jGJreo7ulgpLdlpOwAOrgcaEkhU","authDomain":"imex-prod.firebaseapp.com","databaseURL":"https://imex-prod.firebaseio.com","projectId":"imex-prod","storageBucket":"imex-prod.appspot.com","messagingSenderId":"253497221485","appId":"1:253497221485:web:3c81c483b94db84b227a64","measurementId":"G-NTWBKG2L0M"}
|
||||
REACT_APP_CLOUDINARY_ENDPOINT_API=https://api.cloudinary.com/v1_1/bodyshop
|
||||
REACT_APP_CLOUDINARY_ENDPOINT=https://res.cloudinary.com/bodyshop
|
||||
REACT_APP_CLOUDINARY_API_KEY=473322739956866
|
||||
REACT_APP_CLOUDINARY_THUMB_TRANSFORMATIONS=c_fill,h_250,w_250
|
||||
REACT_APP_FIREBASE_PUBLIC_VAPID_KEY='BMgZT1NZztW2DsJl8Mg2L04hgY9FzAg6b8fbzgNAfww2VDzH3VE63Ot9EaP_U7KWS2JT-7HPHaw0T_Tw_5vkZc8'
|
||||
REACT_APP_STRIPE_PUBLIC_KEY=pk_test_51GqB4TJl3nQjrZ0wCQWAxAhlNF8jKe0tipIa6ExBaxwJGitwvFsIZUEua4dUzaMIAuXp4qwYHXx7lgjyQSwP0Pe900vzm38C7g
|
||||
REACT_APP_AXIOS_BASE_API_URL=https://api.imex.online/
|
||||
REACT_APP_REPORTS_SERVER_URL=https://reports.imex.online
|
||||
REACT_APP_SPLIT_API=et9pjkik6bn67he5evpmpr1agoo7gactphgk
|
||||
15
client/.env.production.imex
Normal file
@@ -0,0 +1,15 @@
|
||||
GENERATE_SOURCEMAP=true
|
||||
VITE_APP_GRAPHQL_ENDPOINT=https://db.imex.online/v1/graphql
|
||||
VITE_APP_GRAPHQL_ENDPOINT_WS=wss://db.imex.online/v1/graphql
|
||||
VITE_APP_GA_CODE=231103507
|
||||
VITE_APP_FIREBASE_CONFIG={"apiKey":"AIzaSyDSezy-jGJreo7ulgpLdlpOwAOrgcaEkhU","authDomain":"imex-prod.firebaseapp.com","databaseURL":"https://imex-prod.firebaseio.com","projectId":"imex-prod","storageBucket":"imex-prod.appspot.com","messagingSenderId":"253497221485","appId":"1:253497221485:web:3c81c483b94db84b227a64","measurementId":"G-NTWBKG2L0M"}
|
||||
VITE_APP_CLOUDINARY_ENDPOINT_API=https://api.cloudinary.com/v1_1/bodyshop
|
||||
VITE_APP_CLOUDINARY_ENDPOINT=https://res.cloudinary.com/bodyshop
|
||||
VITE_APP_CLOUDINARY_API_KEY=473322739956866
|
||||
VITE_APP_CLOUDINARY_THUMB_TRANSFORMATIONS=c_fill,h_250,w_250
|
||||
VITE_APP_FIREBASE_PUBLIC_VAPID_KEY='BMgZT1NZztW2DsJl8Mg2L04hgY9FzAg6b8fbzgNAfww2VDzH3VE63Ot9EaP_U7KWS2JT-7HPHaw0T_Tw_5vkZc8'
|
||||
VITE_APP_STRIPE_PUBLIC_KEY=pk_test_51GqB4TJl3nQjrZ0wCQWAxAhlNF8jKe0tipIa6ExBaxwJGitwvFsIZUEua4dUzaMIAuXp4qwYHXx7lgjyQSwP0Pe900vzm38C7g
|
||||
VITE_APP_AXIOS_BASE_API_URL=https://api.imex.online/
|
||||
VITE_APP_REPORTS_SERVER_URL=https://reports.imex.online
|
||||
VITE_APP_SPLIT_API=et9pjkik6bn67he5evpmpr1agoo7gactphgk
|
||||
VITE_APP_INSTANCE=IMEX
|
||||
15
client/.env.production.promanager
Normal file
@@ -0,0 +1,15 @@
|
||||
GENERATE_SOURCEMAP=true
|
||||
VITE_APP_GRAPHQL_ENDPOINT=https://db.romeonline.io/v1/graphql
|
||||
VITE_APP_GRAPHQL_ENDPOINT_WS=wss://db.romeonline.io/v1/graphql
|
||||
VITE_APP_GA_CODE=231103507
|
||||
VITE_APP_FIREBASE_CONFIG={ "apiKey": "AIzaSyAuLQR9SV5LsVxjU8wh9hvFLdhcAHU6cxE", "authDomain": "rome-prod-1.firebaseapp.com", "projectId": "rome-prod-1", "storageBucket": "rome-prod-1.appspot.com", "messagingSenderId": "147786367145", "appId": "1:147786367145:web:9d4cba68071c3f29a8a9b8", "measurementId": "G-G8Z9DRHTZS"}
|
||||
VITE_APP_CLOUDINARY_ENDPOINT_API=https://api.cloudinary.com/v1_1/bodyshop
|
||||
VITE_APP_CLOUDINARY_ENDPOINT=https://res.cloudinary.com/bodyshop
|
||||
VITE_APP_CLOUDINARY_API_KEY=473322739956866
|
||||
VITE_APP_CLOUDINARY_THUMB_TRANSFORMATIONS=c_fill,h_250,w_250
|
||||
VITE_APP_FIREBASE_PUBLIC_VAPID_KEY='BMgZT1NZztW2DsJl8Mg2L04hgY9FzAg6b8fbzgNAfww2VDzH3VE63Ot9EaP_U7KWS2JT-7HPHaw0T_Tw_5vkZc8'
|
||||
VITE_APP_STRIPE_PUBLIC_KEY=pk_test_51GqB4TJl3nQjrZ0wCQWAxAhlNF8jKe0tipIa6ExBaxwJGitwvFsIZUEua4dUzaMIAuXp4qwYHXx7lgjyQSwP0Pe900vzm38C7g
|
||||
VITE_APP_AXIOS_BASE_API_URL=https://api.romeonline.io/
|
||||
VITE_APP_REPORTS_SERVER_URL=https://reports.romeonline.io
|
||||
VITE_APP_SPLIT_API=et9pjkik6bn67he5evpmpr1agoo7gactphgk
|
||||
VITE_APP_INSTANCE=PROMANAGER
|
||||
15
client/.env.production.rome
Normal file
@@ -0,0 +1,15 @@
|
||||
GENERATE_SOURCEMAP=true
|
||||
VITE_APP_GRAPHQL_ENDPOINT=https://db.romeonline.io/v1/graphql
|
||||
VITE_APP_GRAPHQL_ENDPOINT_WS=wss://db.romeonline.io/v1/graphql
|
||||
VITE_APP_GA_CODE=231103507
|
||||
VITE_APP_FIREBASE_CONFIG={ "apiKey": "AIzaSyAuLQR9SV5LsVxjU8wh9hvFLdhcAHU6cxE", "authDomain": "rome-prod-1.firebaseapp.com", "projectId": "rome-prod-1", "storageBucket": "rome-prod-1.appspot.com", "messagingSenderId": "147786367145", "appId": "1:147786367145:web:9d4cba68071c3f29a8a9b8", "measurementId": "G-G8Z9DRHTZS"}
|
||||
VITE_APP_CLOUDINARY_ENDPOINT_API=https://api.cloudinary.com/v1_1/bodyshop
|
||||
VITE_APP_CLOUDINARY_ENDPOINT=https://res.cloudinary.com/bodyshop
|
||||
VITE_APP_CLOUDINARY_API_KEY=473322739956866
|
||||
VITE_APP_CLOUDINARY_THUMB_TRANSFORMATIONS=c_fill,h_250,w_250
|
||||
VITE_APP_FIREBASE_PUBLIC_VAPID_KEY='BP1B7ZTYpn-KMt6nOxlld6aS8Skt3Q7ZLEqP0hAvGHxG4UojPYiXZ6kPlzZkUC5jH-EcWXomTLtmadAIxurfcHo'
|
||||
VITE_APP_STRIPE_PUBLIC_KEY=pk_test_51GqB4TJl3nQjrZ0wCQWAxAhlNF8jKe0tipIa6ExBaxwJGitwvFsIZUEua4dUzaMIAuXp4qwYHXx7lgjyQSwP0Pe900vzm38C7g
|
||||
VITE_APP_AXIOS_BASE_API_URL=https://api.romeonline.io/
|
||||
VITE_APP_REPORTS_SERVER_URL=https://reports.romeonline.io
|
||||
VITE_APP_SPLIT_API=et9pjkik6bn67he5evpmpr1agoo7gactphgk
|
||||
VITE_APP_INSTANCE=ROME
|
||||
@@ -1,14 +0,0 @@
|
||||
REACT_APP_GRAPHQL_ENDPOINT=https://db.test.bodyshop.app/v1/graphql
|
||||
REACT_APP_GRAPHQL_ENDPOINT_WS=wss://db.test.bodyshop.app/v1/graphql
|
||||
REACT_APP_GA_CODE=231099835
|
||||
REACT_APP_FIREBASE_CONFIG={ "apiKey":"AIzaSyBw7_GTy7GtQyfkIRPVrWHEGKfcqeyXw0c", "authDomain":"imex-test.firebaseapp.com", "projectId":"imex-test", "storageBucket":"imex-test.appspot.com", "messagingSenderId":"991923618608", "appId":"1:991923618608:web:633437569cdad78299bef5", "measurementId":"G-TW0XLZEH18"}
|
||||
REACT_APP_CLOUDINARY_ENDPOINT_API=https://api.cloudinary.com/v1_1/bodyshop
|
||||
REACT_APP_CLOUDINARY_ENDPOINT=https://res.cloudinary.com/bodyshop
|
||||
REACT_APP_CLOUDINARY_API_KEY=473322739956866
|
||||
REACT_APP_CLOUDINARY_THUMB_TRANSFORMATIONS=c_fill,h_250,w_250
|
||||
REACT_APP_FIREBASE_PUBLIC_VAPID_KEY='BN2GcDPjipR5MTEosO5dT4CfQ3cmrdBIsI4juoOQrRijn_5aRiHlwj1mlq0W145mOusx6xynEKl_tvYJhpCc9lo'
|
||||
REACT_APP_STRIPE_PUBLIC_KEY=pk_test_51GqB4TJl3nQjrZ0wCQWAxAhlNF8jKe0tipIa6ExBaxwJGitwvFsIZUEua4dUzaMIAuXp4qwYHXx7lgjyQSwP0Pe900vzm38C7g
|
||||
REACT_APP_AXIOS_BASE_API_URL=https://api.test.imex.online/
|
||||
REACT_APP_REPORTS_SERVER_URL=https://reports3.test.imex.online
|
||||
REACT_APP_IS_TEST=true
|
||||
REACT_APP_SPLIT_API=ts615lqgnmk84thn72uk18uu5pgce6e0l4rc
|
||||
15
client/.env.test.imex
Normal file
@@ -0,0 +1,15 @@
|
||||
VITE_APP_GRAPHQL_ENDPOINT=https://db.test.bodyshop.app/v1/graphql
|
||||
VITE_APP_GRAPHQL_ENDPOINT_WS=wss://db.test.bodyshop.app/v1/graphql
|
||||
VITE_APP_GA_CODE=231099835
|
||||
VITE_APP_FIREBASE_CONFIG={ "apiKey":"AIzaSyBw7_GTy7GtQyfkIRPVrWHEGKfcqeyXw0c", "authDomain":"imex-test.firebaseapp.com", "projectId":"imex-test", "storageBucket":"imex-test.appspot.com", "messagingSenderId":"991923618608", "appId":"1:991923618608:web:633437569cdad78299bef5", "measurementId":"G-TW0XLZEH18"}
|
||||
VITE_APP_CLOUDINARY_ENDPOINT_API=https://api.cloudinary.com/v1_1/bodyshop
|
||||
VITE_APP_CLOUDINARY_ENDPOINT=https://res.cloudinary.com/bodyshop
|
||||
VITE_APP_CLOUDINARY_API_KEY=473322739956866
|
||||
VITE_APP_CLOUDINARY_THUMB_TRANSFORMATIONS=c_fill,h_250,w_250
|
||||
VITE_APP_FIREBASE_PUBLIC_VAPID_KEY='BN2GcDPjipR5MTEosO5dT4CfQ3cmrdBIsI4juoOQrRijn_5aRiHlwj1mlq0W145mOusx6xynEKl_tvYJhpCc9lo'
|
||||
VITE_APP_STRIPE_PUBLIC_KEY=pk_test_51GqB4TJl3nQjrZ0wCQWAxAhlNF8jKe0tipIa6ExBaxwJGitwvFsIZUEua4dUzaMIAuXp4qwYHXx7lgjyQSwP0Pe900vzm38C7g
|
||||
VITE_APP_AXIOS_BASE_API_URL=https://api.test.imex.online/
|
||||
VITE_APP_REPORTS_SERVER_URL=https://reports3.test.imex.online
|
||||
VITE_APP_IS_TEST=true
|
||||
VITE_APP_SPLIT_API=ts615lqgnmk84thn72uk18uu5pgce6e0l4rc
|
||||
VITE_APP_INSTANCE=IMEX
|
||||
15
client/.env.test.promanager
Normal file
@@ -0,0 +1,15 @@
|
||||
VITE_APP_GRAPHQL_ENDPOINT=https://db.test.romeonline.io/v1/graphql
|
||||
VITE_APP_GRAPHQL_ENDPOINT_WS=wss://db.test.romeonline.io/v1/graphql
|
||||
VITE_APP_GA_CODE=231099835
|
||||
VITE_APP_FIREBASE_CONFIG={ "apiKey": "AIzaSyAuLQR9SV5LsVxjU8wh9hvFLdhcAHU6cxE", "authDomain": "rome-prod-1.firebaseapp.com", "projectId": "rome-prod-1", "storageBucket": "rome-prod-1.appspot.com", "messagingSenderId": "147786367145", "appId": "1:147786367145:web:9d4cba68071c3f29a8a9b8", "measurementId": "G-G8Z9DRHTZS"}
|
||||
VITE_APP_CLOUDINARY_ENDPOINT_API=https://api.cloudinary.com/v1_1/bodyshop
|
||||
VITE_APP_CLOUDINARY_ENDPOINT=https://res.cloudinary.com/bodyshop
|
||||
VITE_APP_CLOUDINARY_API_KEY=473322739956866
|
||||
VITE_APP_CLOUDINARY_THUMB_TRANSFORMATIONS=c_fill,h_250,w_250
|
||||
VITE_APP_FIREBASE_PUBLIC_VAPID_KEY='BN2GcDPjipR5MTEosO5dT4CfQ3cmrdBIsI4juoOQrRijn_5aRiHlwj1mlq0W145mOusx6xynEKl_tvYJhpCc9lo'
|
||||
VITE_APP_STRIPE_PUBLIC_KEY=pk_test_51GqB4TJl3nQjrZ0wCQWAxAhlNF8jKe0tipIa6ExBaxwJGitwvFsIZUEua4dUzaMIAuXp4qwYHXx7lgjyQSwP0Pe900vzm38C7g
|
||||
VITE_APP_AXIOS_BASE_API_URL=https://api.test.romeonline.io/
|
||||
VITE_APP_REPORTS_SERVER_URL=https://reports.test.romeonline.io
|
||||
VITE_APP_IS_TEST=true
|
||||
VITE_APP_SPLIT_API=ts615lqgnmk84thn72uk18uu5pgce6e0l4rc
|
||||
VITE_APP_INSTANCE=PROMANAGER
|
||||
15
client/.env.test.rome
Normal file
@@ -0,0 +1,15 @@
|
||||
VITE_APP_GRAPHQL_ENDPOINT=https://db.test.romeonline.io/v1/graphql
|
||||
VITE_APP_GRAPHQL_ENDPOINT_WS=wss://db.test.romeonline.io/v1/graphql
|
||||
VITE_APP_GA_CODE=231103507
|
||||
VITE_APP_FIREBASE_CONFIG={ "apiKey": "AIzaSyAuLQR9SV5LsVxjU8wh9hvFLdhcAHU6cxE", "authDomain": "rome-prod-1.firebaseapp.com", "projectId": "rome-prod-1", "storageBucket": "rome-prod-1.appspot.com", "messagingSenderId": "147786367145", "appId": "1:147786367145:web:9d4cba68071c3f29a8a9b8", "measurementId": "G-G8Z9DRHTZS"}
|
||||
VITE_APP_CLOUDINARY_ENDPOINT_API=https://api.cloudinary.com/v1_1/bodyshop
|
||||
VITE_APP_CLOUDINARY_ENDPOINT=https://res.cloudinary.com/bodyshop
|
||||
VITE_APP_CLOUDINARY_API_KEY=473322739956866
|
||||
VITE_APP_CLOUDINARY_THUMB_TRANSFORMATIONS=c_fill,h_250,w_250
|
||||
VITE_APP_FIREBASE_PUBLIC_VAPID_KEY='BP1B7ZTYpn-KMt6nOxlld6aS8Skt3Q7ZLEqP0hAvGHxG4UojPYiXZ6kPlzZkUC5jH-EcWXomTLtmadAIxurfcHo'
|
||||
VITE_APP_STRIPE_PUBLIC_KEY=pk_test_51GqB4TJl3nQjrZ0wCQWAxAhlNF8jKe0tipIa6ExBaxwJGitwvFsIZUEua4dUzaMIAuXp4qwYHXx7lgjyQSwP0Pe900vzm38C7g
|
||||
VITE_APP_AXIOS_BASE_API_URL=https://api.test.romeonline.io/
|
||||
VITE_APP_REPORTS_SERVER_URL=https://reports.test.romeonline.io
|
||||
VITE_APP_IS_TEST=true
|
||||
VITE_APP_SPLIT_API=ts615lqgnmk84thn72uk18uu5pgce6e0l4rc
|
||||
VITE_APP_INSTANCE=ROME
|
||||
@@ -13,21 +13,7 @@ const v4Token = convertLegacyToken(mapToken);
|
||||
|
||||
module.exports = {
|
||||
plugins: [
|
||||
// {
|
||||
// plugin: SentryWebpackPlugin,
|
||||
// options: {
|
||||
// // sentry-cli configuration
|
||||
// authToken:
|
||||
// "6b45b028a02342db97a9a2f92c0959058665443d379d4a3a876430009e744260",
|
||||
// org: "snapt-software",
|
||||
// project: "imexonline",
|
||||
// release: process.env.REACT_APP_GIT_SHA,
|
||||
//
|
||||
// // webpack-specific configuration
|
||||
// include: ".",
|
||||
// ignore: ["node_modules", "webpack.config.js"],
|
||||
// },
|
||||
// },
|
||||
|
||||
{
|
||||
plugin: CracoLessPlugin,
|
||||
options: {
|
||||
|
||||
1
client/dev-dist/registerSW.js
Normal file
@@ -0,0 +1 @@
|
||||
if('serviceWorker' in navigator) navigator.serviceWorker.register('/dev-sw.js?dev-sw', { scope: '/', type: 'classic' })
|
||||
92
client/dev-dist/sw.js
Normal file
@@ -0,0 +1,92 @@
|
||||
/**
|
||||
* Copyright 2018 Google Inc. All Rights Reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// If the loader is already loaded, just stop.
|
||||
if (!self.define) {
|
||||
let registry = {};
|
||||
|
||||
// Used for `eval` and `importScripts` where we can't get script URL by other means.
|
||||
// In both cases, it's safe to use a global var because those functions are synchronous.
|
||||
let nextDefineUri;
|
||||
|
||||
const singleRequire = (uri, parentUri) => {
|
||||
uri = new URL(uri + ".js", parentUri).href;
|
||||
return registry[uri] || (
|
||||
|
||||
new Promise(resolve => {
|
||||
if ("document" in self) {
|
||||
const script = document.createElement("script");
|
||||
script.src = uri;
|
||||
script.onload = resolve;
|
||||
document.head.appendChild(script);
|
||||
} else {
|
||||
nextDefineUri = uri;
|
||||
importScripts(uri);
|
||||
resolve();
|
||||
}
|
||||
})
|
||||
|
||||
.then(() => {
|
||||
let promise = registry[uri];
|
||||
if (!promise) {
|
||||
throw new Error(`Module ${uri} didn’t register its module`);
|
||||
}
|
||||
return promise;
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
self.define = (depsNames, factory) => {
|
||||
const uri = nextDefineUri || ("document" in self ? document.currentScript.src : "") || location.href;
|
||||
if (registry[uri]) {
|
||||
// Module is already loading or loaded.
|
||||
return;
|
||||
}
|
||||
let exports = {};
|
||||
const require = depUri => singleRequire(depUri, uri);
|
||||
const specialDeps = {
|
||||
module: { uri },
|
||||
exports,
|
||||
require
|
||||
};
|
||||
registry[uri] = Promise.all(depsNames.map(
|
||||
depName => specialDeps[depName] || require(depName)
|
||||
)).then(deps => {
|
||||
factory(...deps);
|
||||
return exports;
|
||||
});
|
||||
};
|
||||
}
|
||||
define(['./workbox-b5f7729d'], (function (workbox) { 'use strict';
|
||||
|
||||
self.skipWaiting();
|
||||
workbox.clientsClaim();
|
||||
|
||||
/**
|
||||
* The precacheAndRoute() method efficiently caches and responds to
|
||||
* requests for URLs in the manifest.
|
||||
* See https://goo.gl/S9QRab
|
||||
*/
|
||||
workbox.precacheAndRoute([{
|
||||
"url": "registerSW.js",
|
||||
"revision": "3ca0b8505b4bec776b69afdba2768812"
|
||||
}, {
|
||||
"url": "index.html",
|
||||
"revision": "0.sa702m4aq68"
|
||||
}], {});
|
||||
workbox.cleanupOutdatedCaches();
|
||||
workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("index.html"), {
|
||||
allowlist: [/^\/$/]
|
||||
}));
|
||||
|
||||
}));
|
||||
3391
client/dev-dist/workbox-b5f7729d.js
Normal file
174
client/index.html
Normal file
@@ -0,0 +1,174 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<% if (env.VITE_APP_INSTANCE === 'IMEX') { %>
|
||||
<link rel="icon" href="/favicon.png" />
|
||||
<% } %> <% if (env.VITE_APP_INSTANCE === 'ROME') { %>
|
||||
<link rel="icon" href="/ro-favicon.png" />
|
||||
<% } %> <% if (env.VITE_APP_INSTANCE === 'PROMANAGER') { %>
|
||||
<link rel="icon" href="/pm/pm-favicon.ico" />
|
||||
<% } %>
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#1690ff" />
|
||||
<!-- <link rel="apple-touch-icon" href="logo192.png" /> -->
|
||||
<!-- TODO:AIo Update the individual logos for each.-->
|
||||
<link rel="apple-touch-icon" href="public/logo192.png" />
|
||||
<link rel="mask-icon" href="/mask-icon.svg" color="#FFFFFF">
|
||||
<!--
|
||||
manifest.json provides metadata used when your web app is installed on a
|
||||
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
||||
-->
|
||||
<!--
|
||||
Notice the use of %PUBLIC_URL% in the tags above.
|
||||
It will be replaced with the URL of the `public` folder during the build.
|
||||
Only files inside the `public` folder can be referenced from the HTML.
|
||||
|
||||
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
|
||||
work correctly both with client-side routing and a non-root public URL.
|
||||
Learn how to configure a non-root public URL by running `npm run build`.
|
||||
-->
|
||||
<% if (env.VITE_APP_INSTANCE === 'IMEX') { %>
|
||||
<meta name="description" content="ImEX Online" />
|
||||
<title>ImEX Online</title>
|
||||
<script type="text/javascript">
|
||||
window.$crisp = [];
|
||||
window.CRISP_WEBSITE_ID = '36724f62-2eb0-4b29-9cdd-9905fb99913e';
|
||||
(function () {
|
||||
d = document;
|
||||
s = d.createElement('script');
|
||||
s.src = 'https://client.crisp.chat/l.js';
|
||||
s.async = 1;
|
||||
d.getElementsByTagName('head')[0].appendChild(s);
|
||||
})();
|
||||
</script>
|
||||
<% } %> <% if (env.VITE_APP_INSTANCE === 'ROME') { %>
|
||||
<meta name="description" content="Rome Online" />
|
||||
<title>Rome Online</title>
|
||||
|
||||
<!--Use the below code snippet to provide real time updates to the live chat plugin without the need of copying and paste each time to your website when changes are made via PBX-->
|
||||
|
||||
<call-us-selector phonesystem-url=https://rometech.east.3cx.us:5001 party="LiveChat528346"></call-us-selector>
|
||||
|
||||
<!--Incase you don't want real time updates to the live chat plugin when options are changed, use the below code snippet. Please note that each time you change the settings you will need to copy and paste the snippet code to your website-->
|
||||
|
||||
<!--<call-us
|
||||
|
||||
phonesystem-url=https://rometech.east.3cx.us:5001
|
||||
|
||||
style="position:fixed;font-size:16px;line-height:17px;z-index: 99999;right: 20px; bottom: 20px;"
|
||||
|
||||
id="wp-live-chat-by-3CX"
|
||||
|
||||
minimized="true"
|
||||
|
||||
animation-style="noanimation"
|
||||
|
||||
party="LiveChat528346"
|
||||
|
||||
minimized-style="bubbleright"
|
||||
|
||||
allow-call="true"
|
||||
|
||||
allow-video="false"
|
||||
|
||||
allow-soundnotifications="true"
|
||||
|
||||
enable-mute="true"
|
||||
|
||||
enable-onmobile="true"
|
||||
|
||||
offline-enabled="true"
|
||||
|
||||
enable="true"
|
||||
|
||||
ignore-queueownership="false"
|
||||
|
||||
authentication="both"
|
||||
|
||||
show-operator-actual-name="true"
|
||||
|
||||
aknowledge-received="true"
|
||||
|
||||
gdpr-enabled="false"
|
||||
|
||||
message-userinfo-format="name"
|
||||
|
||||
message-dateformat="both"
|
||||
|
||||
lang="browser"
|
||||
|
||||
button-icon-type="default"
|
||||
|
||||
greeting-visibility="none"
|
||||
|
||||
greeting-offline-visibility="none"
|
||||
|
||||
chat-delay="2000"
|
||||
|
||||
enable-direct-call="true"
|
||||
|
||||
enable-ga="false"
|
||||
|
||||
></call-us>-->
|
||||
|
||||
<script defer src=https://downloads-global.3cx.com/downloads/livechatandtalk/v1/callus.js id="tcx-callus-js" charset="utf-8"></script>
|
||||
|
||||
|
||||
|
||||
<% } %> <% if (env.VITE_APP_INSTANCE === 'PROMANAGER') { %>
|
||||
<title>ProManager</title>
|
||||
<meta name="description" content="ProManager" />
|
||||
|
||||
<% } %>
|
||||
<script>
|
||||
!(function () {
|
||||
'use strict';
|
||||
var e = [
|
||||
'debug',
|
||||
'destroy',
|
||||
'do',
|
||||
'help',
|
||||
'identify',
|
||||
'is',
|
||||
'off',
|
||||
'on',
|
||||
'ready',
|
||||
'render',
|
||||
'reset',
|
||||
'safe',
|
||||
'set',
|
||||
];
|
||||
if (window.noticeable) console.warn('Noticeable SDK code snippet loaded more than once');
|
||||
else {
|
||||
var n = (window.noticeable = window.noticeable || []);
|
||||
function t(e) {
|
||||
return function () {
|
||||
var t = Array.prototype.slice.call(arguments);
|
||||
return t.unshift(e), n.push(t), n;
|
||||
};
|
||||
}
|
||||
!(function () {
|
||||
for (var o = 0; o < e.length; o++) {
|
||||
var r = e[o];
|
||||
n[r] = t(r);
|
||||
}
|
||||
})(),
|
||||
(function () {
|
||||
var e = document.createElement('script');
|
||||
(e.async = !0), (e.src = 'https://sdk.noticeable.io/l.js');
|
||||
var n = document.head;
|
||||
n.insertBefore(e, n.firstChild);
|
||||
})();
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root"></div>
|
||||
|
||||
<script type="module" src="src/index.jsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
15855
client/package-lock.json
generated
@@ -1,6 +1,10 @@
|
||||
{
|
||||
"name": "bodyshop",
|
||||
"version": "0.2.1",
|
||||
"engines": {
|
||||
"node": "18.18.2"
|
||||
},
|
||||
"type": "module",
|
||||
"private": true,
|
||||
"proxy": "http://localhost:4000",
|
||||
"dependencies": {
|
||||
@@ -17,17 +21,22 @@
|
||||
"@sentry/tracing": "^7.102.1",
|
||||
"@splitsoftware/splitio-react": "^1.11.0",
|
||||
"@tanem/react-nprogress": "^5.0.51",
|
||||
"@vitejs/plugin-legacy": "^5.3.0",
|
||||
"@vitejs/plugin-react": "^4.2.1",
|
||||
"@vitejs/plugin-react-refresh": "^1.3.6",
|
||||
"@vitejs/plugin-react-swc": "^3.6.0",
|
||||
"antd": "^5.14.2",
|
||||
"apollo-link-logger": "^2.0.1",
|
||||
"apollo-link-sentry": "^3.3.0",
|
||||
"axios": "^1.6.7",
|
||||
"craco-less": "^3.0.1",
|
||||
"consola": "^3.2.3",
|
||||
"dayjs": "^1.11.10",
|
||||
"dayjs-business-days2": "^1.2.2",
|
||||
"dinero.js": "^1.9.1",
|
||||
"dotenv": "^16.4.5",
|
||||
"enquire-js": "^0.2.1",
|
||||
"env-cmd": "^10.1.0",
|
||||
"esbuild": "^0.20.0",
|
||||
"exifr": "^7.1.3",
|
||||
"firebase": "^10.8.0",
|
||||
"graphql": "^16.6.0",
|
||||
@@ -77,6 +86,9 @@
|
||||
"styled-components": "^6.1.8",
|
||||
"subscriptions-transport-ws": "^0.11.0",
|
||||
"terser-webpack-plugin": "^5.3.10",
|
||||
"vite-plugin-compression": "^0.5.1",
|
||||
"vite-plugin-ejs": "^1.7.0",
|
||||
"vite-plugin-svgr": "^4.2.0",
|
||||
"web-vitals": "^3.5.2",
|
||||
"workbox-core": "^7.0.0",
|
||||
"workbox-expiration": "^7.0.0",
|
||||
@@ -88,16 +100,22 @@
|
||||
},
|
||||
"scripts": {
|
||||
"analyze": "source-map-explorer 'build/static/js/*.js'",
|
||||
"start": "craco start",
|
||||
"build": "REACT_APP_GIT_SHA=`git rev-parse --short HEAD` craco build",
|
||||
"build:test": "env-cmd -f .env.test npm run build",
|
||||
"build-deploy:test": "npm run build:test && s3cmd sync build/* s3://imex-online-test && echo '🚀 TESTING Deployed!'",
|
||||
"buildcra": "REACT_APP_GIT_SHA=`git rev-parse --short HEAD` craco build",
|
||||
"start": "vite",
|
||||
"build": "vite build",
|
||||
"start:imex": "dotenvx run --env-file=.env.development.imex -- vite",
|
||||
"start:rome": "dotenvx run --env-file=.env.development.rome -- vite",
|
||||
"start:promanager": "dotenvx run --env-file=.env.development.promanager -- vite",
|
||||
"build:test:imex": "env-cmd -f .env.test.imex npm run build",
|
||||
"build:test:rome": "env-cmd -f .env.test.rome npm run build",
|
||||
"build:test:promanager": "env-cmd -f .env.test.promanager npm run build",
|
||||
"build:production:imex": "env-cmd -f .env.production.imex npm run build",
|
||||
"build:production:rome": "env-cmd -f .env.production.rome npm run build",
|
||||
"build:production:promanager": "env-cmd -f .env.production.promanager npm run build",
|
||||
"test": "cypress open",
|
||||
"eject": "react-scripts eject",
|
||||
"madge": "madge --image ./madge-graph.svg --extensions js,jsx,ts,tsx --circular .",
|
||||
"eulaize": "node src/utils/eulaize.js",
|
||||
"sentry:sourcemaps": "sentry-cli sourcemaps inject --org imex --project imexonline ./build && sentry-cli sourcemaps upload --org imex --project imexonline ./build"
|
||||
"sentry:sourcemaps:imex": "sentry-cli sourcemaps inject --org imex --project imexonline ./build && sentry-cli sourcemaps upload --org imex --project imexonline ./build"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": [
|
||||
@@ -123,12 +141,30 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
|
||||
"@babel/preset-react": "^7.23.3",
|
||||
"@dotenvx/dotenvx": "^0.15.0",
|
||||
"@emotion/babel-plugin": "^11.11.0",
|
||||
"@emotion/react": "^11.11.3",
|
||||
"@sentry/webpack-plugin": "^2.14.2",
|
||||
"@swc/core": "^1.3.107",
|
||||
"@swc/plugin-styled-components": "^1.5.108",
|
||||
"@testing-library/cypress": "^10.0.1",
|
||||
"browserslist": "^4.22.3",
|
||||
"browserslist-to-esbuild": "^2.1.1",
|
||||
"craco-less": "^3.0.1",
|
||||
"cross-env": "^7.0.3",
|
||||
"cypress": "^13.6.6",
|
||||
"eslint-plugin-cypress": "^2.15.1",
|
||||
"memfs": "^4.6.0",
|
||||
"os-browserify": "^0.3.0",
|
||||
"react-error-overlay": "6.0.11",
|
||||
"redux-logger": "^3.0.6",
|
||||
"source-map-explorer": "^2.5.3"
|
||||
"source-map-explorer": "^2.5.3",
|
||||
"vite": "^5.0.11",
|
||||
"vite-plugin-babel": "^1.2.0",
|
||||
"vite-plugin-legacy": "^2.1.0",
|
||||
"vite-plugin-node-polyfills": "^0.19.0",
|
||||
"vite-plugin-pwa": "^0.19.0",
|
||||
"vite-plugin-style-import": "^2.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
// unlayer.registerPropertyEditor({
|
||||
// name: "field_name",
|
||||
// layout: "bottom",
|
||||
// Widget: unlayer.createWidget({
|
||||
// render(value) {
|
||||
// return `
|
||||
// <input class="field" value=${value} />
|
||||
// `;
|
||||
// },
|
||||
// mount(node, value, updateValue) {
|
||||
// var input = node.getElementsByClassName("field")[0];
|
||||
// input.onchange = function (event) {
|
||||
// updateValue(event.target.value);
|
||||
// };
|
||||
// },
|
||||
// }),
|
||||
// });
|
||||
|
||||
// unlayer.registerTool({
|
||||
// type: "whatever",
|
||||
// category: "contents",
|
||||
// label: "Begin Repeat",
|
||||
// icon: "fa-smile",
|
||||
// values: {},
|
||||
// options: {
|
||||
// default: {
|
||||
// title: null,
|
||||
// },
|
||||
// text: {
|
||||
// title: "Field",
|
||||
// position: 1,
|
||||
// options: {
|
||||
// field: {
|
||||
// label: "Field",
|
||||
// defaultValue: "",
|
||||
// widget: "field_name",
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// renderer: {
|
||||
// Viewer: unlayer.createViewer({
|
||||
// render(values) {
|
||||
// console.log(values);
|
||||
// return `
|
||||
// <div style="display: none;">{{#each ${values.field}}}</div>
|
||||
// `;
|
||||
// },
|
||||
// }),
|
||||
// exporters: {
|
||||
// web: function () {},
|
||||
// email: function () {},
|
||||
// },
|
||||
// },
|
||||
// });
|
||||
|
||||
// unlayer.registerTool({
|
||||
// type: "whatever",
|
||||
// category: "contents",
|
||||
// label: "End Repeat",
|
||||
// icon: "fa-smile",
|
||||
// values: {},
|
||||
// options: {
|
||||
// default: {
|
||||
// title: null,
|
||||
// },
|
||||
// text: {
|
||||
// title: "Field",
|
||||
// position: 1,
|
||||
// options: {
|
||||
// field: {
|
||||
// label: "Field",
|
||||
// defaultValue: "",
|
||||
// widget: "field_name",
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// renderer: {
|
||||
// Viewer: unlayer.createViewer({
|
||||
// render(values) {
|
||||
// return `
|
||||
// <div style="display: none;">{{ /each }}</div>
|
||||
// `;
|
||||
// },
|
||||
// }),
|
||||
// exporters: {
|
||||
// web: function () {},
|
||||
// email: function () {},
|
||||
// },
|
||||
// },
|
||||
// });
|
||||
|
||||
unlayer.registerColumns([2, 2, 2, 2, 2, 2]);
|
||||
unlayer.registerColumns([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]);
|
||||
@@ -1,56 +0,0 @@
|
||||
// Scripts for firebase and firebase messaging
|
||||
importScripts("https://www.gstatic.com/firebasejs/8.2.0/firebase-app.js");
|
||||
importScripts("https://www.gstatic.com/firebasejs/8.2.0/firebase-messaging.js");
|
||||
|
||||
// Initialize the Firebase app in the service worker by passing the generated config
|
||||
let firebaseConfig;
|
||||
switch (this.location.hostname) {
|
||||
case "localhost":
|
||||
firebaseConfig = {
|
||||
apiKey: "AIzaSyDPLT8GiDHDR1R4nI66Qi0BY1aYviDPioc",
|
||||
authDomain: "imex-dev.firebaseapp.com",
|
||||
databaseURL: "https://imex-dev.firebaseio.com",
|
||||
projectId: "imex-dev",
|
||||
storageBucket: "imex-dev.appspot.com",
|
||||
messagingSenderId: "759548147434",
|
||||
appId: "1:759548147434:web:e8239868a48ceb36700993",
|
||||
measurementId: "G-K5XRBVVB4S",
|
||||
};
|
||||
break;
|
||||
case "test.imex.online":
|
||||
firebaseConfig = {
|
||||
apiKey: "AIzaSyBw7_GTy7GtQyfkIRPVrWHEGKfcqeyXw0c",
|
||||
authDomain: "imex-test.firebaseapp.com",
|
||||
projectId: "imex-test",
|
||||
storageBucket: "imex-test.appspot.com",
|
||||
messagingSenderId: "991923618608",
|
||||
appId: "1:991923618608:web:633437569cdad78299bef5",
|
||||
// measurementId: "${config.measurementId}",
|
||||
};
|
||||
break;
|
||||
case "imex.online":
|
||||
default:
|
||||
firebaseConfig = {
|
||||
apiKey: "AIzaSyDSezy-jGJreo7ulgpLdlpOwAOrgcaEkhU",
|
||||
authDomain: "imex-prod.firebaseapp.com",
|
||||
databaseURL: "https://imex-prod.firebaseio.com",
|
||||
projectId: "imex-prod",
|
||||
storageBucket: "imex-prod.appspot.com",
|
||||
messagingSenderId: "253497221485",
|
||||
appId: "1:253497221485:web:3c81c483b94db84b227a64",
|
||||
measurementId: "G-NTWBKG2L0M",
|
||||
};
|
||||
}
|
||||
|
||||
firebase.initializeApp(firebaseConfig);
|
||||
|
||||
// Retrieve firebase messaging
|
||||
const messaging = firebase.messaging();
|
||||
|
||||
messaging.onBackgroundMessage(function (payload) {
|
||||
// Customize notification here
|
||||
const channel = new BroadcastChannel("imex-sw-messages");
|
||||
channel.postMessage(payload);
|
||||
|
||||
//self.registration.showNotification(notificationTitle, notificationOptions);
|
||||
});
|
||||
@@ -1,88 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<link href="%PUBLIC_URL%/favicon.png" rel="icon"/>
|
||||
<meta content="width=device-width, initial-scale=1" name="viewport"/>
|
||||
<meta content="#002366" name="theme-color"/>
|
||||
<meta content="ImEX Online" name="description"/>
|
||||
<!-- <link rel="apple-touch-icon" href="logo192.png" /> -->
|
||||
<link href="logo192.png" rel="apple-touch-icon"/>
|
||||
<script type="text/javascript">
|
||||
window.$crisp = [];
|
||||
window.CRISP_WEBSITE_ID = "36724f62-2eb0-4b29-9cdd-9905fb99913e";
|
||||
(function () {
|
||||
d = document;
|
||||
s = d.createElement("script");
|
||||
s.src = "https://client.crisp.chat/l.js";
|
||||
s.async = 1;
|
||||
d.getElementsByTagName("head")[0].appendChild(s);
|
||||
})();
|
||||
</script>
|
||||
<script>
|
||||
!(function () {
|
||||
"use strict";
|
||||
var e = [
|
||||
"debug",
|
||||
"destroy",
|
||||
"do",
|
||||
"help",
|
||||
"identify",
|
||||
"is",
|
||||
"off",
|
||||
"on",
|
||||
"ready",
|
||||
"render",
|
||||
"reset",
|
||||
"safe",
|
||||
"set",
|
||||
];
|
||||
if (window.noticeable)
|
||||
console.warn("Noticeable SDK code snippet loaded more than once");
|
||||
else {
|
||||
var n = (window.noticeable = window.noticeable || []);
|
||||
|
||||
function t(e) {
|
||||
return function () {
|
||||
var t = Array.prototype.slice.call(arguments);
|
||||
return t.unshift(e), n.push(t), n;
|
||||
};
|
||||
}
|
||||
|
||||
!(function () {
|
||||
for (var o = 0; o < e.length; o++) {
|
||||
var r = e[o];
|
||||
n[r] = t(r);
|
||||
}
|
||||
})(),
|
||||
(function () {
|
||||
var e = document.createElement("script");
|
||||
(e.async = !0), (e.src = "https://sdk.noticeable.io/l.js");
|
||||
var n = document.head;
|
||||
n.insertBefore(e, n.firstChild);
|
||||
})();
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
|
||||
<!--
|
||||
manifest.json provides metadata used when your web app is installed on a
|
||||
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
||||
-->
|
||||
<link href="%PUBLIC_URL%/manifest.json" rel="manifest"/>
|
||||
<!--
|
||||
Notice the use of %PUBLIC_URL% in the tags above.
|
||||
It will be replaced with the URL of the `public` folder during the build.
|
||||
Only files inside the `public` folder can be referenced from the HTML.
|
||||
|
||||
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
|
||||
work correctly both with client-side routing and a non-root public URL.
|
||||
Learn how to configure a non-root public URL by running `npm run build`.
|
||||
-->
|
||||
<title>ImEX Online</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,27 +0,0 @@
|
||||
{
|
||||
"short_name": "ImEX Online",
|
||||
"name": "ImEX Online",
|
||||
"description": "The ultimate bodyshop management system.",
|
||||
"icons": [
|
||||
{
|
||||
"src": "favicon.ico",
|
||||
"sizes": "64x64 32x32 24x24 16x16",
|
||||
"type": "image/x-icon"
|
||||
},
|
||||
{
|
||||
"src": "logo192.png",
|
||||
"type": "image/png",
|
||||
"sizes": "192x192"
|
||||
},
|
||||
{
|
||||
"src": "logo1024.png",
|
||||
"type": "image/png",
|
||||
"sizes": "512x512"
|
||||
}
|
||||
],
|
||||
"start_url": ".",
|
||||
"display": "standalone",
|
||||
"theme_color": "#fff",
|
||||
"background_color": "#fff",
|
||||
"gcm_sender_id": "103953800507"
|
||||
}
|
||||
BIN
client/public/pm/pm-apple-touch-icon.png
Normal file
|
After Width: | Height: | Size: 5.4 KiB |
BIN
client/public/pm/pm-favicon.ico
Normal file
|
After Width: | Height: | Size: 5.1 KiB |
BIN
client/public/pm/pm-icon-192-maskable.png
Normal file
|
After Width: | Height: | Size: 6.0 KiB |
BIN
client/public/pm/pm-icon-192.png
Normal file
|
After Width: | Height: | Size: 9.2 KiB |
BIN
client/public/pm/pm-icon-512-maskable.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
client/public/pm/pm-icon-512.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
client/public/ro-favicon.png
Normal file
|
After Width: | Height: | Size: 376 B |
@@ -17,7 +17,7 @@ dayjs.locale("en");
|
||||
|
||||
const config = {
|
||||
core: {
|
||||
authorizationKey: process.env.REACT_APP_SPLIT_API,
|
||||
authorizationKey: import.meta.env.VITE_APP_SPLIT_API,
|
||||
key: "anon",
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import {useSplitClient} from "@splitsoftware/splitio-react";
|
||||
import {Button, Result} from "antd";
|
||||
import { useSplitClient } from "@splitsoftware/splitio-react";
|
||||
import { Button, Result } from "antd";
|
||||
import LogRocket from "logrocket";
|
||||
import React, {lazy, Suspense, useEffect, useState} from "react";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import {connect} from "react-redux";
|
||||
import {Route, Routes} from "react-router-dom";
|
||||
import {createStructuredSelector} from "reselect";
|
||||
import React, { lazy, Suspense, useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import { Route, Routes } from "react-router-dom";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import DocumentEditorContainer from "../components/document-editor/document-editor.container";
|
||||
import ErrorBoundary from "../components/error-boundary/error-boundary.component";
|
||||
|
||||
@@ -14,15 +14,19 @@ import LoadingSpinner from "../components/loading-spinner/loading-spinner.compon
|
||||
import DisclaimerPage from "../pages/disclaimer/disclaimer.page";
|
||||
import LandingPage from "../pages/landing/landing.page";
|
||||
import TechPageContainer from "../pages/tech/tech.page.container";
|
||||
import {setOnline} from "../redux/application/application.actions";
|
||||
import {selectOnline} from "../redux/application/application.selectors";
|
||||
import {checkUserSession} from "../redux/user/user.actions";
|
||||
import {selectBodyshop, selectCurrentEula, selectCurrentUser,} from "../redux/user/user.selectors";
|
||||
import { setOnline } from "../redux/application/application.actions";
|
||||
import { selectOnline } from "../redux/application/application.selectors";
|
||||
import { checkUserSession } from "../redux/user/user.actions";
|
||||
import {
|
||||
selectBodyshop,
|
||||
selectCurrentEula,
|
||||
selectCurrentUser,
|
||||
} from "../redux/user/user.selectors";
|
||||
import PrivateRoute from "../components/PrivateRoute";
|
||||
import "./App.styles.scss";
|
||||
import handleBeta from "../utils/betaHandler";
|
||||
import Eula from "../components/eula/eula.component";
|
||||
|
||||
import InstanceRenderMgr from "../utils/instanceRenderMgr";
|
||||
const ResetPassword = lazy(() =>
|
||||
import("../pages/reset-password/reset-password.component")
|
||||
);
|
||||
@@ -37,18 +41,24 @@ const mapStateToProps = createStructuredSelector({
|
||||
currentUser: selectCurrentUser,
|
||||
online: selectOnline,
|
||||
bodyshop: selectBodyshop,
|
||||
currentEula: selectCurrentEula
|
||||
currentEula: selectCurrentEula,
|
||||
});
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
checkUserSession: () => dispatch(checkUserSession()),
|
||||
setOnline: (isOnline) => dispatch(setOnline(isOnline)),
|
||||
});
|
||||
|
||||
export function App({bodyshop, checkUserSession, currentUser, online, setOnline, currentEula}) {
|
||||
export function App({
|
||||
bodyshop,
|
||||
checkUserSession,
|
||||
currentUser,
|
||||
online,
|
||||
setOnline,
|
||||
currentEula,
|
||||
}) {
|
||||
const client = useSplitClient().client;
|
||||
const [listenersAdded, setListenersAdded] = useState(false)
|
||||
const {t} = useTranslation();
|
||||
|
||||
const [listenersAdded, setListenersAdded] = useState(false);
|
||||
const { t } = useTranslation();
|
||||
|
||||
useEffect(() => {
|
||||
if (!navigator.onLine) {
|
||||
@@ -65,14 +75,14 @@ export function App({bodyshop, checkUserSession, currentUser, online, setOnline,
|
||||
useEffect(() => {
|
||||
const offlineListener = (e) => {
|
||||
setOnline(false);
|
||||
}
|
||||
};
|
||||
|
||||
const onlineListener = (e) => {
|
||||
setOnline(true);
|
||||
}
|
||||
};
|
||||
|
||||
if (!listenersAdded) {
|
||||
console.log('Added events for offline and online');
|
||||
console.log("Added events for offline and online");
|
||||
window.addEventListener("offline", offlineListener);
|
||||
window.addEventListener("online", onlineListener);
|
||||
setListenersAdded(true);
|
||||
@@ -81,7 +91,7 @@ export function App({bodyshop, checkUserSession, currentUser, online, setOnline,
|
||||
return () => {
|
||||
window.removeEventListener("offline", offlineListener);
|
||||
window.removeEventListener("online", onlineListener);
|
||||
}
|
||||
};
|
||||
}, [setOnline, listenersAdded]);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -90,16 +100,26 @@ export function App({bodyshop, checkUserSession, currentUser, online, setOnline,
|
||||
|
||||
if (
|
||||
client.getTreatment("LogRocket_Tracking") === "on" ||
|
||||
window.location.hostname === 'beta.imex.online'
|
||||
window.location.hostname ===
|
||||
InstanceRenderMgr({
|
||||
imex: "beta.imex.online",
|
||||
rome: "beta.romeonline.io",
|
||||
})
|
||||
) {
|
||||
console.log("LR Start");
|
||||
LogRocket.init("gvfvfw/bodyshopapp");
|
||||
LogRocket.init(
|
||||
InstanceRenderMgr({
|
||||
imex: "gvfvfw/bodyshopapp",
|
||||
rome: "rome-online/rome-online",
|
||||
promanager: "", //TODO:AIO Add in log rocket for promanager instances.
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
}, [bodyshop, client, currentUser.authorized]);
|
||||
|
||||
if (currentUser.authorized === null) {
|
||||
return <LoadingSpinner message={t("general.labels.loggingin")}/>;
|
||||
return <LoadingSpinner message={t("general.labels.loggingin")} />;
|
||||
}
|
||||
|
||||
handleBeta();
|
||||
@@ -124,29 +144,102 @@ export function App({bodyshop, checkUserSession, currentUser, online, setOnline,
|
||||
);
|
||||
|
||||
if (currentEula && !currentUser.eulaIsAccepted) {
|
||||
return <Eula/>
|
||||
return <Eula />;
|
||||
}
|
||||
|
||||
// Any route that is not assigned and matched will default to the Landing Page component
|
||||
return (
|
||||
<Suspense fallback={<LoadingSpinner message="ImEX Online"/>}>
|
||||
<Suspense
|
||||
fallback={
|
||||
<LoadingSpinner
|
||||
message={InstanceRenderMgr({
|
||||
imex: t("titles.imexonline"),
|
||||
rome: t("titles.romeonline"),
|
||||
promanager: t("titles.promanager")
|
||||
})}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Routes>
|
||||
<Route path="*" element={<ErrorBoundary><LandingPage/></ErrorBoundary>}/>
|
||||
<Route path="/signin" element={<ErrorBoundary><SignInPage/></ErrorBoundary>}/>
|
||||
<Route path="/resetpassword" element={<ErrorBoundary><ResetPassword/></ErrorBoundary>}/>
|
||||
<Route path="/csi/:surveyId" element={<ErrorBoundary><CsiPage/></ErrorBoundary>}/>
|
||||
<Route path="/disclaimer" element={<ErrorBoundary><DisclaimerPage/></ErrorBoundary>}/>
|
||||
<Route path="/mp/:paymentIs" element={<ErrorBoundary><MobilePaymentContainer/></ErrorBoundary>}/>
|
||||
<Route path="/manage/*"
|
||||
element={<ErrorBoundary><PrivateRoute isAuthorized={currentUser.authorized}/></ErrorBoundary>}>
|
||||
<Route path="*" element={<ManagePage/>}/>
|
||||
<Route
|
||||
path="*"
|
||||
element={
|
||||
<ErrorBoundary>
|
||||
<LandingPage />
|
||||
</ErrorBoundary>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/signin"
|
||||
element={
|
||||
<ErrorBoundary>
|
||||
<SignInPage />
|
||||
</ErrorBoundary>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/resetpassword"
|
||||
element={
|
||||
<ErrorBoundary>
|
||||
<ResetPassword />
|
||||
</ErrorBoundary>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/csi/:surveyId"
|
||||
element={
|
||||
<ErrorBoundary>
|
||||
<CsiPage />
|
||||
</ErrorBoundary>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/disclaimer"
|
||||
element={
|
||||
<ErrorBoundary>
|
||||
<DisclaimerPage />
|
||||
</ErrorBoundary>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/mp/:paymentIs"
|
||||
element={
|
||||
<ErrorBoundary>
|
||||
<MobilePaymentContainer />
|
||||
</ErrorBoundary>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/manage/*"
|
||||
element={
|
||||
<ErrorBoundary>
|
||||
<PrivateRoute
|
||||
isAuthorized={currentUser.authorized}
|
||||
/>
|
||||
</ErrorBoundary>
|
||||
}
|
||||
>
|
||||
<Route path="*" element={<ManagePage />} />
|
||||
</Route>
|
||||
<Route path="/tech/*"
|
||||
element={<ErrorBoundary><PrivateRoute isAuthorized={currentUser.authorized}/></ErrorBoundary>}>
|
||||
<Route path="*" element={<TechPageContainer/>}/>
|
||||
<Route
|
||||
path="/tech/*"
|
||||
element={
|
||||
<ErrorBoundary>
|
||||
<PrivateRoute
|
||||
isAuthorized={currentUser.authorized}
|
||||
/>
|
||||
</ErrorBoundary>
|
||||
}
|
||||
>
|
||||
<Route path="*" element={<TechPageContainer />} />
|
||||
</Route>
|
||||
<Route path="/edit/*" element={<PrivateRoute isAuthorized={currentUser.authorized}/>}>
|
||||
<Route path="*" element={<DocumentEditorContainer/>}/>
|
||||
<Route
|
||||
path="/edit/*"
|
||||
element={
|
||||
<PrivateRoute isAuthorized={currentUser.authorized} />
|
||||
}
|
||||
>
|
||||
<Route path="*" element={<DocumentEditorContainer />} />
|
||||
</Route>
|
||||
</Routes>
|
||||
</Suspense>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import {defaultsDeep} from "lodash";
|
||||
import {theme} from "antd";
|
||||
import InstanceRenderMgr from '../utils/instanceRenderMgr'
|
||||
|
||||
const {defaultAlgorithm, darkAlgorithm} = theme;
|
||||
|
||||
@@ -10,21 +11,30 @@ let isDarkMode = false;
|
||||
* @type {{components: {Menu: {itemDividerBorderColor: string}}}}
|
||||
*/
|
||||
const defaultTheme = {
|
||||
components: {
|
||||
Table: {
|
||||
rowHoverBg: '#e7f3ff',
|
||||
rowSelectedBg: '#e6f7ff',
|
||||
headerSortHoverBg: 'transparent',
|
||||
},
|
||||
Menu: {
|
||||
darkItemHoverBg: '#1677ff',
|
||||
itemHoverBg: '#1677ff',
|
||||
horizontalItemHoverBg: '#1677ff',
|
||||
}
|
||||
components: {
|
||||
Table: {
|
||||
rowHoverBg: '#e7f3ff',
|
||||
rowSelectedBg: '#e6f7ff',
|
||||
headerSortHoverBg: 'transparent',
|
||||
},
|
||||
token: {
|
||||
colorPrimary: '#1677ff'
|
||||
}
|
||||
Menu: {
|
||||
darkItemHoverBg: '#1890ff',
|
||||
itemHoverBg: '#1890ff',
|
||||
horizontalItemHoverBg: '#1890ff',
|
||||
},
|
||||
},
|
||||
token: {
|
||||
colorPrimary: InstanceRenderMgr({
|
||||
imex: '#1890ff',
|
||||
rome: '#326ade',
|
||||
promanager:"#1d69a6"
|
||||
}),
|
||||
colorInfo: InstanceRenderMgr({
|
||||
imex: '#1890ff',
|
||||
rome: '#326ade',
|
||||
promanager:"#1d69a6"
|
||||
}),
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -50,11 +60,11 @@ const devTheme = {
|
||||
*/
|
||||
const prodTheme = {};
|
||||
|
||||
const currentTheme = process.env.NODE_ENV === "development" ? devTheme
|
||||
const currentTheme = import.meta.env.DEV ? devTheme
|
||||
: prodTheme;
|
||||
|
||||
const finaltheme = {
|
||||
algorithm: isDarkMode ? darkAlgorithm : defaultAlgorithm,
|
||||
...defaultsDeep(currentTheme, defaultTheme)
|
||||
}
|
||||
export default finaltheme;
|
||||
export default finaltheme;
|
||||
|
||||
BIN
client/src/assets/RomeOnline.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
client/src/assets/RomeOnlineBlue.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
client/src/assets/promanager/android/play_store_512.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@mipmap/ic_launcher_background"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
<monochrome android:drawable="@mipmap/ic_launcher_monochrome"/>
|
||||
</adaptive-icon>
|
||||
|
After Width: | Height: | Size: 5.2 KiB |
|
After Width: | Height: | Size: 857 B |
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 463 B |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 7.6 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 4.0 KiB |
|
After Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 8.2 KiB |
|
After Width: | Height: | Size: 7.9 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 4.1 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 9.8 KiB |
BIN
client/src/assets/promanager/ios/AppIcon-20@2x.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
client/src/assets/promanager/ios/AppIcon-20@2x~ipad.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
client/src/assets/promanager/ios/AppIcon-20@3x.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
client/src/assets/promanager/ios/AppIcon-20~ipad.png
Normal file
|
After Width: | Height: | Size: 527 B |
BIN
client/src/assets/promanager/ios/AppIcon-29.png
Normal file
|
After Width: | Height: | Size: 948 B |
BIN
client/src/assets/promanager/ios/AppIcon-29@2x.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
client/src/assets/promanager/ios/AppIcon-29@2x~ipad.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
client/src/assets/promanager/ios/AppIcon-29@3x.png
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
client/src/assets/promanager/ios/AppIcon-29~ipad.png
Normal file
|
After Width: | Height: | Size: 948 B |
BIN
client/src/assets/promanager/ios/AppIcon-40@2x.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
client/src/assets/promanager/ios/AppIcon-40@2x~ipad.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
client/src/assets/promanager/ios/AppIcon-40@3x.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
client/src/assets/promanager/ios/AppIcon-40~ipad.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
client/src/assets/promanager/ios/AppIcon-60@2x~car.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
client/src/assets/promanager/ios/AppIcon-60@3x~car.png
Normal file
|
After Width: | Height: | Size: 5.4 KiB |
BIN
client/src/assets/promanager/ios/AppIcon-83.5@2x~ipad.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
client/src/assets/promanager/ios/AppIcon@2x.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
client/src/assets/promanager/ios/AppIcon@2x~ipad.png
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
BIN
client/src/assets/promanager/ios/AppIcon@3x.png
Normal file
|
After Width: | Height: | Size: 5.4 KiB |
BIN
client/src/assets/promanager/ios/AppIcon~ios-marketing.png
Normal file
|
After Width: | Height: | Size: 46 KiB |
BIN
client/src/assets/promanager/ios/AppIcon~ipad.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
134
client/src/assets/promanager/ios/Contents.json
Normal file
@@ -0,0 +1,134 @@
|
||||
{
|
||||
"images": [
|
||||
{
|
||||
"filename": "AppIcon@2x.png",
|
||||
"idiom": "iphone",
|
||||
"scale": "2x",
|
||||
"size": "60x60"
|
||||
},
|
||||
{
|
||||
"filename": "AppIcon@3x.png",
|
||||
"idiom": "iphone",
|
||||
"scale": "3x",
|
||||
"size": "60x60"
|
||||
},
|
||||
{
|
||||
"filename": "AppIcon~ipad.png",
|
||||
"idiom": "ipad",
|
||||
"scale": "1x",
|
||||
"size": "76x76"
|
||||
},
|
||||
{
|
||||
"filename": "AppIcon@2x~ipad.png",
|
||||
"idiom": "ipad",
|
||||
"scale": "2x",
|
||||
"size": "76x76"
|
||||
},
|
||||
{
|
||||
"filename": "AppIcon-83.5@2x~ipad.png",
|
||||
"idiom": "ipad",
|
||||
"scale": "2x",
|
||||
"size": "83.5x83.5"
|
||||
},
|
||||
{
|
||||
"filename": "AppIcon-40@2x.png",
|
||||
"idiom": "iphone",
|
||||
"scale": "2x",
|
||||
"size": "40x40"
|
||||
},
|
||||
{
|
||||
"filename": "AppIcon-40@3x.png",
|
||||
"idiom": "iphone",
|
||||
"scale": "3x",
|
||||
"size": "40x40"
|
||||
},
|
||||
{
|
||||
"filename": "AppIcon-40~ipad.png",
|
||||
"idiom": "ipad",
|
||||
"scale": "1x",
|
||||
"size": "40x40"
|
||||
},
|
||||
{
|
||||
"filename": "AppIcon-40@2x~ipad.png",
|
||||
"idiom": "ipad",
|
||||
"scale": "2x",
|
||||
"size": "40x40"
|
||||
},
|
||||
{
|
||||
"filename": "AppIcon-20@2x.png",
|
||||
"idiom": "iphone",
|
||||
"scale": "2x",
|
||||
"size": "20x20"
|
||||
},
|
||||
{
|
||||
"filename": "AppIcon-20@3x.png",
|
||||
"idiom": "iphone",
|
||||
"scale": "3x",
|
||||
"size": "20x20"
|
||||
},
|
||||
{
|
||||
"filename": "AppIcon-20~ipad.png",
|
||||
"idiom": "ipad",
|
||||
"scale": "1x",
|
||||
"size": "20x20"
|
||||
},
|
||||
{
|
||||
"filename": "AppIcon-20@2x~ipad.png",
|
||||
"idiom": "ipad",
|
||||
"scale": "2x",
|
||||
"size": "20x20"
|
||||
},
|
||||
{
|
||||
"filename": "AppIcon-29.png",
|
||||
"idiom": "iphone",
|
||||
"scale": "1x",
|
||||
"size": "29x29"
|
||||
},
|
||||
{
|
||||
"filename": "AppIcon-29@2x.png",
|
||||
"idiom": "iphone",
|
||||
"scale": "2x",
|
||||
"size": "29x29"
|
||||
},
|
||||
{
|
||||
"filename": "AppIcon-29@3x.png",
|
||||
"idiom": "iphone",
|
||||
"scale": "3x",
|
||||
"size": "29x29"
|
||||
},
|
||||
{
|
||||
"filename": "AppIcon-29~ipad.png",
|
||||
"idiom": "ipad",
|
||||
"scale": "1x",
|
||||
"size": "29x29"
|
||||
},
|
||||
{
|
||||
"filename": "AppIcon-29@2x~ipad.png",
|
||||
"idiom": "ipad",
|
||||
"scale": "2x",
|
||||
"size": "29x29"
|
||||
},
|
||||
{
|
||||
"filename": "AppIcon-60@2x~car.png",
|
||||
"idiom": "car",
|
||||
"scale": "2x",
|
||||
"size": "60x60"
|
||||
},
|
||||
{
|
||||
"filename": "AppIcon-60@3x~car.png",
|
||||
"idiom": "car",
|
||||
"scale": "3x",
|
||||
"size": "60x60"
|
||||
},
|
||||
{
|
||||
"filename": "AppIcon~ios-marketing.png",
|
||||
"idiom": "ios-marketing",
|
||||
"scale": "1x",
|
||||
"size": "1024x1024"
|
||||
}
|
||||
],
|
||||
"info": {
|
||||
"author": "iconkitchen",
|
||||
"version": 1
|
||||
}
|
||||
}
|
||||
18
client/src/assets/promanager/web/README.txt
Normal file
@@ -0,0 +1,18 @@
|
||||
Add this to your HTML <head>:
|
||||
|
||||
<link rel="icon" href="/favicon.ico" sizes="any">
|
||||
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
|
||||
|
||||
Add this to your app's manifest.json:
|
||||
|
||||
...
|
||||
{
|
||||
"icons": [
|
||||
{ "src": "/favicon.ico", "type": "image/x-icon", "sizes": "16x16 32x32" },
|
||||
{ "src": "/icon-192.png", "type": "image/png", "sizes": "192x192" },
|
||||
{ "src": "/icon-512.png", "type": "image/png", "sizes": "512x512" },
|
||||
{ "src": "/icon-192-maskable.png", "type": "image/png", "sizes": "192x192", "purpose": "maskable" },
|
||||
{ "src": "/icon-512-maskable.png", "type": "image/png", "sizes": "512x512", "purpose": "maskable" }
|
||||
]
|
||||
}
|
||||
...
|
||||
BIN
client/src/assets/promanager/web/apple-touch-icon.png
Normal file
|
After Width: | Height: | Size: 5.4 KiB |
BIN
client/src/assets/promanager/web/favicon.ico
Normal file
|
After Width: | Height: | Size: 5.1 KiB |
BIN
client/src/assets/promanager/web/icon-192-maskable.png
Normal file
|
After Width: | Height: | Size: 6.0 KiB |
BIN
client/src/assets/promanager/web/icon-192.png
Normal file
|
After Width: | Height: | Size: 9.2 KiB |
BIN
client/src/assets/promanager/web/icon-512-maskable.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
client/src/assets/promanager/web/icon-512.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
client/src/assets/romelogo.png
Normal file
|
After Width: | Height: | Size: 72 KiB |
@@ -14,4 +14,4 @@ function PrivateRoute({component: Component, isAuthorized, ...rest}) {
|
||||
return <Outlet/>;
|
||||
}
|
||||
|
||||
export default PrivateRoute;
|
||||
export default PrivateRoute;
|
||||
@@ -1,4 +1,5 @@
|
||||
import {useApolloClient, useMutation} from "@apollo/client";
|
||||
import {useSplitTreatments} from "@splitsoftware/splitio-react";
|
||||
import {Button, Checkbox, Form, Modal, notification, Space} from "antd";
|
||||
import _ from "lodash";
|
||||
import React, {useEffect, useMemo, useState} from "react";
|
||||
@@ -57,9 +58,21 @@ function BillEnterModalContainer({
|
||||
"enter_bill_generate_label",
|
||||
false
|
||||
);
|
||||
|
||||
const {treatments: {Enhanced_Payroll}} = useSplitTreatments({
|
||||
attributes: {},
|
||||
names: ["Enhanced_Payroll"],
|
||||
splitKey: bodyshop.imexshopid,
|
||||
});
|
||||
|
||||
const formValues = useMemo(() => {
|
||||
return {
|
||||
...billEnterModal.context.bill,
|
||||
//Added as a part of IO-2436 for capturing parts price changes.
|
||||
billlines: billEnterModal.context?.bill?.billlines?.map((line) => ({
|
||||
...line,
|
||||
original_actual_price: line.actual_price,
|
||||
})),
|
||||
jobid:
|
||||
(billEnterModal.context.job && billEnterModal.context.job.id) || null,
|
||||
federal_tax_rate:
|
||||
@@ -93,6 +106,7 @@ function BillEnterModalContainer({
|
||||
} = values;
|
||||
|
||||
let adjustmentsToInsert = {};
|
||||
let payrollAdjustmentsToInsert = [];
|
||||
|
||||
const r1 = await insertBill({
|
||||
variables: {
|
||||
@@ -108,14 +122,33 @@ function BillEnterModalContainer({
|
||||
lbr_adjustment,
|
||||
location: lineLocation,
|
||||
part_type,
|
||||
create_ppc,
|
||||
original_actual_price,
|
||||
...restI
|
||||
} = i;
|
||||
|
||||
if (deductedfromlbr) {
|
||||
adjustmentsToInsert[lbr_adjustment.mod_lbr_ty] =
|
||||
(adjustmentsToInsert[lbr_adjustment.mod_lbr_ty] || 0) -
|
||||
restI.actual_price / lbr_adjustment.rate;
|
||||
if (Enhanced_Payroll.treatment === "on") {
|
||||
if (
|
||||
deductedfromlbr &&
|
||||
true //payroll is on
|
||||
) {
|
||||
payrollAdjustmentsToInsert.push({
|
||||
id: i.joblineid,
|
||||
convertedtolbr: true,
|
||||
convertedtolbr_data: {
|
||||
mod_lb_hrs: lbr_adjustment.mod_lb_hrs * -1,
|
||||
mod_lbr_ty: lbr_adjustment.mod_lbr_ty,
|
||||
},
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (deductedfromlbr) {
|
||||
adjustmentsToInsert[lbr_adjustment.mod_lbr_ty] =
|
||||
(adjustmentsToInsert[lbr_adjustment.mod_lbr_ty] || 0) -
|
||||
restI.actual_price / lbr_adjustment.rate;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
...restI,
|
||||
deductedfromlbr: deductedfromlbr,
|
||||
@@ -141,6 +174,20 @@ function BillEnterModalContainer({
|
||||
refetchQueries: ["QUERY_PARTS_BILLS_BY_JOBID", "GET_JOB_BY_PK"],
|
||||
});
|
||||
|
||||
await Promise.all(
|
||||
payrollAdjustmentsToInsert.map((li) => {
|
||||
return updateJobLines({
|
||||
variables: {
|
||||
lineId: li.id,
|
||||
line: {
|
||||
convertedtolbr: li.convertedtolbr,
|
||||
convertedtolbr_data: li.convertedtolbr_data,
|
||||
},
|
||||
},
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
const adjKeys = Object.keys(adjustmentsToInsert);
|
||||
if (adjKeys.length > 0) {
|
||||
//Query the adjustments, merge, and update them.
|
||||
@@ -249,6 +296,14 @@ function BillEnterModalContainer({
|
||||
location: li.location || location,
|
||||
status:
|
||||
bodyshop.md_order_statuses.default_received || "Received*",
|
||||
//Added parts price changes.
|
||||
...(li.create_ppc &&
|
||||
li.original_actual_price !== li.actual_price
|
||||
? {
|
||||
act_price_before_ppc: li.original_actual_price,
|
||||
act_price: li.actual_price,
|
||||
}
|
||||
: {}),
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -317,12 +372,12 @@ function BillEnterModalContainer({
|
||||
});
|
||||
|
||||
if (enterAgain) {
|
||||
form.resetFields();
|
||||
form.resetFields();
|
||||
// form.resetFields();
|
||||
form.setFieldsValue({
|
||||
...formValues,
|
||||
billlines: [],
|
||||
});
|
||||
form.resetFields();
|
||||
} else {
|
||||
toggleModalVisible();
|
||||
}
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
import React from "react";
|
||||
import {
|
||||
PlusCircleFilled,
|
||||
MinusCircleFilled,
|
||||
WarningOutlined,
|
||||
} from "@ant-design/icons";
|
||||
import {Form, Button, InputNumber, Input, Select, Switch, Space} from "antd";
|
||||
import {MinusCircleFilled, PlusCircleFilled, WarningOutlined,} from "@ant-design/icons";
|
||||
import {Button, Form, Input, InputNumber, Select, Space, Switch} from "antd";
|
||||
import {useTranslation} from "react-i18next";
|
||||
|
||||
import {connect} from "react-redux";
|
||||
|
||||
@@ -21,6 +21,7 @@ import LayoutFormRow from "../layout-form-row/layout-form-row.component";
|
||||
import VendorSearchSelect from "../vendor-search-select/vendor-search-select.component";
|
||||
import BillFormLines from "./bill-form.lines.component";
|
||||
import {CalculateBillTotal} from "./bill-form.totals.utility";
|
||||
import InstanceRenderManager from "../../utils/instanceRenderMgr";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop,
|
||||
@@ -68,17 +69,17 @@ export function BillFormComponent({
|
||||
};
|
||||
|
||||
const handleFederalTaxExemptSwitchToggle = (checked) => {
|
||||
// Early gate
|
||||
if (!checked) return;
|
||||
const values = form.getFieldsValue("billlines");
|
||||
// Gate bill lines
|
||||
if (!values?.billlines?.length) return;
|
||||
// Early gate
|
||||
if (!checked) return;
|
||||
const values = form.getFieldsValue("billlines");
|
||||
// Gate bill lines
|
||||
if (!values?.billlines?.length) return;
|
||||
|
||||
const billlines = values.billlines.map((b) => {
|
||||
b.applicable_taxes.federal = false;
|
||||
return b;
|
||||
});
|
||||
form.setFieldsValue({billlines});
|
||||
const billlines = values.billlines.map((b) => {
|
||||
b.applicable_taxes.federal = false;
|
||||
return b;
|
||||
});
|
||||
form.setFieldsValue({ billlines });
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
@@ -368,13 +369,17 @@ export function BillFormComponent({
|
||||
)}
|
||||
</LayoutFormRow>
|
||||
<LayoutFormRow>
|
||||
<Form.Item
|
||||
span={3}
|
||||
label={t("bills.fields.federal_tax_rate")}
|
||||
name="federal_tax_rate"
|
||||
>
|
||||
<CurrencyInput min={0} disabled={disabled}/>
|
||||
</Form.Item>
|
||||
{
|
||||
InstanceRenderManager({imex:
|
||||
<Form.Item
|
||||
span={3}
|
||||
label={t("bills.fields.federal_tax_rate")}
|
||||
name="federal_tax_rate"
|
||||
>
|
||||
<CurrencyInput min={0} disabled={disabled} />
|
||||
</Form.Item> })
|
||||
|
||||
}
|
||||
<Form.Item
|
||||
span={3}
|
||||
label={t("bills.fields.state_tax_rate")}
|
||||
@@ -382,22 +387,26 @@ export function BillFormComponent({
|
||||
>
|
||||
<CurrencyInput min={0} disabled={disabled}/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
span={3}
|
||||
label={t("bills.fields.local_tax_rate")}
|
||||
name="local_tax_rate"
|
||||
>
|
||||
<CurrencyInput min={0}/>
|
||||
</Form.Item>
|
||||
{bodyshop.pbs_serialnumber || bodyshop.cdk_dealerid ? (
|
||||
<Form.Item
|
||||
span={2}
|
||||
label={t("bills.labels.federal_tax_exempt")}
|
||||
name="federal_tax_exempt"
|
||||
>
|
||||
<Switch onChange={handleFederalTaxExemptSwitchToggle}/>
|
||||
</Form.Item>
|
||||
) : null}
|
||||
{
|
||||
InstanceRenderManager({imex: <>
|
||||
<Form.Item
|
||||
span={3}
|
||||
label={t("bills.fields.local_tax_rate")}
|
||||
name="local_tax_rate"
|
||||
>
|
||||
<CurrencyInput min={0} />
|
||||
</Form.Item>
|
||||
{bodyshop.pbs_serialnumber || bodyshop.cdk_dealerid ? (
|
||||
<Form.Item
|
||||
span={2}
|
||||
label={t("bills.labels.federal_tax_exempt")}
|
||||
name="federal_tax_exempt"
|
||||
>
|
||||
<Switch onChange={handleFederalTaxExemptSwitchToggle} />
|
||||
</Form.Item>
|
||||
) : null}
|
||||
</>})
|
||||
}
|
||||
<Form.Item shouldUpdate span={13}>
|
||||
{() => {
|
||||
const values = form.getFieldsValue([
|
||||
@@ -423,21 +432,25 @@ export function BillFormComponent({
|
||||
value={totals.subtotal.toFormat()}
|
||||
precision={2}
|
||||
/>
|
||||
<Statistic
|
||||
title={t("bills.labels.federal_tax")}
|
||||
value={totals.federalTax.toFormat()}
|
||||
precision={2}
|
||||
/>
|
||||
{
|
||||
InstanceRenderManager({imex: <Statistic
|
||||
title={t("bills.labels.federal_tax")}
|
||||
value={totals.federalTax.toFormat()}
|
||||
precision={2}
|
||||
/> })
|
||||
}
|
||||
<Statistic
|
||||
title={t("bills.labels.state_tax")}
|
||||
value={totals.stateTax.toFormat()}
|
||||
precision={2}
|
||||
/>
|
||||
<Statistic
|
||||
title={t("bills.labels.local_tax")}
|
||||
value={totals.localTax.toFormat()}
|
||||
precision={2}
|
||||
/>
|
||||
{
|
||||
InstanceRenderManager({imex: <Statistic
|
||||
title={t("bills.labels.local_tax")}
|
||||
value={totals.localTax.toFormat()}
|
||||
precision={2}
|
||||
/>})
|
||||
}
|
||||
<Statistic
|
||||
title={t("bills.labels.entered_total")}
|
||||
value={totals.enteredTotal.toFormat()}
|
||||
|
||||
@@ -1,15 +1,27 @@
|
||||
import {DeleteFilled, DollarCircleFilled} from "@ant-design/icons";
|
||||
import {useSplitTreatments} from "@splitsoftware/splitio-react";
|
||||
import {Button, Form, Input, InputNumber, Select, Space, Switch, Table, Tooltip,} from "antd";
|
||||
import { DeleteFilled, DollarCircleFilled } from "@ant-design/icons";
|
||||
import { useSplitTreatments } from "@splitsoftware/splitio-react";
|
||||
import {
|
||||
Button,
|
||||
Checkbox,
|
||||
Form,
|
||||
Input,
|
||||
InputNumber,
|
||||
Select,
|
||||
Space,
|
||||
Switch,
|
||||
Table,
|
||||
Tooltip,
|
||||
} from "antd";
|
||||
import React from "react";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import {connect} from "react-redux";
|
||||
import {createStructuredSelector} from "reselect";
|
||||
import {selectBodyshop} from "../../redux/user/user.selectors";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
import CiecaSelect from "../../utils/Ciecaselect";
|
||||
import BillLineSearchSelect from "../bill-line-search-select/bill-line-search-select.component";
|
||||
import BilllineAddInventory from "../billline-add-inventory/billline-add-inventory.component";
|
||||
import CurrencyInput from "../form-items-formatted/currency-form-item.component";
|
||||
import InstanceRenderManager from "../../utils/instanceRenderMgr";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
//currentUser: selectCurrentUser
|
||||
@@ -20,25 +32,26 @@ const mapDispatchToProps = (dispatch) => ({
|
||||
});
|
||||
|
||||
export function BillEnterModalLinesComponent({
|
||||
bodyshop,
|
||||
disabled,
|
||||
lineData,
|
||||
discount,
|
||||
form,
|
||||
responsibilityCenters,
|
||||
billEdit,
|
||||
billid,
|
||||
}) {
|
||||
const {t} = useTranslation();
|
||||
const {setFieldsValue, getFieldsValue, getFieldValue} = form;
|
||||
bodyshop,
|
||||
disabled,
|
||||
lineData,
|
||||
discount,
|
||||
form,
|
||||
responsibilityCenters,
|
||||
billEdit,
|
||||
billid,
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const { setFieldsValue, getFieldsValue, getFieldValue } = form;
|
||||
|
||||
const {treatments: {Simple_Inventory}} = useSplitTreatments({
|
||||
const {
|
||||
treatments: { Simple_Inventory, Enhanced_Payroll },
|
||||
} = useSplitTreatments({
|
||||
attributes: {},
|
||||
names: ["Simple_Inventory"],
|
||||
names: ["Simple_Inventory", "Enhanced_Payroll"],
|
||||
splitKey: bodyshop && bodyshop.imexshopid,
|
||||
});
|
||||
|
||||
|
||||
const columns = (remove) => {
|
||||
return [
|
||||
{
|
||||
@@ -75,34 +88,39 @@ export function BillEnterModalLinesComponent({
|
||||
<BillLineSearchSelect
|
||||
disabled={disabled}
|
||||
options={lineData}
|
||||
style={{width: "100%", minWidth: "10rem"}}
|
||||
allowRemoved={form.getFieldValue("is_credit_memo") || false}
|
||||
style={{ width: "100%", minWidth: "10rem" }}
|
||||
allowRemoved={
|
||||
form.getFieldValue("is_credit_memo") || false
|
||||
}
|
||||
onSelect={(value, opt) => {
|
||||
setFieldsValue({
|
||||
billlines: getFieldsValue(["billlines"]).billlines.map(
|
||||
(item, idx) => {
|
||||
if (idx === index) {
|
||||
return {
|
||||
...item,
|
||||
line_desc: opt.line_desc,
|
||||
quantity: opt.part_qty || 1,
|
||||
actual_price: opt.cost,
|
||||
cost_center: opt.part_type
|
||||
? bodyshop.pbs_serialnumber || bodyshop.cdk_dealerid
|
||||
? opt.part_type !== "PAE"
|
||||
? opt.part_type
|
||||
: null
|
||||
: responsibilityCenters.defaults &&
|
||||
(responsibilityCenters.defaults.costs[
|
||||
opt.part_type
|
||||
] ||
|
||||
null)
|
||||
: null,
|
||||
};
|
||||
}
|
||||
return item;
|
||||
billlines: getFieldsValue([
|
||||
"billlines",
|
||||
]).billlines.map((item, idx) => {
|
||||
if (idx === index) {
|
||||
return {
|
||||
...item,
|
||||
line_desc: opt.line_desc,
|
||||
quantity: opt.part_qty || 1,
|
||||
actual_price: opt.cost,
|
||||
original_actual_price: opt.cost,
|
||||
cost_center: opt.part_type
|
||||
? bodyshop.pbs_serialnumber ||
|
||||
bodyshop.cdk_dealerid
|
||||
? opt.part_type !== "PAE"
|
||||
? opt.part_type
|
||||
: null
|
||||
: responsibilityCenters.defaults &&
|
||||
(responsibilityCenters
|
||||
.defaults.costs[
|
||||
opt.part_type
|
||||
] ||
|
||||
null)
|
||||
: null,
|
||||
};
|
||||
}
|
||||
),
|
||||
return item;
|
||||
}),
|
||||
});
|
||||
}}
|
||||
/>
|
||||
@@ -126,7 +144,7 @@ export function BillEnterModalLinesComponent({
|
||||
],
|
||||
};
|
||||
},
|
||||
formInput: (record, index) => <Input disabled={disabled}/>,
|
||||
formInput: (record, index) => <Input disabled={disabled} />,
|
||||
},
|
||||
{
|
||||
title: t("billlines.fields.quantity"),
|
||||
@@ -143,19 +161,24 @@ export function BillEnterModalLinesComponent({
|
||||
required: true,
|
||||
//message: t("general.validation.required"),
|
||||
},
|
||||
({getFieldValue}) => ({
|
||||
({ getFieldValue }) => ({
|
||||
validator(rule, value) {
|
||||
if (
|
||||
value &&
|
||||
getFieldValue("billlines")[field.fieldKey]?.inventories
|
||||
?.length > value
|
||||
getFieldValue("billlines")[
|
||||
field.fieldKey
|
||||
]?.inventories?.length > value
|
||||
) {
|
||||
return Promise.reject(
|
||||
t("bills.validation.inventoryquantity", {
|
||||
number:
|
||||
getFieldValue("billlines")[field.fieldKey]
|
||||
?.inventories?.length,
|
||||
})
|
||||
t(
|
||||
"bills.validation.inventoryquantity",
|
||||
{
|
||||
number: getFieldValue(
|
||||
"billlines"
|
||||
)[field.fieldKey]
|
||||
?.inventories?.length,
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
return Promise.resolve();
|
||||
@@ -165,7 +188,7 @@ export function BillEnterModalLinesComponent({
|
||||
};
|
||||
},
|
||||
formInput: (record, index) => (
|
||||
<InputNumber precision={0} min={1} disabled={disabled}/>
|
||||
<InputNumber precision={0} min={1} disabled={disabled} />
|
||||
),
|
||||
},
|
||||
{
|
||||
@@ -192,27 +215,87 @@ export function BillEnterModalLinesComponent({
|
||||
disabled={disabled}
|
||||
onBlur={(e) => {
|
||||
setFieldsValue({
|
||||
billlines: getFieldsValue("billlines").billlines.map(
|
||||
(item, idx) => {
|
||||
if (idx === index) {
|
||||
return {
|
||||
...item,
|
||||
actual_cost: !!item.actual_cost
|
||||
? item.actual_cost
|
||||
: Math.round(
|
||||
(parseFloat(e.target.value) * (1 - discount) +
|
||||
Number.EPSILON) *
|
||||
100
|
||||
) / 100,
|
||||
};
|
||||
}
|
||||
return item;
|
||||
billlines: getFieldsValue(
|
||||
"billlines"
|
||||
).billlines.map((item, idx) => {
|
||||
if (idx === index) {
|
||||
return {
|
||||
...item,
|
||||
actual_cost: !!item.actual_cost
|
||||
? item.actual_cost
|
||||
: Math.round(
|
||||
(parseFloat(
|
||||
e.target.value
|
||||
) *
|
||||
(1 - discount) +
|
||||
Number.EPSILON) *
|
||||
100
|
||||
) / 100,
|
||||
};
|
||||
}
|
||||
),
|
||||
return item;
|
||||
}),
|
||||
});
|
||||
}}
|
||||
/>
|
||||
),
|
||||
additional: (record, index) =>
|
||||
InstanceRenderManager({
|
||||
rome: (
|
||||
<Form.Item
|
||||
dependencies={[
|
||||
"billlines",
|
||||
record.name,
|
||||
"actual_price",
|
||||
]}
|
||||
noStyle
|
||||
>
|
||||
{() => {
|
||||
const billLine = getFieldValue([
|
||||
"billlines",
|
||||
record.name,
|
||||
]);
|
||||
const jobLine = lineData.find(
|
||||
(line) =>
|
||||
line.id === billLine?.joblineid
|
||||
);
|
||||
|
||||
if (
|
||||
!billEdit &&
|
||||
billLine &&
|
||||
jobLine &&
|
||||
billLine?.actual_price !==
|
||||
jobLine?.act_price
|
||||
) {
|
||||
return (
|
||||
<Space size="small">
|
||||
<Form.Item
|
||||
noStyle
|
||||
label={t(
|
||||
"joblines.fields.create_ppc"
|
||||
)}
|
||||
key={`${index}ppc`}
|
||||
valuePropName="checked"
|
||||
name={[
|
||||
record.name,
|
||||
"create_ppc",
|
||||
]}
|
||||
>
|
||||
<Checkbox />
|
||||
</Form.Item>
|
||||
{t(
|
||||
"joblines.fields.create_ppc"
|
||||
)}
|
||||
</Space>
|
||||
);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}}
|
||||
</Form.Item>
|
||||
),
|
||||
//Do not need to set for promanager as it will default to Rome.
|
||||
}),
|
||||
},
|
||||
{
|
||||
title: t("billlines.fields.actual_cost"),
|
||||
@@ -241,17 +324,30 @@ export function BillEnterModalLinesComponent({
|
||||
addonAfter={
|
||||
<Form.Item shouldUpdate noStyle>
|
||||
{() => {
|
||||
const line = getFieldsValue(["billlines"]).billlines[index];
|
||||
const line = getFieldsValue(["billlines"])
|
||||
.billlines[index];
|
||||
if (!!!line) return null;
|
||||
let lineDiscount = 1 - line.actual_cost / line.actual_price;
|
||||
let lineDiscount =
|
||||
1 -
|
||||
line.actual_cost / line.actual_price;
|
||||
if (isNaN(lineDiscount)) lineDiscount = 0;
|
||||
return (
|
||||
<Tooltip title={`${(lineDiscount * 100).toFixed(2) || 0}%`}>
|
||||
<Tooltip
|
||||
title={`${
|
||||
(lineDiscount * 100).toFixed(
|
||||
2
|
||||
) || 0
|
||||
}%`}
|
||||
>
|
||||
<DollarCircleFilled
|
||||
style={{
|
||||
color:
|
||||
Math.abs(lineDiscount - discount) > 0.005
|
||||
? lineDiscount > discount
|
||||
Math.abs(
|
||||
lineDiscount -
|
||||
discount
|
||||
) > 0.005
|
||||
? lineDiscount >
|
||||
discount
|
||||
? "orange"
|
||||
: "red"
|
||||
: "green",
|
||||
@@ -307,40 +403,48 @@ export function BillEnterModalLinesComponent({
|
||||
};
|
||||
},
|
||||
formInput: (record, index) => (
|
||||
<Select showSearch style={{minWidth: "3rem"}} disabled={disabled}>
|
||||
<Select
|
||||
showSearch
|
||||
style={{ minWidth: "3rem" }}
|
||||
disabled={disabled}
|
||||
>
|
||||
{bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber
|
||||
? CiecaSelect(true, false)
|
||||
: responsibilityCenters.costs.map((item) => (
|
||||
<Select.Option key={item.name}>{item.name}</Select.Option>
|
||||
))}
|
||||
<Select.Option key={item.name}>
|
||||
{item.name}
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
),
|
||||
},
|
||||
...(billEdit
|
||||
? []
|
||||
: [
|
||||
{
|
||||
title: t("billlines.fields.location"),
|
||||
dataIndex: "location",
|
||||
editable: true,
|
||||
label: t("billlines.fields.location"),
|
||||
formItemProps: (field) => {
|
||||
return {
|
||||
key: `${field.index}location`,
|
||||
name: [field.name, "location"],
|
||||
};
|
||||
},
|
||||
formInput: (record, index) => (
|
||||
<Select disabled={disabled}>
|
||||
{bodyshop.md_parts_locations.map((loc, idx) => (
|
||||
<Select.Option key={idx} value={loc}>
|
||||
{loc}
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
),
|
||||
},
|
||||
]),
|
||||
{
|
||||
title: t("billlines.fields.location"),
|
||||
dataIndex: "location",
|
||||
editable: true,
|
||||
label: t("billlines.fields.location"),
|
||||
formItemProps: (field) => {
|
||||
return {
|
||||
key: `${field.index}location`,
|
||||
name: [field.name, "location"],
|
||||
};
|
||||
},
|
||||
formInput: (record, index) => (
|
||||
<Select disabled={disabled}>
|
||||
{bodyshop.md_parts_locations.map(
|
||||
(loc, idx) => (
|
||||
<Select.Option key={idx} value={loc}>
|
||||
{loc}
|
||||
</Select.Option>
|
||||
)
|
||||
)}
|
||||
</Select>
|
||||
),
|
||||
},
|
||||
]),
|
||||
{
|
||||
title: t("billlines.labels.deductedfromlbr"),
|
||||
dataIndex: "deductedfromlbr",
|
||||
@@ -352,9 +456,13 @@ export function BillEnterModalLinesComponent({
|
||||
name: [field.name, "deductedfromlbr"],
|
||||
};
|
||||
},
|
||||
formInput: (record, index) => <Switch disabled={disabled}/>,
|
||||
formInput: (record, index) => <Switch disabled={disabled} />,
|
||||
additional: (record, index) => (
|
||||
<Form.Item shouldUpdate style={{display: "inline-block"}}>
|
||||
<Form.Item
|
||||
shouldUpdate
|
||||
noStyle
|
||||
style={{ display: "inline-block" }}
|
||||
>
|
||||
{() => {
|
||||
const price = getFieldValue([
|
||||
"billlines",
|
||||
@@ -369,81 +477,201 @@ export function BillEnterModalLinesComponent({
|
||||
"rate",
|
||||
]);
|
||||
|
||||
if (getFieldValue(["billlines", record.name, "deductedfromlbr"]))
|
||||
const billline = getFieldValue([
|
||||
"billlines",
|
||||
record.name,
|
||||
]);
|
||||
|
||||
const jobline = lineData.find(
|
||||
(line) => line.id === billline?.joblineid
|
||||
);
|
||||
|
||||
const employeeTeamName =
|
||||
bodyshop.employee_teams.find(
|
||||
(team) => team.id === jobline?.assigned_team
|
||||
);
|
||||
|
||||
if (
|
||||
getFieldValue([
|
||||
"billlines",
|
||||
record.name,
|
||||
"deductedfromlbr",
|
||||
])
|
||||
)
|
||||
return (
|
||||
<div>
|
||||
{Enhanced_Payroll.treatment === "on" ? (
|
||||
<Space>
|
||||
{t(
|
||||
"joblines.fields.assigned_team",
|
||||
{
|
||||
name: employeeTeamName?.name,
|
||||
}
|
||||
)}
|
||||
{`${
|
||||
jobline.mod_lb_hrs
|
||||
} units/${t(
|
||||
`joblines.fields.lbr_types.${jobline.mod_lbr_ty}`
|
||||
)}`}
|
||||
</Space>
|
||||
) : null}
|
||||
|
||||
<Form.Item
|
||||
label={t("joblines.fields.mod_lbr_ty")}
|
||||
label={t(
|
||||
"joblines.fields.mod_lbr_ty"
|
||||
)}
|
||||
key={`${index}modlbrty`}
|
||||
initialValue={
|
||||
jobline
|
||||
? jobline.mod_lbr_ty
|
||||
: null
|
||||
}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
//message: t("general.validation.required"),
|
||||
},
|
||||
]}
|
||||
name={[record.name, "lbr_adjustment", "mod_lbr_ty"]}
|
||||
name={[
|
||||
record.name,
|
||||
"lbr_adjustment",
|
||||
"mod_lbr_ty",
|
||||
]}
|
||||
>
|
||||
<Select allowClear>
|
||||
<Select.Option value="LAA">
|
||||
{t("joblines.fields.lbr_types.LAA")}
|
||||
{t(
|
||||
"joblines.fields.lbr_types.LAA"
|
||||
)}
|
||||
</Select.Option>
|
||||
<Select.Option value="LAB">
|
||||
{t("joblines.fields.lbr_types.LAB")}
|
||||
{t(
|
||||
"joblines.fields.lbr_types.LAB"
|
||||
)}
|
||||
</Select.Option>
|
||||
<Select.Option value="LAD">
|
||||
{t("joblines.fields.lbr_types.LAD")}
|
||||
{t(
|
||||
"joblines.fields.lbr_types.LAD"
|
||||
)}
|
||||
</Select.Option>
|
||||
<Select.Option value="LAE">
|
||||
{t("joblines.fields.lbr_types.LAE")}
|
||||
{t(
|
||||
"joblines.fields.lbr_types.LAE"
|
||||
)}
|
||||
</Select.Option>
|
||||
<Select.Option value="LAF">
|
||||
{t("joblines.fields.lbr_types.LAF")}
|
||||
{t(
|
||||
"joblines.fields.lbr_types.LAF"
|
||||
)}
|
||||
</Select.Option>
|
||||
<Select.Option value="LAG">
|
||||
{t("joblines.fields.lbr_types.LAG")}
|
||||
{t(
|
||||
"joblines.fields.lbr_types.LAG"
|
||||
)}
|
||||
</Select.Option>
|
||||
<Select.Option value="LAM">
|
||||
{t("joblines.fields.lbr_types.LAM")}
|
||||
{t(
|
||||
"joblines.fields.lbr_types.LAM"
|
||||
)}
|
||||
</Select.Option>
|
||||
<Select.Option value="LAR">
|
||||
{t("joblines.fields.lbr_types.LAR")}
|
||||
{t(
|
||||
"joblines.fields.lbr_types.LAR"
|
||||
)}
|
||||
</Select.Option>
|
||||
<Select.Option value="LAS">
|
||||
{t("joblines.fields.lbr_types.LAS")}
|
||||
{t(
|
||||
"joblines.fields.lbr_types.LAS"
|
||||
)}
|
||||
</Select.Option>
|
||||
<Select.Option value="LAU">
|
||||
{t("joblines.fields.lbr_types.LAU")}
|
||||
{t(
|
||||
"joblines.fields.lbr_types.LAU"
|
||||
)}
|
||||
</Select.Option>
|
||||
<Select.Option value="LA1">
|
||||
{t("joblines.fields.lbr_types.LA1")}
|
||||
{t(
|
||||
"joblines.fields.lbr_types.LA1"
|
||||
)}
|
||||
</Select.Option>
|
||||
<Select.Option value="LA2">
|
||||
{t("joblines.fields.lbr_types.LA2")}
|
||||
{t(
|
||||
"joblines.fields.lbr_types.LA2"
|
||||
)}
|
||||
</Select.Option>
|
||||
<Select.Option value="LA3">
|
||||
{t("joblines.fields.lbr_types.LA3")}
|
||||
{t(
|
||||
"joblines.fields.lbr_types.LA3"
|
||||
)}
|
||||
</Select.Option>
|
||||
<Select.Option value="LA4">
|
||||
{t("joblines.fields.lbr_types.LA4")}
|
||||
{t(
|
||||
"joblines.fields.lbr_types.LA4"
|
||||
)}
|
||||
</Select.Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.labels.adjustmentrate")}
|
||||
name={[record.name, "lbr_adjustment", "rate"]}
|
||||
initialValue={bodyshop.default_adjustment_rate}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
//message: t("general.validation.required"),
|
||||
},
|
||||
]}
|
||||
>
|
||||
<InputNumber precision={2} min={0.01}/>
|
||||
</Form.Item>
|
||||
{price &&
|
||||
adjustmentRate &&
|
||||
`${(price / adjustmentRate).toFixed(1)} hrs`}
|
||||
{Enhanced_Payroll.treatment === "on" ? (
|
||||
<Form.Item
|
||||
label={t(
|
||||
"billlines.labels.mod_lbr_adjustment"
|
||||
)}
|
||||
name={[
|
||||
record.name,
|
||||
"lbr_adjustment",
|
||||
"mod_lb_hrs",
|
||||
]}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
//message: t("general.validation.required"),
|
||||
},
|
||||
]}
|
||||
>
|
||||
<InputNumber
|
||||
precision={5}
|
||||
min={0.01}
|
||||
max={
|
||||
jobline
|
||||
? jobline.mod_lb_hrs
|
||||
: 0
|
||||
}
|
||||
/>
|
||||
</Form.Item>
|
||||
) : (
|
||||
<Form.Item
|
||||
label={t(
|
||||
"jobs.labels.adjustmentrate"
|
||||
)}
|
||||
name={[
|
||||
record.name,
|
||||
"lbr_adjustment",
|
||||
"rate",
|
||||
]}
|
||||
initialValue={
|
||||
bodyshop.default_adjustment_rate
|
||||
}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
//message: t("general.validation.required"),
|
||||
},
|
||||
]}
|
||||
>
|
||||
<InputNumber
|
||||
precision={2}
|
||||
min={0.01}
|
||||
/>
|
||||
</Form.Item>
|
||||
)}
|
||||
|
||||
<Space>
|
||||
{price &&
|
||||
adjustmentRate &&
|
||||
`${(
|
||||
price / adjustmentRate
|
||||
).toFixed(1)} hrs`}
|
||||
</Space>
|
||||
</div>
|
||||
);
|
||||
return <></>;
|
||||
@@ -451,22 +679,33 @@ export function BillEnterModalLinesComponent({
|
||||
</Form.Item>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: t("billlines.fields.federal_tax_applicable"),
|
||||
dataIndex: "applicable_taxes.federal",
|
||||
editable: true,
|
||||
|
||||
formItemProps: (field) => {
|
||||
return {
|
||||
key: `${field.index}fedtax`,
|
||||
valuePropName: "checked",
|
||||
initialValue:
|
||||
form.getFieldValue("federal_tax_exempt") === true ? false : true,
|
||||
name: [field.name, "applicable_taxes", "federal"],
|
||||
};
|
||||
},
|
||||
formInput: (record, index) => <Switch disabled={disabled}/>,
|
||||
},
|
||||
...InstanceRenderManager({
|
||||
imex: [
|
||||
{
|
||||
title: t("billlines.fields.federal_tax_applicable"),
|
||||
dataIndex: "applicable_taxes.federal",
|
||||
editable: true,
|
||||
|
||||
formItemProps: (field) => {
|
||||
return {
|
||||
key: `${field.index}fedtax`,
|
||||
valuePropName: "checked",
|
||||
// initialValue: true,
|
||||
name: [
|
||||
field.name,
|
||||
"applicable_taxes",
|
||||
"federal",
|
||||
],
|
||||
};
|
||||
},
|
||||
formInput: (record, index) => (
|
||||
<Switch disabled={disabled} />
|
||||
),
|
||||
},
|
||||
],
|
||||
}),
|
||||
|
||||
{
|
||||
title: t("billlines.fields.state_tax_applicable"),
|
||||
dataIndex: "applicable_taxes.state",
|
||||
@@ -479,22 +718,29 @@ export function BillEnterModalLinesComponent({
|
||||
name: [field.name, "applicable_taxes", "state"],
|
||||
};
|
||||
},
|
||||
formInput: (record, index) => <Switch disabled={disabled}/>,
|
||||
formInput: (record, index) => <Switch disabled={disabled} />,
|
||||
},
|
||||
{
|
||||
title: t("billlines.fields.local_tax_applicable"),
|
||||
dataIndex: "applicable_taxes.local",
|
||||
editable: true,
|
||||
|
||||
formItemProps: (field) => {
|
||||
return {
|
||||
key: `${field.index}localtax`,
|
||||
valuePropName: "checked",
|
||||
name: [field.name, "applicable_taxes", "local"],
|
||||
};
|
||||
},
|
||||
formInput: (record, index) => <Switch disabled={disabled}/>,
|
||||
},
|
||||
...InstanceRenderManager({
|
||||
imex: [
|
||||
{
|
||||
title: t("billlines.fields.local_tax_applicable"),
|
||||
dataIndex: "applicable_taxes.local",
|
||||
editable: true,
|
||||
|
||||
formItemProps: (field) => {
|
||||
return {
|
||||
key: `${field.index}localtax`,
|
||||
valuePropName: "checked",
|
||||
name: [field.name, "applicable_taxes", "local"],
|
||||
};
|
||||
},
|
||||
formInput: (record, index) => (
|
||||
<Switch disabled={disabled} />
|
||||
),
|
||||
},
|
||||
],
|
||||
}),
|
||||
{
|
||||
title: t("general.labels.actions"),
|
||||
|
||||
@@ -506,12 +752,13 @@ export function BillEnterModalLinesComponent({
|
||||
<Button
|
||||
disabled={
|
||||
disabled ||
|
||||
getFieldValue("billlines")[record.fieldKey]?.inventories
|
||||
?.length > 0
|
||||
getFieldValue("billlines")[
|
||||
record.fieldKey
|
||||
]?.inventories?.length > 0
|
||||
}
|
||||
onClick={() => remove(record.name)}
|
||||
>
|
||||
<DeleteFilled/>
|
||||
<DeleteFilled />
|
||||
</Button>
|
||||
{Simple_Inventory.treatment === "on" && (
|
||||
<BilllineAddInventory
|
||||
@@ -520,7 +767,11 @@ export function BillEnterModalLinesComponent({
|
||||
form.isFieldsTouched() ||
|
||||
form.getFieldValue("is_credit_memo")
|
||||
}
|
||||
billline={getFieldValue("billlines")[record.fieldKey]}
|
||||
billline={
|
||||
getFieldValue("billlines")[
|
||||
record.fieldKey
|
||||
]
|
||||
}
|
||||
jobid={getFieldValue("jobid")}
|
||||
/>
|
||||
)}
|
||||
@@ -563,7 +814,7 @@ export function BillEnterModalLinesComponent({
|
||||
},
|
||||
]}
|
||||
>
|
||||
{(fields, {add, remove, move}) => {
|
||||
{(fields, { add, remove, move }) => {
|
||||
return (
|
||||
<>
|
||||
<Table
|
||||
@@ -576,7 +827,7 @@ export function BillEnterModalLinesComponent({
|
||||
bordered
|
||||
dataSource={fields}
|
||||
columns={mergedColumns(remove)}
|
||||
scroll={{x: true}}
|
||||
scroll={{ x: true }}
|
||||
pagination={false}
|
||||
rowClassName="editable-row"
|
||||
/>
|
||||
@@ -586,7 +837,7 @@ export function BillEnterModalLinesComponent({
|
||||
onClick={() => {
|
||||
add();
|
||||
}}
|
||||
style={{width: "100%"}}
|
||||
style={{ width: "100%" }}
|
||||
>
|
||||
{t("billlines.actions.newline")}
|
||||
</Button>
|
||||
@@ -604,31 +855,32 @@ export default connect(
|
||||
)(BillEnterModalLinesComponent);
|
||||
|
||||
const EditableCell = ({
|
||||
dataIndex,
|
||||
title,
|
||||
inputType,
|
||||
record,
|
||||
index,
|
||||
children,
|
||||
formInput,
|
||||
formItemProps,
|
||||
additional,
|
||||
wrapper,
|
||||
...restProps
|
||||
}) => {
|
||||
dataIndex,
|
||||
title,
|
||||
inputType,
|
||||
record,
|
||||
index,
|
||||
children,
|
||||
formInput,
|
||||
formItemProps,
|
||||
additional,
|
||||
wrapper,
|
||||
...restProps
|
||||
}) => {
|
||||
if (additional)
|
||||
return (
|
||||
<td {...restProps}>
|
||||
<Space size="small">
|
||||
<div size="small">
|
||||
<Form.Item
|
||||
name={dataIndex}
|
||||
labelCol={{span: 0}}
|
||||
labelCol={{ span: 0 }}
|
||||
{...(formItemProps && formItemProps(record))}
|
||||
>
|
||||
{(formInput && formInput(record, record.name)) || children}
|
||||
{(formInput && formInput(record, record.name)) ||
|
||||
children}
|
||||
</Form.Item>
|
||||
{additional && additional(record, record.name)}
|
||||
</Space>
|
||||
</div>
|
||||
</td>
|
||||
);
|
||||
if (wrapper)
|
||||
@@ -636,11 +888,12 @@ const EditableCell = ({
|
||||
<wrapper>
|
||||
<td {...restProps}>
|
||||
<Form.Item
|
||||
labelCol={{span: 0}}
|
||||
labelCol={{ span: 0 }}
|
||||
name={dataIndex}
|
||||
{...(formItemProps && formItemProps(record))}
|
||||
>
|
||||
{(formInput && formInput(record, record.name)) || children}
|
||||
{(formInput && formInput(record, record.name)) ||
|
||||
children}
|
||||
</Form.Item>
|
||||
</td>
|
||||
</wrapper>
|
||||
@@ -648,7 +901,7 @@ const EditableCell = ({
|
||||
return (
|
||||
<td {...restProps}>
|
||||
<Form.Item
|
||||
labelCol={{span: 0}}
|
||||
labelCol={{ span: 0 }}
|
||||
name={dataIndex}
|
||||
{...(formItemProps && formItemProps(record))}
|
||||
>
|
||||
|
||||